1*b4e9c954SAl Viro // SPDX-License-Identifier: GPL-2.0-only 2*b4e9c954SAl Viro #include <linux/export.h> 3*b4e9c954SAl Viro #include <linux/slab.h> 4*b4e9c954SAl Viro #include <linux/regset.h> 5*b4e9c954SAl Viro 6*b4e9c954SAl Viro static int __regset_get(struct task_struct *target, 7*b4e9c954SAl Viro const struct user_regset *regset, 8*b4e9c954SAl Viro unsigned int size, 9*b4e9c954SAl Viro void **data) 10*b4e9c954SAl Viro { 11*b4e9c954SAl Viro void *p = *data, *to_free = NULL; 12*b4e9c954SAl Viro int res; 13*b4e9c954SAl Viro 14*b4e9c954SAl Viro if (!regset->get) 15*b4e9c954SAl Viro return -EOPNOTSUPP; 16*b4e9c954SAl Viro if (size > regset->n * regset->size) 17*b4e9c954SAl Viro size = regset->n * regset->size; 18*b4e9c954SAl Viro if (!p) { 19*b4e9c954SAl Viro to_free = p = kzalloc(size, GFP_KERNEL); 20*b4e9c954SAl Viro if (!p) 21*b4e9c954SAl Viro return -ENOMEM; 22*b4e9c954SAl Viro } 23*b4e9c954SAl Viro res = regset->get(target, regset, 0, size, p, NULL); 24*b4e9c954SAl Viro if (unlikely(res < 0)) { 25*b4e9c954SAl Viro kfree(to_free); 26*b4e9c954SAl Viro return res; 27*b4e9c954SAl Viro } 28*b4e9c954SAl Viro *data = p; 29*b4e9c954SAl Viro if (regset->get_size) { // arm64-only kludge, will go away 30*b4e9c954SAl Viro unsigned max_size = regset->get_size(target, regset); 31*b4e9c954SAl Viro if (size > max_size) 32*b4e9c954SAl Viro size = max_size; 33*b4e9c954SAl Viro } 34*b4e9c954SAl Viro return size; 35*b4e9c954SAl Viro } 36*b4e9c954SAl Viro 37*b4e9c954SAl Viro int regset_get(struct task_struct *target, 38*b4e9c954SAl Viro const struct user_regset *regset, 39*b4e9c954SAl Viro unsigned int size, 40*b4e9c954SAl Viro void *data) 41*b4e9c954SAl Viro { 42*b4e9c954SAl Viro return __regset_get(target, regset, size, &data); 43*b4e9c954SAl Viro } 44*b4e9c954SAl Viro EXPORT_SYMBOL(regset_get); 45*b4e9c954SAl Viro 46*b4e9c954SAl Viro int regset_get_alloc(struct task_struct *target, 47*b4e9c954SAl Viro const struct user_regset *regset, 48*b4e9c954SAl Viro unsigned int size, 49*b4e9c954SAl Viro void **data) 50*b4e9c954SAl Viro { 51*b4e9c954SAl Viro *data = NULL; 52*b4e9c954SAl Viro return __regset_get(target, regset, size, data); 53*b4e9c954SAl Viro } 54*b4e9c954SAl Viro EXPORT_SYMBOL(regset_get_alloc); 55