2020-06-02 02:42:40 +03:00
// SPDX-License-Identifier: GPL-2.0-only
# include <linux/export.h>
# include <linux/slab.h>
# include <linux/regset.h>
static int __regset_get ( struct task_struct * target ,
const struct user_regset * regset ,
unsigned int size ,
void * * data )
{
void * p = * data , * to_free = NULL ;
int res ;
2020-06-16 22:34:20 +03:00
if ( ! regset - > regset_get )
2020-06-02 02:42:40 +03:00
return - EOPNOTSUPP ;
if ( size > regset - > n * regset - > size )
size = regset - > n * regset - > size ;
if ( ! p ) {
to_free = p = kzalloc ( size , GFP_KERNEL ) ;
if ( ! p )
return - ENOMEM ;
}
2020-06-16 22:34:20 +03:00
res = regset - > regset_get ( target , regset ,
( struct membuf ) { . p = p , . left = size } ) ;
if ( res < 0 ) {
2020-06-02 02:42:40 +03:00
kfree ( to_free ) ;
return res ;
}
* data = p ;
2020-06-16 22:34:20 +03:00
return size - res ;
2020-06-02 02:42:40 +03:00
}
int regset_get ( struct task_struct * target ,
const struct user_regset * regset ,
unsigned int size ,
void * data )
{
return __regset_get ( target , regset , size , & data ) ;
}
EXPORT_SYMBOL ( regset_get ) ;
int regset_get_alloc ( struct task_struct * target ,
const struct user_regset * regset ,
unsigned int size ,
void * * data )
{
* data = NULL ;
return __regset_get ( target , regset , size , data ) ;
}
EXPORT_SYMBOL ( regset_get_alloc ) ;
2020-02-17 20:25:14 +03:00
/**
* copy_regset_to_user - fetch a thread ' s user_regset data into user memory
* @ target : thread to be examined
* @ view : & struct user_regset_view describing user thread machine state
* @ setno : index in @ view - > regsets
* @ offset : offset into the regset data , in bytes
* @ size : amount of data to copy , in bytes
* @ data : user - mode pointer to copy into
*/
int copy_regset_to_user ( struct task_struct * target ,
const struct user_regset_view * view ,
unsigned int setno ,
unsigned int offset , unsigned int size ,
void __user * data )
{
const struct user_regset * regset = & view - > regsets [ setno ] ;
void * buf ;
int ret ;
ret = regset_get_alloc ( target , regset , size , & buf ) ;
if ( ret > 0 )
ret = copy_to_user ( data , buf , ret ) ? - EFAULT : 0 ;
kfree ( buf ) ;
return ret ;
}