Skip to content

Commit cdf647e

Browse files
xhackerustcpalmer-dabbelt
authored andcommitted
riscv: uaccess: use 'asm goto' for put_user()
With 'asm goto' we don't need to test the error etc, the exception just jumps to the error handling directly. Because there are no output clobbers which could trigger gcc bugs [1] the use of asm_goto_output() macro is not necessary here. Not using asm_goto_output() is desirable as the generated output asm will be cleaner. Use of the volatile keyword is redundant as per gcc 14.2.0 manual section 6.48.2.7 Goto Labels: > Also note that an asm goto statement is always implicitly considered volatile. Link: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113921 # 1 Signed-off-by: Jisheng Zhang <[email protected]> [Cyril Bur: Rewritten commit message] Signed-off-by: Cyril Bur <[email protected]> Reviewed-by: Alexandre Ghiti <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Palmer Dabbelt <[email protected]>
1 parent 62135bf commit cdf647e

File tree

1 file changed

+33
-38
lines changed

1 file changed

+33
-38
lines changed

arch/riscv/include/asm/uaccess.h

Lines changed: 33 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -214,61 +214,66 @@ do { \
214214
((x) = (__force __typeof__(x))0, -EFAULT); \
215215
})
216216

217-
#define __put_user_asm(insn, x, ptr, err) \
217+
#define __put_user_asm(insn, x, ptr, label) \
218218
do { \
219219
__typeof__(*(ptr)) __x = x; \
220-
__asm__ __volatile__ ( \
220+
asm goto( \
221221
"1:\n" \
222-
" " insn " %z1, %2\n" \
223-
"2:\n" \
224-
_ASM_EXTABLE_UACCESS_ERR(1b, 2b, %0) \
225-
: "+r" (err) \
226-
: "rJ" (__x), "m"(*(ptr))); \
222+
" " insn " %z0, %1\n" \
223+
_ASM_EXTABLE(1b, %l2) \
224+
: : "rJ" (__x), "m"(*(ptr)) : : label); \
227225
} while (0)
228226

229227
#ifdef CONFIG_64BIT
230-
#define __put_user_8(x, ptr, err) \
231-
__put_user_asm("sd", x, ptr, err)
228+
#define __put_user_8(x, ptr, label) \
229+
__put_user_asm("sd", x, ptr, label)
232230
#else /* !CONFIG_64BIT */
233-
#define __put_user_8(x, ptr, err) \
231+
#define __put_user_8(x, ptr, label) \
234232
do { \
235233
u32 __user *__ptr = (u32 __user *)(ptr); \
236234
u64 __x = (__typeof__((x)-(x)))(x); \
237-
__asm__ __volatile__ ( \
235+
asm goto( \
238236
"1:\n" \
239-
" sw %z1, %3\n" \
237+
" sw %z0, %2\n" \
240238
"2:\n" \
241-
" sw %z2, %4\n" \
242-
"3:\n" \
243-
_ASM_EXTABLE_UACCESS_ERR(1b, 3b, %0) \
244-
_ASM_EXTABLE_UACCESS_ERR(2b, 3b, %0) \
245-
: "+r" (err) \
246-
: "rJ" (__x), "rJ" (__x >> 32), \
239+
" sw %z1, %3\n" \
240+
_ASM_EXTABLE(1b, %l4) \
241+
_ASM_EXTABLE(2b, %l4) \
242+
: : "rJ" (__x), "rJ" (__x >> 32), \
247243
"m" (__ptr[__LSW]), \
248-
"m" (__ptr[__MSW])); \
244+
"m" (__ptr[__MSW]) : : label); \
249245
} while (0)
250246
#endif /* CONFIG_64BIT */
251247

252-
#define __put_user_nocheck(x, __gu_ptr, __pu_err) \
248+
#define __put_user_nocheck(x, __gu_ptr, label) \
253249
do { \
254250
switch (sizeof(*__gu_ptr)) { \
255251
case 1: \
256-
__put_user_asm("sb", (x), __gu_ptr, __pu_err); \
252+
__put_user_asm("sb", (x), __gu_ptr, label); \
257253
break; \
258254
case 2: \
259-
__put_user_asm("sh", (x), __gu_ptr, __pu_err); \
255+
__put_user_asm("sh", (x), __gu_ptr, label); \
260256
break; \
261257
case 4: \
262-
__put_user_asm("sw", (x), __gu_ptr, __pu_err); \
258+
__put_user_asm("sw", (x), __gu_ptr, label); \
263259
break; \
264260
case 8: \
265-
__put_user_8((x), __gu_ptr, __pu_err); \
261+
__put_user_8((x), __gu_ptr, label); \
266262
break; \
267263
default: \
268264
BUILD_BUG(); \
269265
} \
270266
} while (0)
271267

268+
#define __put_user_error(x, ptr, err) \
269+
do { \
270+
__label__ err_label; \
271+
__put_user_nocheck(x, ptr, err_label); \
272+
break; \
273+
err_label: \
274+
(err) = -EFAULT; \
275+
} while (0)
276+
272277
/**
273278
* __put_user: - Write a simple value into user space, with less checking.
274279
* @x: Value to copy to user space.
@@ -299,7 +304,7 @@ do { \
299304
__chk_user_ptr(__gu_ptr); \
300305
\
301306
__enable_user_access(); \
302-
__put_user_nocheck(__val, __gu_ptr, __pu_err); \
307+
__put_user_error(__val, __gu_ptr, __pu_err); \
303308
__disable_user_access(); \
304309
\
305310
__pu_err; \
@@ -373,13 +378,7 @@ do { \
373378
} while (0)
374379

375380
#define __put_kernel_nofault(dst, src, type, err_label) \
376-
do { \
377-
long __kr_err = 0; \
378-
\
379-
__put_user_nocheck(*((type *)(src)), (type *)(dst), __kr_err); \
380-
if (unlikely(__kr_err)) \
381-
goto err_label; \
382-
} while (0)
381+
__put_user_nocheck(*((type *)(src)), (type *)(dst), err_label)
383382

384383
static __must_check __always_inline bool user_access_begin(const void __user *ptr, size_t len)
385384
{
@@ -398,12 +397,8 @@ static inline void user_access_restore(unsigned long enabled) { }
398397
* We want the unsafe accessors to always be inlined and use
399398
* the error labels - thus the macro games.
400399
*/
401-
#define unsafe_put_user(x, ptr, label) do { \
402-
long __err = 0; \
403-
__put_user_nocheck(x, (ptr), __err); \
404-
if (__err) \
405-
goto label; \
406-
} while (0)
400+
#define unsafe_put_user(x, ptr, label) \
401+
__put_user_nocheck(x, (ptr), label)
407402

408403
#define unsafe_get_user(x, ptr, label) do { \
409404
long __err = 0; \

0 commit comments

Comments
 (0)