1/* 2 * __get_user functions. 3 * 4 * (C) Copyright 1998 Linus Torvalds 5 * (C) Copyright 2005 Andi Kleen 6 * (C) Copyright 2008 Glauber Costa 7 * 8 * These functions have a non-standard call interface 9 * to make them more efficient, especially as they 10 * return an error value in addition to the "real" 11 * return value. 12 */ 13 14/* 15 * __get_user_X 16 * 17 * Inputs: %[r|e]ax contains the address. 18 * 19 * Outputs: %[r|e]ax is error code (0 or -EFAULT) 20 * %[r|e]dx contains zero-extended value 21 * %ecx contains the high half for 32-bit __get_user_8 22 * 23 * 24 * These functions should not modify any other registers, 25 * as they get called from within inline assembly. 26 */ 27 28#include <linux/linkage.h> 29#include <asm/dwarf2.h> 30#include <asm/page_types.h> 31#include <asm/errno.h> 32#include <asm/asm-offsets.h> 33#include <asm/thread_info.h> 34#include <asm/asm.h> 35#include <asm/smap.h> 36 37 .text 38ENTRY(__get_user_1) 39 CFI_STARTPROC 40 GET_THREAD_INFO(%_ASM_DX) 41 cmp TI_addr_limit(%_ASM_DX),%_ASM_AX 42 jae bad_get_user 43 ASM_STAC 441: movzbl (%_ASM_AX),%edx 45 xor %eax,%eax 46 ASM_CLAC 47 ret 48 CFI_ENDPROC 49ENDPROC(__get_user_1) 50 51ENTRY(__get_user_2) 52 CFI_STARTPROC 53 add $1,%_ASM_AX 54 jc bad_get_user 55 GET_THREAD_INFO(%_ASM_DX) 56 cmp TI_addr_limit(%_ASM_DX),%_ASM_AX 57 jae bad_get_user 58 ASM_STAC 592: movzwl -1(%_ASM_AX),%edx 60 xor %eax,%eax 61 ASM_CLAC 62 ret 63 CFI_ENDPROC 64ENDPROC(__get_user_2) 65 66ENTRY(__get_user_4) 67 CFI_STARTPROC 68 add $3,%_ASM_AX 69 jc bad_get_user 70 GET_THREAD_INFO(%_ASM_DX) 71 cmp TI_addr_limit(%_ASM_DX),%_ASM_AX 72 jae bad_get_user 73 ASM_STAC 743: movl -3(%_ASM_AX),%edx 75 xor %eax,%eax 76 ASM_CLAC 77 ret 78 CFI_ENDPROC 79ENDPROC(__get_user_4) 80 81ENTRY(__get_user_8) 82 CFI_STARTPROC 83#ifdef CONFIG_X86_64 84 add $7,%_ASM_AX 85 jc bad_get_user 86 GET_THREAD_INFO(%_ASM_DX) 87 cmp TI_addr_limit(%_ASM_DX),%_ASM_AX 88 jae bad_get_user 89 ASM_STAC 904: movq -7(%_ASM_AX),%rdx 91 xor %eax,%eax 92 ASM_CLAC 93 ret 94#else 95 add $7,%_ASM_AX 96 jc bad_get_user_8 97 GET_THREAD_INFO(%_ASM_DX) 98 cmp TI_addr_limit(%_ASM_DX),%_ASM_AX 99 jae bad_get_user_8 100 ASM_STAC 1014: movl -7(%_ASM_AX),%edx 1025: movl -3(%_ASM_AX),%ecx 103 xor %eax,%eax 104 ASM_CLAC 105 ret 106#endif 107 CFI_ENDPROC 108ENDPROC(__get_user_8) 109 110 111bad_get_user: 112 CFI_STARTPROC 113 xor %edx,%edx 114 mov $(-EFAULT),%_ASM_AX 115 ASM_CLAC 116 ret 117 CFI_ENDPROC 118END(bad_get_user) 119 120#ifdef CONFIG_X86_32 121bad_get_user_8: 122 CFI_STARTPROC 123 xor %edx,%edx 124 xor %ecx,%ecx 125 mov $(-EFAULT),%_ASM_AX 126 ASM_CLAC 127 ret 128 CFI_ENDPROC 129END(bad_get_user_8) 130#endif 131 132 _ASM_EXTABLE(1b,bad_get_user) 133 _ASM_EXTABLE(2b,bad_get_user) 134 _ASM_EXTABLE(3b,bad_get_user) 135#ifdef CONFIG_X86_64 136 _ASM_EXTABLE(4b,bad_get_user) 137#else 138 _ASM_EXTABLE(4b,bad_get_user_8) 139 _ASM_EXTABLE(5b,bad_get_user_8) 140#endif 141