mirror of https://gitee.com/openkylin/linux.git
s390/uaccess: fix __put_get_user_asm define
The __put_get_user_asm defines an inline assmembly which makes use of the asm register construct. The parameters passed to that define may also contain function calls. It is a gcc restriction that between register asm statements and the use of any such annotated variables function calls may clobber the register / variable contents. Or in other words: gcc would generate broken code. This can be achieved e.g. with the following code: get_user(x, func() ? a : b); where the call of func would clobber register zero which is used by the __put_get_user_asm define. To avoid this add two static inline functions which don't have these side effects. Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
This commit is contained in:
parent
109ab95471
commit
dc4aace160
|
@ -151,8 +151,65 @@ unsigned long __must_check __copy_to_user(void __user *to, const void *from,
|
|||
__rc; \
|
||||
})
|
||||
|
||||
#define __put_user_fn(x, ptr, size) __put_get_user_asm(ptr, x, size, 0x810000UL)
|
||||
#define __get_user_fn(x, ptr, size) __put_get_user_asm(x, ptr, size, 0x81UL)
|
||||
static inline int __put_user_fn(void *x, void __user *ptr, unsigned long size)
|
||||
{
|
||||
unsigned long spec = 0x810000UL;
|
||||
int rc;
|
||||
|
||||
switch (size) {
|
||||
case 1:
|
||||
rc = __put_get_user_asm((unsigned char __user *)ptr,
|
||||
(unsigned char *)x,
|
||||
size, spec);
|
||||
break;
|
||||
case 2:
|
||||
rc = __put_get_user_asm((unsigned short __user *)ptr,
|
||||
(unsigned short *)x,
|
||||
size, spec);
|
||||
break;
|
||||
case 4:
|
||||
rc = __put_get_user_asm((unsigned int __user *)ptr,
|
||||
(unsigned int *)x,
|
||||
size, spec);
|
||||
break;
|
||||
case 8:
|
||||
rc = __put_get_user_asm((unsigned long __user *)ptr,
|
||||
(unsigned long *)x,
|
||||
size, spec);
|
||||
break;
|
||||
};
|
||||
return rc;
|
||||
}
|
||||
|
||||
static inline int __get_user_fn(void *x, const void __user *ptr, unsigned long size)
|
||||
{
|
||||
unsigned long spec = 0x81UL;
|
||||
int rc;
|
||||
|
||||
switch (size) {
|
||||
case 1:
|
||||
rc = __put_get_user_asm((unsigned char *)x,
|
||||
(unsigned char __user *)ptr,
|
||||
size, spec);
|
||||
break;
|
||||
case 2:
|
||||
rc = __put_get_user_asm((unsigned short *)x,
|
||||
(unsigned short __user *)ptr,
|
||||
size, spec);
|
||||
break;
|
||||
case 4:
|
||||
rc = __put_get_user_asm((unsigned int *)x,
|
||||
(unsigned int __user *)ptr,
|
||||
size, spec);
|
||||
break;
|
||||
case 8:
|
||||
rc = __put_get_user_asm((unsigned long *)x,
|
||||
(unsigned long __user *)ptr,
|
||||
size, spec);
|
||||
break;
|
||||
};
|
||||
return rc;
|
||||
}
|
||||
|
||||
#else /* CONFIG_HAVE_MARCH_Z10_FEATURES */
|
||||
|
||||
|
|
Loading…
Reference in New Issue