1 // SPDX-License-Identifier: GPL-2.0-only 2 #include <linux/export.h> 3 #include <linux/slab.h> 4 #include <linux/regset.h> 5 6 static 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->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->get(target, regset, 0, size, p, NULL); 24 if (unlikely(res < 0)) { 25 kfree(to_free); 26 return res; 27 } 28 *data = p; 29 if (regset->get_size) { // arm64-only kludge, will go away 30 unsigned max_size = regset->get_size(target, regset); 31 if (size > max_size) 32 size = max_size; 33 } 34 return size; 35 } 36 37 int regset_get(struct task_struct *target, 38 const struct user_regset *regset, 39 unsigned int size, 40 void *data) 41 { 42 return __regset_get(target, regset, size, &data); 43 } 44 EXPORT_SYMBOL(regset_get); 45 46 int regset_get_alloc(struct task_struct *target, 47 const struct user_regset *regset, 48 unsigned int size, 49 void **data) 50 { 51 *data = NULL; 52 return __regset_get(target, regset, size, data); 53 } 54 EXPORT_SYMBOL(regset_get_alloc); 55