Message ID | 20240625040500.1788-5-jszhang@kernel.org (mailing list archive) |
---|---|
State | Changes Requested, archived |
Headers | show |
Series | riscv: uaccess: optimizations | expand |
Hi Jisheng, kernel test robot noticed the following build errors: [auto build test ERROR on linus/master] [also build test ERROR on v6.10-rc6] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/Jisheng-Zhang/riscv-implement-user_access_begin-and-families/20240626-005352 base: linus/master patch link: https://lore.kernel.org/r/20240625040500.1788-5-jszhang%40kernel.org patch subject: [PATCH 4/4] riscv: uaccess: use 'asm goto output' for get_user config: riscv-randconfig-r121-20240705 (https://download.01.org/0day-ci/archive/20240705/202407051159.ArkAPA6L-lkp@intel.com/config) compiler: riscv32-linux-gcc (GCC) 13.2.0 reproduce: (https://download.01.org/0day-ci/archive/20240705/202407051159.ArkAPA6L-lkp@intel.com/reproduce) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp@intel.com> | Closes: https://lore.kernel.org/oe-kbuild-all/202407051159.ArkAPA6L-lkp@intel.com/ All errors (new ones prefixed by >>): In file included from include/linux/compiler_types.h:174, from <command-line>: net/rfkill/core.c: In function 'rfkill_fop_ioctl': >> arch/riscv/include/asm/uaccess.h:104:26: error: '__lo' undeclared (first use in this function) 104 | : "=&r" (__lo), "=r" (__hi) \ | ^~~~ include/linux/compiler-gcc.h:84:32: note: in definition of macro 'asm_goto_output' 84 | do { asm volatile goto(x); asm (""); } while (0) | ^ arch/riscv/include/asm/uaccess.h:148:17: note: in expansion of macro '__get_user_8' 148 | __get_user_8((x), __gu_ptr, label); \ | ^~~~~~~~~~~~ arch/riscv/include/asm/uaccess.h:159:9: note: in expansion of macro '__get_user_nocheck' 159 | __get_user_nocheck(x, ptr, __gu_failed); \ | ^~~~~~~~~~~~~~~~~~ arch/riscv/include/asm/uaccess.h:196:9: note: in expansion of macro '__get_user_error' 196 | __get_user_error(__gu_val, __gu_ptr, __gu_err); \ | ^~~~~~~~~~~~~~~~ arch/riscv/include/asm/uaccess.h:226:17: note: in expansion of macro '__get_user' 226 | __get_user((x), __p) : \ | ^~~~~~~~~~ net/rfkill/core.c:1373:21: note: in expansion of macro 'get_user' 1373 | if (get_user(size, (__u32 __user *)arg)) { | ^~~~~~~~ arch/riscv/include/asm/uaccess.h:104:26: note: each undeclared identifier is reported only once for each function it appears in 104 | : "=&r" (__lo), "=r" (__hi) \ | ^~~~ include/linux/compiler-gcc.h:84:32: note: in definition of macro 'asm_goto_output' 84 | do { asm volatile goto(x); asm (""); } while (0) | ^ arch/riscv/include/asm/uaccess.h:148:17: note: in expansion of macro '__get_user_8' 148 | __get_user_8((x), __gu_ptr, label); \ | ^~~~~~~~~~~~ arch/riscv/include/asm/uaccess.h:159:9: note: in expansion of macro '__get_user_nocheck' 159 | __get_user_nocheck(x, ptr, __gu_failed); \ | ^~~~~~~~~~~~~~~~~~ arch/riscv/include/asm/uaccess.h:196:9: note: in expansion of macro '__get_user_error' 196 | __get_user_error(__gu_val, __gu_ptr, __gu_err); \ | ^~~~~~~~~~~~~~~~ arch/riscv/include/asm/uaccess.h:226:17: note: in expansion of macro '__get_user' 226 | __get_user((x), __p) : \ | ^~~~~~~~~~ net/rfkill/core.c:1373:21: note: in expansion of macro 'get_user' 1373 | if (get_user(size, (__u32 __user *)arg)) { | ^~~~~~~~ >> arch/riscv/include/asm/uaccess.h:104:39: error: '__hi' undeclared (first use in this function) 104 | : "=&r" (__lo), "=r" (__hi) \ | ^~~~ include/linux/compiler-gcc.h:84:32: note: in definition of macro 'asm_goto_output' 84 | do { asm volatile goto(x); asm (""); } while (0) | ^ arch/riscv/include/asm/uaccess.h:148:17: note: in expansion of macro '__get_user_8' 148 | __get_user_8((x), __gu_ptr, label); \ | ^~~~~~~~~~~~ arch/riscv/include/asm/uaccess.h:159:9: note: in expansion of macro '__get_user_nocheck' 159 | __get_user_nocheck(x, ptr, __gu_failed); \ | ^~~~~~~~~~~~~~~~~~ arch/riscv/include/asm/uaccess.h:196:9: note: in expansion of macro '__get_user_error' 196 | __get_user_error(__gu_val, __gu_ptr, __gu_err); \ | ^~~~~~~~~~~~~~~~ arch/riscv/include/asm/uaccess.h:226:17: note: in expansion of macro '__get_user' 226 | __get_user((x), __p) : \ | ^~~~~~~~~~ net/rfkill/core.c:1373:21: note: in expansion of macro 'get_user' 1373 | if (get_user(size, (__u32 __user *)arg)) { | ^~~~~~~~ >> arch/riscv/include/asm/uaccess.h:105:24: error: '__ptr' undeclared (first use in this function); did you mean '__p'? 105 | : "m" (__ptr[__LSW]), "m" (__ptr[__MSW]) \ | ^~~~~ include/linux/compiler-gcc.h:84:32: note: in definition of macro 'asm_goto_output' 84 | do { asm volatile goto(x); asm (""); } while (0) | ^ arch/riscv/include/asm/uaccess.h:148:17: note: in expansion of macro '__get_user_8' 148 | __get_user_8((x), __gu_ptr, label); \ | ^~~~~~~~~~~~ arch/riscv/include/asm/uaccess.h:159:9: note: in expansion of macro '__get_user_nocheck' 159 | __get_user_nocheck(x, ptr, __gu_failed); \ | ^~~~~~~~~~~~~~~~~~ arch/riscv/include/asm/uaccess.h:196:9: note: in expansion of macro '__get_user_error' 196 | __get_user_error(__gu_val, __gu_ptr, __gu_err); \ | ^~~~~~~~~~~~~~~~ arch/riscv/include/asm/uaccess.h:226:17: note: in expansion of macro '__get_user' 226 | __get_user((x), __p) : \ | ^~~~~~~~~~ net/rfkill/core.c:1373:21: note: in expansion of macro 'get_user' 1373 | if (get_user(size, (__u32 __user *)arg)) { | ^~~~~~~~ vim +/__lo +104 arch/riscv/include/asm/uaccess.h 94 95 #ifdef CONFIG_CC_HAS_ASM_GOTO_OUTPUT 96 #define __get_user_8(x, ptr, label) \ 97 asm_goto_output( \ 98 "1:\n" \ 99 " lw %0, %2\n" \ 100 "2:\n" \ 101 " lw %1, %3\n" \ 102 _ASM_EXTABLE_UACCESS_ERR(1b, %l4, %0) \ 103 _ASM_EXTABLE_UACCESS_ERR(2b, %l4, %0) \ > 104 : "=&r" (__lo), "=r" (__hi) \ > 105 : "m" (__ptr[__LSW]), "m" (__ptr[__MSW]) \ 106 : : label) 107
diff --git a/arch/riscv/include/asm/uaccess.h b/arch/riscv/include/asm/uaccess.h index d8c44705b61d..d9c32b4f7d13 100644 --- a/arch/riscv/include/asm/uaccess.h +++ b/arch/riscv/include/asm/uaccess.h @@ -63,27 +63,54 @@ * call. */ -#define __get_user_asm(insn, x, ptr, err) \ +#ifdef CONFIG_CC_HAS_ASM_GOTO_OUTPUT +#define __get_user_asm(insn, x, ptr, label) \ + asm_goto_output( \ + "1:\n" \ + " " insn " %0, %1\n" \ + _ASM_EXTABLE_UACCESS_ERR(1b, %l2, %0) \ + : "=&r" (x) \ + : "m" (*(ptr)) : : label) +#else /* !CONFIG_CC_HAS_ASM_GOTO_OUTPUT */ +#define __get_user_asm(insn, x, ptr, label) \ do { \ - __typeof__(x) __x; \ + long __gua_err = 0; \ __asm__ __volatile__ ( \ "1:\n" \ " " insn " %1, %2\n" \ "2:\n" \ _ASM_EXTABLE_UACCESS_ERR_ZERO(1b, 2b, %0, %1) \ - : "+r" (err), "=&r" (__x) \ + : "+r" (__gua_err), "=&r" (x) \ : "m" (*(ptr))); \ - (x) = __x; \ + if (__gua_err) \ + goto label; \ } while (0) +#endif /* CONFIG_CC_HAS_ASM_GOTO_OUTPUT */ #ifdef CONFIG_64BIT -#define __get_user_8(x, ptr, err) \ - __get_user_asm("ld", x, ptr, err) +#define __get_user_8(x, ptr, label) \ + __get_user_asm("ld", x, ptr, label) #else /* !CONFIG_64BIT */ -#define __get_user_8(x, ptr, err) \ + +#ifdef CONFIG_CC_HAS_ASM_GOTO_OUTPUT +#define __get_user_8(x, ptr, label) \ + asm_goto_output( \ + "1:\n" \ + " lw %0, %2\n" \ + "2:\n" \ + " lw %1, %3\n" \ + _ASM_EXTABLE_UACCESS_ERR(1b, %l4, %0) \ + _ASM_EXTABLE_UACCESS_ERR(2b, %l4, %0) \ + : "=&r" (__lo), "=r" (__hi) \ + : "m" (__ptr[__LSW]), "m" (__ptr[__MSW]) \ + : : label) + +#else /* !CONFIG_CC_HAS_ASM_GOTO_OUTPUT */ +#define __get_user_8(x, ptr, label) \ do { \ u32 __user *__ptr = (u32 __user *)(ptr); \ u32 __lo, __hi; \ + long __gu8_err = 0; \ __asm__ __volatile__ ( \ "1:\n" \ " lw %1, %3\n" \ @@ -92,35 +119,51 @@ do { \ "3:\n" \ _ASM_EXTABLE_UACCESS_ERR_ZERO(1b, 3b, %0, %1) \ _ASM_EXTABLE_UACCESS_ERR_ZERO(2b, 3b, %0, %1) \ - : "+r" (err), "=&r" (__lo), "=r" (__hi) \ + : "+r" (__gu8_err), "=&r" (__lo), "=r" (__hi) \ : "m" (__ptr[__LSW]), "m" (__ptr[__MSW])); \ - if (err) \ + if (__gu8_err) { \ __hi = 0; \ + goto label; \ + } \ (x) = (__typeof__(x))((__typeof__((x)-(x)))( \ (((u64)__hi << 32) | __lo))); \ } while (0) +#endif /* CONFIG_CC_HAS_ASM_GOTO_OUTPUT */ + #endif /* CONFIG_64BIT */ -#define __get_user_nocheck(x, __gu_ptr, __gu_err) \ +#define __get_user_nocheck(x, __gu_ptr, label) \ do { \ switch (sizeof(*__gu_ptr)) { \ case 1: \ - __get_user_asm("lb", (x), __gu_ptr, __gu_err); \ + __get_user_asm("lb", (x), __gu_ptr, label); \ break; \ case 2: \ - __get_user_asm("lh", (x), __gu_ptr, __gu_err); \ + __get_user_asm("lh", (x), __gu_ptr, label); \ break; \ case 4: \ - __get_user_asm("lw", (x), __gu_ptr, __gu_err); \ + __get_user_asm("lw", (x), __gu_ptr, label); \ break; \ case 8: \ - __get_user_8((x), __gu_ptr, __gu_err); \ + __get_user_8((x), __gu_ptr, label); \ break; \ default: \ BUILD_BUG(); \ } \ } while (0) +#define __get_user_error(x, ptr, err) \ +do { \ + __label__ __gu_failed; \ + \ + __get_user_nocheck(x, ptr, __gu_failed); \ + err = 0; \ + break; \ +__gu_failed: \ + x = 0; \ + err = -EFAULT; \ +} while (0) + /** * __get_user: - Get a simple variable from user space, with less checking. * @x: Variable to store result. @@ -145,13 +188,16 @@ do { \ ({ \ const __typeof__(*(ptr)) __user *__gu_ptr = (ptr); \ long __gu_err = 0; \ + __typeof__(x) __gu_val; \ \ __chk_user_ptr(__gu_ptr); \ \ __enable_user_access(); \ - __get_user_nocheck(x, __gu_ptr, __gu_err); \ + __get_user_error(__gu_val, __gu_ptr, __gu_err); \ __disable_user_access(); \ \ + (x) = __gu_val; \ + \ __gu_err; \ }) @@ -336,13 +382,7 @@ unsigned long __must_check clear_user(void __user *to, unsigned long n) } #define __get_kernel_nofault(dst, src, type, err_label) \ -do { \ - long __kr_err = 0; \ - \ - __get_user_nocheck(*((type *)(dst)), (type *)(src), __kr_err); \ - if (unlikely(__kr_err)) \ - goto err_label; \ -} while (0) + __get_user_nocheck(*((type *)(dst)), (type *)(src), err_label); #define __put_kernel_nofault(dst, src, type, err_label) \ __put_user_nocheck(*((type *)(src)), (type *)(dst), err_label); @@ -364,11 +404,9 @@ static inline void user_access_restore(unsigned long enabled) { } __put_user_nocheck(x, (ptr), label); #define unsafe_get_user(x, ptr, label) do { \ - long __kr_err = 0; \ __inttype(*(ptr)) __gu_val; \ - __get_user_nocheck(__gu_val, (ptr), __kr_err); \ + __get_user_nocheck(__gu_val, (ptr), label); \ (x) = (__force __typeof__(*(ptr)))__gu_val; \ - if (__kr_err) goto label; \ } while (0) /*
'asm goto output' generates noticeably better code since we don't need to test the error etc, the exception just jumps to the error handling directly. Signed-off-by: Jisheng Zhang <jszhang@kernel.org> --- arch/riscv/include/asm/uaccess.h | 88 +++++++++++++++++++++++--------- 1 file changed, 63 insertions(+), 25 deletions(-)