mirror of https://gitee.com/openkylin/linux.git
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
|
@ -136,6 +136,59 @@ do { \
|
||||||
: "=r" (err) \
|
: "=r" (err) \
|
||||||
: "b" (uaddr), "b" (kaddr), "i" (-EFAULT), "0" (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) \
|
#define __get_user_asm(x, addr, err, op) \
|
||||||
__asm__ __volatile__( \
|
__asm__ __volatile__( \
|
||||||
"1: "op"%U2%X2 %1, %2 # get_user\n" \
|
"1: "op"%U2%X2 %1, %2 # get_user\n" \
|
||||||
|
@ -192,6 +245,8 @@ do { \
|
||||||
goto label; \
|
goto label; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
#endif /* CONFIG_CC_HAS_ASM_GOTO_OUTPUT */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is a type: either unsigned long, if the argument fits into
|
* This is a type: either unsigned long, if the argument fits into
|
||||||
* that type, or otherwise unsigned long long.
|
* that type, or otherwise unsigned long long.
|
||||||
|
|
Loading…
Reference in New Issue