diff options
Diffstat (limited to 'arch/x86/lib/getuser.S')
| -rw-r--r-- | arch/x86/lib/getuser.S | 62 | 
1 files changed, 49 insertions, 13 deletions
diff --git a/arch/x86/lib/getuser.S b/arch/x86/lib/getuser.S index 51f1504cddd..a4512359656 100644 --- a/arch/x86/lib/getuser.S +++ b/arch/x86/lib/getuser.S @@ -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, @@ -33,6 +32,7 @@  #include <asm/asm-offsets.h>  #include <asm/thread_info.h>  #include <asm/asm.h> +#include <asm/smap.h>  	.text  ENTRY(__get_user_1) @@ -40,8 +40,10 @@ ENTRY(__get_user_1)  	GET_THREAD_INFO(%_ASM_DX)  	cmp TI_addr_limit(%_ASM_DX),%_ASM_AX  	jae bad_get_user -1:	movzb (%_ASM_AX),%edx +	ASM_STAC +1:	movzbl (%_ASM_AX),%edx  	xor %eax,%eax +	ASM_CLAC  	ret  	CFI_ENDPROC  ENDPROC(__get_user_1) @@ -53,8 +55,10 @@ ENTRY(__get_user_2)  	GET_THREAD_INFO(%_ASM_DX)  	cmp TI_addr_limit(%_ASM_DX),%_ASM_AX  	jae bad_get_user +	ASM_STAC  2:	movzwl -1(%_ASM_AX),%edx  	xor %eax,%eax +	ASM_CLAC  	ret  	CFI_ENDPROC  ENDPROC(__get_user_2) @@ -66,39 +70,71 @@ ENTRY(__get_user_4)  	GET_THREAD_INFO(%_ASM_DX)  	cmp TI_addr_limit(%_ASM_DX),%_ASM_AX  	jae bad_get_user -3:	mov -3(%_ASM_AX),%edx +	ASM_STAC +3:	movl -3(%_ASM_AX),%edx  	xor %eax,%eax +	ASM_CLAC  	ret  	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 -4:	movq -7(%_ASM_AX),%_ASM_DX +	jae bad_get_user +	ASM_STAC +4:	movq -7(%_ASM_AX),%rdx  	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:	movl -7(%_ASM_AX),%edx +5:	movl -3(%_ASM_AX),%ecx +	xor %eax,%eax +	ASM_CLAC +	ret +#endif  	CFI_ENDPROC  ENDPROC(__get_user_8) -#endif +  bad_get_user:  	CFI_STARTPROC  	xor %edx,%edx  	mov $(-EFAULT),%_ASM_AX +	ASM_CLAC  	ret  	CFI_ENDPROC  END(bad_get_user) -.section __ex_table,"a" -	_ASM_PTR 1b,bad_get_user -	_ASM_PTR 2b,bad_get_user -	_ASM_PTR 3b,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_PTR 4b,bad_get_user +	_ASM_EXTABLE(4b,bad_get_user) +#else +	_ASM_EXTABLE(4b,bad_get_user_8) +	_ASM_EXTABLE(5b,bad_get_user_8)  #endif  | 
