Skip to content

Commit a959dc8

Browse files
committed
Use __put_user_goto in __put_user_size() and unsafe_put_user()
This actually enables the __put_user_goto() functionality in unsafe_put_user(). For an example of the effect of this, this is the code generated for the unsafe_put_user(signo, &infop->si_signo, Efault); in the waitid() system call: movl %ecx,(%rbx) # signo, MEM[(struct __large_struct *)_2] It's just one single store instruction, along with generating an exception table entry pointing to the Efault label case in case that instruction faults. Before, we would generate this: xorl %edx, %edx movl %ecx,(%rbx) # signo, MEM[(struct __large_struct *)_3] testl %edx, %edx jne .L309 with the exception table generated for that 'mov' instruction causing us to jump to a stub that set %edx to -EFAULT and then jumped back to the 'testl' instruction. So not only do we now get rid of the extra code in the normal sequence, we also avoid unnecessarily keeping that extra error register live across it all. Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
1 parent 4a78921 commit a959dc8

File tree

1 file changed

+22
-31
lines changed

1 file changed

+22
-31
lines changed

arch/x86/include/asm/uaccess.h

Lines changed: 22 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -186,19 +186,14 @@ __typeof__(__builtin_choose_expr(sizeof(x) > sizeof(0UL), 0ULL, 0UL))
186186

187187

188188
#ifdef CONFIG_X86_32
189-
#define __put_user_asm_u64(x, addr, err, errret) \
190-
asm volatile("\n" \
191-
"1: movl %%eax,0(%2)\n" \
192-
"2: movl %%edx,4(%2)\n" \
193-
"3:" \
194-
".section .fixup,\"ax\"\n" \
195-
"4: movl %3,%0\n" \
196-
" jmp 3b\n" \
197-
".previous\n" \
198-
_ASM_EXTABLE_UA(1b, 4b) \
199-
_ASM_EXTABLE_UA(2b, 4b) \
200-
: "=r" (err) \
201-
: "A" (x), "r" (addr), "i" (errret), "0" (err))
189+
#define __put_user_goto_u64(x, addr, label) \
190+
asm_volatile_goto("\n" \
191+
"1: movl %%eax,0(%1)\n" \
192+
"2: movl %%edx,4(%1)\n" \
193+
_ASM_EXTABLE_UA(1b, %l2) \
194+
_ASM_EXTABLE_UA(2b, %l2) \
195+
: : "A" (x), "r" (addr) \
196+
: : label)
202197

203198
#define __put_user_asm_ex_u64(x, addr) \
204199
asm volatile("\n" \
@@ -213,8 +208,8 @@ __typeof__(__builtin_choose_expr(sizeof(x) > sizeof(0UL), 0ULL, 0UL))
213208
asm volatile("call __put_user_8" : "=a" (__ret_pu) \
214209
: "A" ((typeof(*(ptr)))(x)), "c" (ptr) : "ebx")
215210
#else
216-
#define __put_user_asm_u64(x, ptr, retval, errret) \
217-
__put_user_asm(x, ptr, retval, "q", "", "er", errret)
211+
#define __put_user_goto_u64(x, ptr, label) \
212+
__put_user_goto(x, ptr, "q", "", "er", label)
218213
#define __put_user_asm_ex_u64(x, addr) \
219214
__put_user_asm_ex(x, addr, "q", "", "er")
220215
#define __put_user_x8(x, ptr, __ret_pu) __put_user_x(8, x, ptr, __ret_pu)
@@ -275,23 +270,21 @@ extern void __put_user_8(void);
275270
__builtin_expect(__ret_pu, 0); \
276271
})
277272

278-
#define __put_user_size(x, ptr, size, retval, errret) \
273+
#define __put_user_size(x, ptr, size, label) \
279274
do { \
280-
retval = 0; \
281275
__chk_user_ptr(ptr); \
282276
switch (size) { \
283277
case 1: \
284-
__put_user_asm(x, ptr, retval, "b", "b", "iq", errret); \
278+
__put_user_goto(x, ptr, "b", "b", "iq", label); \
285279
break; \
286280
case 2: \
287-
__put_user_asm(x, ptr, retval, "w", "w", "ir", errret); \
281+
__put_user_goto(x, ptr, "w", "w", "ir", label); \
288282
break; \
289283
case 4: \
290-
__put_user_asm(x, ptr, retval, "l", "k", "ir", errret); \
284+
__put_user_goto(x, ptr, "l", "k", "ir", label); \
291285
break; \
292286
case 8: \
293-
__put_user_asm_u64((__typeof__(*ptr))(x), ptr, retval, \
294-
errret); \
287+
__put_user_goto_u64((__typeof__(*ptr))(x), ptr, label); \
295288
break; \
296289
default: \
297290
__put_user_bad(); \
@@ -436,9 +429,12 @@ do { \
436429

437430
#define __put_user_nocheck(x, ptr, size) \
438431
({ \
439-
int __pu_err; \
432+
__label__ __pu_label; \
433+
int __pu_err = -EFAULT; \
440434
__uaccess_begin(); \
441-
__put_user_size((x), (ptr), (size), __pu_err, -EFAULT); \
435+
__put_user_size((x), (ptr), (size), __pu_label); \
436+
__pu_err = 0; \
437+
__pu_label: \
442438
__uaccess_end(); \
443439
__builtin_expect(__pu_err, 0); \
444440
})
@@ -721,13 +717,8 @@ static __must_check inline bool user_access_begin(const void __user *ptr, size_t
721717
#define user_access_begin(a,b) user_access_begin(a,b)
722718
#define user_access_end() __uaccess_end()
723719

724-
#define unsafe_put_user(x, ptr, err_label) \
725-
do { \
726-
int __pu_err; \
727-
__typeof__(*(ptr)) __pu_val = (x); \
728-
__put_user_size(__pu_val, (ptr), sizeof(*(ptr)), __pu_err, -EFAULT); \
729-
if (unlikely(__pu_err)) goto err_label; \
730-
} while (0)
720+
#define unsafe_put_user(x, ptr, label) \
721+
__put_user_size((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr)), label)
731722

732723
#define unsafe_get_user(x, ptr, err_label) \
733724
do { \

0 commit comments

Comments
 (0)