mirror of
https://github.com/torvalds/linux.git
synced 2024-11-17 01:22:07 +00:00
96477b4cd7
Implement __get_user_8() for x86-32. It will return the 64-bit result in edx:eax register pair, and ecx is used to pass in the address and return the error value. For consistency, change the register assignment for all other __get_user_x() variants, so that address is passed in ecx/rcx, the error value is returned in ecx/rcx, and eax/rax contains the actual value. [ hpa: I modified the patch so that it does NOT change the calling conventions for the existing callsites, this also means that the code is completely unchanged for 64 bits. Instead, continue to use eax for address input/error output and use the ecx:edx register pair for the output. ] This is a partial refresh of a patch [1] by Jamie Lokier from 2004. Only the minimal changes to implement 64bit get_user() were picked from the original patch. [1] http://article.gmane.org/gmane.linux.kernel/198823 Originally-by: Jamie Lokier <jamie@shareable.org> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: http://lkml.kernel.org/r/1355312043-11467-1-git-send-email-ville.syrjala@linux.intel.com Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
141 lines
2.5 KiB
ArmAsm
141 lines
2.5 KiB
ArmAsm
/*
|
|
* __get_user functions.
|
|
*
|
|
* (C) Copyright 1998 Linus Torvalds
|
|
* (C) Copyright 2005 Andi Kleen
|
|
* (C) Copyright 2008 Glauber Costa
|
|
*
|
|
* These functions have a non-standard call interface
|
|
* to make them more efficient, especially as they
|
|
* return an error value in addition to the "real"
|
|
* return value.
|
|
*/
|
|
|
|
/*
|
|
* __get_user_X
|
|
*
|
|
* Inputs: %[r|e]ax contains the address.
|
|
*
|
|
* 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,
|
|
* as they get called from within inline assembly.
|
|
*/
|
|
|
|
#include <linux/linkage.h>
|
|
#include <asm/dwarf2.h>
|
|
#include <asm/page_types.h>
|
|
#include <asm/errno.h>
|
|
#include <asm/asm-offsets.h>
|
|
#include <asm/thread_info.h>
|
|
#include <asm/asm.h>
|
|
#include <asm/smap.h>
|
|
|
|
.text
|
|
ENTRY(__get_user_1)
|
|
CFI_STARTPROC
|
|
GET_THREAD_INFO(%_ASM_DX)
|
|
cmp TI_addr_limit(%_ASM_DX),%_ASM_AX
|
|
jae bad_get_user
|
|
ASM_STAC
|
|
1: movzb (%_ASM_AX),%edx
|
|
xor %eax,%eax
|
|
ASM_CLAC
|
|
ret
|
|
CFI_ENDPROC
|
|
ENDPROC(__get_user_1)
|
|
|
|
ENTRY(__get_user_2)
|
|
CFI_STARTPROC
|
|
add $1,%_ASM_AX
|
|
jc bad_get_user
|
|
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)
|
|
|
|
ENTRY(__get_user_4)
|
|
CFI_STARTPROC
|
|
add $3,%_ASM_AX
|
|
jc bad_get_user
|
|
GET_THREAD_INFO(%_ASM_DX)
|
|
cmp TI_addr_limit(%_ASM_DX),%_ASM_AX
|
|
jae bad_get_user
|
|
ASM_STAC
|
|
3: mov -3(%_ASM_AX),%edx
|
|
xor %eax,%eax
|
|
ASM_CLAC
|
|
ret
|
|
CFI_ENDPROC
|
|
ENDPROC(__get_user_4)
|
|
|
|
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
|
|
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)
|
|
|
|
|
|
bad_get_user:
|
|
CFI_STARTPROC
|
|
xor %edx,%edx
|
|
mov $(-EFAULT),%_ASM_AX
|
|
ASM_CLAC
|
|
ret
|
|
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
|