Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 #include <linux/export.h>
0003 #include <linux/slab.h>
0004 #include <linux/regset.h>
0005 
0006 static int __regset_get(struct task_struct *target,
0007             const struct user_regset *regset,
0008             unsigned int size,
0009             void **data)
0010 {
0011     void *p = *data, *to_free = NULL;
0012     int res;
0013 
0014     if (!regset->regset_get)
0015         return -EOPNOTSUPP;
0016     if (size > regset->n * regset->size)
0017         size = regset->n * regset->size;
0018     if (!p) {
0019         to_free = p = kzalloc(size, GFP_KERNEL);
0020         if (!p)
0021             return -ENOMEM;
0022     }
0023     res = regset->regset_get(target, regset,
0024                (struct membuf){.p = p, .left = size});
0025     if (res < 0) {
0026         kfree(to_free);
0027         return res;
0028     }
0029     *data = p;
0030     return size - res;
0031 }
0032 
0033 int regset_get(struct task_struct *target,
0034            const struct user_regset *regset,
0035            unsigned int size,
0036            void *data)
0037 {
0038     return __regset_get(target, regset, size, &data);
0039 }
0040 EXPORT_SYMBOL(regset_get);
0041 
0042 int regset_get_alloc(struct task_struct *target,
0043              const struct user_regset *regset,
0044              unsigned int size,
0045              void **data)
0046 {
0047     *data = NULL;
0048     return __regset_get(target, regset, size, data);
0049 }
0050 EXPORT_SYMBOL(regset_get_alloc);
0051 
0052 /**
0053  * copy_regset_to_user - fetch a thread's user_regset data into user memory
0054  * @target: thread to be examined
0055  * @view:   &struct user_regset_view describing user thread machine state
0056  * @setno:  index in @view->regsets
0057  * @offset: offset into the regset data, in bytes
0058  * @size:   amount of data to copy, in bytes
0059  * @data:   user-mode pointer to copy into
0060  */
0061 int copy_regset_to_user(struct task_struct *target,
0062             const struct user_regset_view *view,
0063             unsigned int setno,
0064             unsigned int offset, unsigned int size,
0065             void __user *data)
0066 {
0067     const struct user_regset *regset = &view->regsets[setno];
0068     void *buf;
0069     int ret;
0070 
0071     ret = regset_get_alloc(target, regset, size, &buf);
0072     if (ret > 0)
0073         ret = copy_to_user(data, buf, ret) ? -EFAULT : 0;
0074     kfree(buf);
0075     return ret;
0076 }