Skip to content

Commit 4cd4156

Browse files
committed
Merge branch 'x86-asm-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86/asm changes from Ingo Molnar: "Misc optimizations" * 'x86-asm-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86: Slightly tweak the access_ok() C variant for better code x86: Replace assembly access_ok() with a C variant x86-64, copy_user: Use leal to produce 32-bit results x86-64, copy_user: Remove zero byte check before copy user buffer.
2 parents 1a7dbbc + a740576 commit 4cd4156

File tree

2 files changed

+24
-20
lines changed

2 files changed

+24
-20
lines changed

arch/x86/include/asm/uaccess.h

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -40,22 +40,30 @@
4040
/*
4141
* Test whether a block of memory is a valid user space address.
4242
* Returns 0 if the range is valid, nonzero otherwise.
43-
*
44-
* This is equivalent to the following test:
45-
* (u33)addr + (u33)size > (u33)current->addr_limit.seg (u65 for x86_64)
46-
*
47-
* This needs 33-bit (65-bit for x86_64) arithmetic. We have a carry...
4843
*/
44+
static inline bool __chk_range_not_ok(unsigned long addr, unsigned long size, unsigned long limit)
45+
{
46+
/*
47+
* If we have used "sizeof()" for the size,
48+
* we know it won't overflow the limit (but
49+
* it might overflow the 'addr', so it's
50+
* important to subtract the size from the
51+
* limit, not add it to the address).
52+
*/
53+
if (__builtin_constant_p(size))
54+
return addr > limit - size;
55+
56+
/* Arbitrary sizes? Be careful about overflow */
57+
addr += size;
58+
if (addr < size)
59+
return true;
60+
return addr > limit;
61+
}
4962

5063
#define __range_not_ok(addr, size, limit) \
5164
({ \
52-
unsigned long flag, roksum; \
5365
__chk_user_ptr(addr); \
54-
asm("add %3,%1 ; sbb %0,%0 ; cmp %1,%4 ; sbb $0,%0" \
55-
: "=&r" (flag), "=r" (roksum) \
56-
: "1" (addr), "g" ((long)(size)), \
57-
"rm" (limit)); \
58-
flag; \
66+
__chk_range_not_ok((unsigned long __force)(addr), size, limit); \
5967
})
6068

6169
/**
@@ -78,7 +86,7 @@
7886
* this function, memory access functions may still return -EFAULT.
7987
*/
8088
#define access_ok(type, addr, size) \
81-
(likely(__range_not_ok(addr, size, user_addr_max()) == 0))
89+
likely(!__range_not_ok(addr, size, user_addr_max()))
8290

8391
/*
8492
* The exception table consists of pairs of addresses relative to the

arch/x86/lib/copy_user_64.S

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ ENTRY(copy_user_generic_unrolled)
186186
30: shll $6,%ecx
187187
addl %ecx,%edx
188188
jmp 60f
189-
40: lea (%rdx,%rcx,8),%rdx
189+
40: leal (%rdx,%rcx,8),%edx
190190
jmp 60f
191191
50: movl %ecx,%edx
192192
60: jmp copy_user_handle_tail /* ecx is zerorest also */
@@ -236,8 +236,6 @@ ENDPROC(copy_user_generic_unrolled)
236236
ENTRY(copy_user_generic_string)
237237
CFI_STARTPROC
238238
ASM_STAC
239-
andl %edx,%edx
240-
jz 4f
241239
cmpl $8,%edx
242240
jb 2f /* less than 8 bytes, go to byte copy loop */
243241
ALIGN_DESTINATION
@@ -249,12 +247,12 @@ ENTRY(copy_user_generic_string)
249247
2: movl %edx,%ecx
250248
3: rep
251249
movsb
252-
4: xorl %eax,%eax
250+
xorl %eax,%eax
253251
ASM_CLAC
254252
ret
255253

256254
.section .fixup,"ax"
257-
11: lea (%rdx,%rcx,8),%rcx
255+
11: leal (%rdx,%rcx,8),%ecx
258256
12: movl %ecx,%edx /* ecx is zerorest also */
259257
jmp copy_user_handle_tail
260258
.previous
@@ -279,12 +277,10 @@ ENDPROC(copy_user_generic_string)
279277
ENTRY(copy_user_enhanced_fast_string)
280278
CFI_STARTPROC
281279
ASM_STAC
282-
andl %edx,%edx
283-
jz 2f
284280
movl %edx,%ecx
285281
1: rep
286282
movsb
287-
2: xorl %eax,%eax
283+
xorl %eax,%eax
288284
ASM_CLAC
289285
ret
290286

0 commit comments

Comments
 (0)