mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-12 13:55:32 +00:00
powerpc/uaccess: Use asm goto for get_user when compiler supports it
clang 11 and future GCC are supporting asm goto with outputs. Use it to implement get_user in order to get better generated code. Note that clang requires to set x in the default branch of __get_user_size_goto() otherwise is compliant about x not being initialised :puzzled: Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> Link: https://lore.kernel.org/r/403745b5aaa1b315bb4e8e46c1ba949e77eecec0.1615398265.git.christophe.leroy@csgroup.eu
This commit is contained in:
parent
035785ab28
commit
5cd29b1fd3
1 changed files with 55 additions and 0 deletions
|
@ -136,6 +136,59 @@ do { \
|
|||
: "=r" (err) \
|
||||
: "b" (uaddr), "b" (kaddr), "i" (-EFAULT), "0" (err))
|
||||
|
||||
#ifdef CONFIG_CC_HAS_ASM_GOTO_OUTPUT
|
||||
|
||||
#define __get_user_asm_goto(x, addr, label, op) \
|
||||
asm_volatile_goto( \
|
||||
"1: "op"%U1%X1 %0, %1 # get_user\n" \
|
||||
EX_TABLE(1b, %l2) \
|
||||
: "=r" (x) \
|
||||
: "m"UPD_CONSTR (*addr) \
|
||||
: \
|
||||
: label)
|
||||
|
||||
#ifdef __powerpc64__
|
||||
#define __get_user_asm2_goto(x, addr, label) \
|
||||
__get_user_asm_goto(x, addr, label, "ld")
|
||||
#else /* __powerpc64__ */
|
||||
#define __get_user_asm2_goto(x, addr, label) \
|
||||
asm_volatile_goto( \
|
||||
"1: lwz%X1 %0, %1\n" \
|
||||
"2: lwz%X1 %L0, %L1\n" \
|
||||
EX_TABLE(1b, %l2) \
|
||||
EX_TABLE(2b, %l2) \
|
||||
: "=r" (x) \
|
||||
: "m" (*addr) \
|
||||
: \
|
||||
: label)
|
||||
#endif /* __powerpc64__ */
|
||||
|
||||
#define __get_user_size_goto(x, ptr, size, label) \
|
||||
do { \
|
||||
BUILD_BUG_ON(size > sizeof(x)); \
|
||||
switch (size) { \
|
||||
case 1: __get_user_asm_goto(x, (u8 __user *)ptr, label, "lbz"); break; \
|
||||
case 2: __get_user_asm_goto(x, (u16 __user *)ptr, label, "lhz"); break; \
|
||||
case 4: __get_user_asm_goto(x, (u32 __user *)ptr, label, "lwz"); break; \
|
||||
case 8: __get_user_asm2_goto(x, (u64 __user *)ptr, label); break; \
|
||||
default: x = 0; BUILD_BUG(); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define __get_user_size_allowed(x, ptr, size, retval) \
|
||||
do { \
|
||||
__label__ __gus_failed; \
|
||||
\
|
||||
__get_user_size_goto(x, ptr, size, __gus_failed); \
|
||||
retval = 0; \
|
||||
break; \
|
||||
__gus_failed: \
|
||||
x = 0; \
|
||||
retval = -EFAULT; \
|
||||
} while (0)
|
||||
|
||||
#else /* CONFIG_CC_HAS_ASM_GOTO_OUTPUT */
|
||||
|
||||
#define __get_user_asm(x, addr, err, op) \
|
||||
__asm__ __volatile__( \
|
||||
"1: "op"%U2%X2 %1, %2 # get_user\n" \
|
||||
|
@ -192,6 +245,8 @@ do { \
|
|||
goto label; \
|
||||
} while (0)
|
||||
|
||||
#endif /* CONFIG_CC_HAS_ASM_GOTO_OUTPUT */
|
||||
|
||||
/*
|
||||
* This is a type: either unsigned long, if the argument fits into
|
||||
* that type, or otherwise unsigned long long.
|
||||
|
|
Loading…
Reference in a new issue