Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 356174
b: refs/heads/master
c: 96477b4
h: refs/heads/master
v: v3
  • Loading branch information
Ville Syrjälä authored and H. Peter Anvin committed Feb 7, 2013
1 parent e46a093 commit e1af354
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 10 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 07f4207a305c834f528d08428df4531744e25678
refs/heads/master: 96477b4cd705c5416346aef262b0a1116cfcdd80
19 changes: 15 additions & 4 deletions trunk/arch/x86/include/asm/uaccess.h
Original file line number Diff line number Diff line change
Expand Up @@ -151,8 +151,15 @@ extern int __get_user_bad(void);
* On error, the variable @x is set to zero.
*/
#ifdef CONFIG_X86_32
#define __get_user_8(__ret_gu, __val_gu, ptr) \
__get_user_x(X, __ret_gu, __val_gu, ptr)
#define __get_user_8(ret, x, ptr) \
do { \
register unsigned long long __xx asm("%edx"); \
asm volatile("call __get_user_8" \
: "=a" (ret), "=r" (__xx) \
: "0" (ptr)); \
(x) = __xx; \
} while (0)

#else
#define __get_user_8(__ret_gu, __val_gu, ptr) \
__get_user_x(8, __ret_gu, __val_gu, ptr)
Expand All @@ -162,6 +169,7 @@ extern int __get_user_bad(void);
({ \
int __ret_gu; \
unsigned long __val_gu; \
unsigned long long __val_gu8; \
__chk_user_ptr(ptr); \
might_fault(); \
switch (sizeof(*(ptr))) { \
Expand All @@ -175,13 +183,16 @@ extern int __get_user_bad(void);
__get_user_x(4, __ret_gu, __val_gu, ptr); \
break; \
case 8: \
__get_user_8(__ret_gu, __val_gu, ptr); \
__get_user_8(__ret_gu, __val_gu8, ptr); \
break; \
default: \
__get_user_x(X, __ret_gu, __val_gu, ptr); \
break; \
} \
(x) = (__typeof__(*(ptr)))__val_gu; \
if (sizeof(*(ptr)) == 8) \
(x) = (__typeof__(*(ptr)))__val_gu8; \
else \
(x) = (__typeof__(*(ptr)))__val_gu; \
__ret_gu; \
})

Expand Down
1 change: 1 addition & 0 deletions trunk/arch/x86/kernel/i386_ksyms_32.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ EXPORT_SYMBOL(csum_partial_copy_generic);
EXPORT_SYMBOL(__get_user_1);
EXPORT_SYMBOL(__get_user_2);
EXPORT_SYMBOL(__get_user_4);
EXPORT_SYMBOL(__get_user_8);

EXPORT_SYMBOL(__put_user_1);
EXPORT_SYMBOL(__put_user_2);
Expand Down
37 changes: 32 additions & 5 deletions trunk/arch/x86/lib/getuser.S
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,10 @@
* __get_user_X
*
* Inputs: %[r|e]ax contains the address.
* The register is modified, but all changes are undone
* before returning because the C code doesn't know about it.
*
* Outputs: %[r|e]ax is error code (0 or -EFAULT)
* %[r|e]dx contains zero-extended value
* %ecx contains the high half for 32-bit __get_user_8
*
*
* These functions should not modify any other registers,
Expand Down Expand Up @@ -79,22 +78,35 @@ ENTRY(__get_user_4)
CFI_ENDPROC
ENDPROC(__get_user_4)

#ifdef CONFIG_X86_64
ENTRY(__get_user_8)
CFI_STARTPROC
#ifdef CONFIG_X86_64
add $7,%_ASM_AX
jc bad_get_user
GET_THREAD_INFO(%_ASM_DX)
cmp TI_addr_limit(%_ASM_DX),%_ASM_AX
jae bad_get_user
jae bad_get_user
ASM_STAC
4: movq -7(%_ASM_AX),%_ASM_DX
xor %eax,%eax
ASM_CLAC
ret
#else
add $7,%_ASM_AX
jc bad_get_user_8
GET_THREAD_INFO(%_ASM_DX)
cmp TI_addr_limit(%_ASM_DX),%_ASM_AX
jae bad_get_user_8
ASM_STAC
4: mov -7(%_ASM_AX),%edx
5: mov -3(%_ASM_AX),%ecx
xor %eax,%eax
ASM_CLAC
ret
#endif
CFI_ENDPROC
ENDPROC(__get_user_8)
#endif


bad_get_user:
CFI_STARTPROC
Expand All @@ -105,9 +117,24 @@ bad_get_user:
CFI_ENDPROC
END(bad_get_user)

#ifdef CONFIG_X86_32
bad_get_user_8:
CFI_STARTPROC
xor %edx,%edx
xor %ecx,%ecx
mov $(-EFAULT),%_ASM_AX
ASM_CLAC
ret
CFI_ENDPROC
END(bad_get_user_8)
#endif

_ASM_EXTABLE(1b,bad_get_user)
_ASM_EXTABLE(2b,bad_get_user)
_ASM_EXTABLE(3b,bad_get_user)
#ifdef CONFIG_X86_64
_ASM_EXTABLE(4b,bad_get_user)
#else
_ASM_EXTABLE(4b,bad_get_user_8)
_ASM_EXTABLE(5b,bad_get_user_8)
#endif

0 comments on commit e1af354

Please sign in to comment.