linux/kernel/regset.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2#include <linux/export.h>
   3#include <linux/slab.h>
   4#include <linux/regset.h>
   5
   6static int __regset_get(struct task_struct *target,
   7                        const struct user_regset *regset,
   8                        unsigned int size,
   9                        void **data)
  10{
  11        void *p = *data, *to_free = NULL;
  12        int res;
  13
  14        if (!regset->regset_get)
  15                return -EOPNOTSUPP;
  16        if (size > regset->n * regset->size)
  17                size = regset->n * regset->size;
  18        if (!p) {
  19                to_free = p = kzalloc(size, GFP_KERNEL);
  20                if (!p)
  21                        return -ENOMEM;
  22        }
  23        res = regset->regset_get(target, regset,
  24                           (struct membuf){.p = p, .left = size});
  25        if (res < 0) {
  26                kfree(to_free);
  27                return res;
  28        }
  29        *data = p;
  30        return size - res;
  31}
  32
  33int regset_get(struct task_struct *target,
  34               const struct user_regset *regset,
  35               unsigned int size,
  36               void *data)
  37{
  38        return __regset_get(target, regset, size, &data);
  39}
  40EXPORT_SYMBOL(regset_get);
  41
  42int regset_get_alloc(struct task_struct *target,
  43                     const struct user_regset *regset,
  44                     unsigned int size,
  45                     void **data)
  46{
  47        *data = NULL;
  48        return __regset_get(target, regset, size, data);
  49}
  50EXPORT_SYMBOL(regset_get_alloc);
  51
  52/**
  53 * copy_regset_to_user - fetch a thread's user_regset data into user memory
  54 * @target:     thread to be examined
  55 * @view:       &struct user_regset_view describing user thread machine state
  56 * @setno:      index in @view->regsets
  57 * @offset:     offset into the regset data, in bytes
  58 * @size:       amount of data to copy, in bytes
  59 * @data:       user-mode pointer to copy into
  60 */
  61int copy_regset_to_user(struct task_struct *target,
  62                        const struct user_regset_view *view,
  63                        unsigned int setno,
  64                        unsigned int offset, unsigned int size,
  65                        void __user *data)
  66{
  67        const struct user_regset *regset = &view->regsets[setno];
  68        void *buf;
  69        int ret;
  70
  71        ret = regset_get_alloc(target, regset, size, &buf);
  72        if (ret > 0)
  73                ret = copy_to_user(data, buf, ret) ? -EFAULT : 0;
  74        kfree(buf);
  75        return ret;
  76}
  77