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/page_types.h> 30#include <asm/errno.h> 31#include <asm/asm-offsets.h> 32#include <asm/thread_info.h> 33#include <asm/asm.h> 34#include <asm/smap.h> 35#include <asm/export.h> 36 37 .text 38ENTRY(__get_user_1) 39 mov PER_CPU_VAR(current_task), %_ASM_DX 40 cmp TASK_addr_limit(%_ASM_DX),%_ASM_AX 41 jae bad_get_user 42 ASM_STAC 431: movzbl (%_ASM_AX),%edx 44 xor %eax,%eax 45 ASM_CLAC 46 ret 47ENDPROC(__get_user_1) 48EXPORT_SYMBOL(__get_user_1) 49 50ENTRY(__get_user_2) 51 add $1,%_ASM_AX 52 jc bad_get_user 53 mov PER_CPU_VAR(current_task), %_ASM_DX 54 cmp TASK_addr_limit(%_ASM_DX),%_ASM_AX 55 jae bad_get_user 56 ASM_STAC 572: movzwl -1(%_ASM_AX),%edx 58 xor %eax,%eax 59 ASM_CLAC 60 ret 61ENDPROC(__get_user_2) 62EXPORT_SYMBOL(__get_user_2) 63 64ENTRY(__get_user_4) 65 add $3,%_ASM_AX 66 jc bad_get_user 67 mov PER_CPU_VAR(current_task), %_ASM_DX 68 cmp TASK_addr_limit(%_ASM_DX),%_ASM_AX 69 jae bad_get_user 70 ASM_STAC 713: movl -3(%_ASM_AX),%edx 72 xor %eax,%eax 73 ASM_CLAC 74 ret 75ENDPROC(__get_user_4) 76EXPORT_SYMBOL(__get_user_4) 77 78ENTRY(__get_user_8) 79#ifdef CONFIG_X86_64 80 add $7,%_ASM_AX 81 jc bad_get_user 82 mov PER_CPU_VAR(current_task), %_ASM_DX 83 cmp TASK_addr_limit(%_ASM_DX),%_ASM_AX 84 jae bad_get_user 85 ASM_STAC 864: movq -7(%_ASM_AX),%rdx 87 xor %eax,%eax 88 ASM_CLAC 89 ret 90#else 91 add $7,%_ASM_AX 92 jc bad_get_user_8 93 mov PER_CPU_VAR(current_task), %_ASM_DX 94 cmp TASK_addr_limit(%_ASM_DX),%_ASM_AX 95 jae bad_get_user_8 96 ASM_STAC 974: movl -7(%_ASM_AX),%edx 985: movl -3(%_ASM_AX),%ecx 99 xor %eax,%eax 100 ASM_CLAC 101 ret 102#endif 103ENDPROC(__get_user_8) 104EXPORT_SYMBOL(__get_user_8) 105 106 107bad_get_user: 108 xor %edx,%edx 109 mov $(-EFAULT),%_ASM_AX 110 ASM_CLAC 111 ret 112END(bad_get_user) 113 114#ifdef CONFIG_X86_32 115bad_get_user_8: 116 xor %edx,%edx 117 xor %ecx,%ecx 118 mov $(-EFAULT),%_ASM_AX 119 ASM_CLAC 120 ret 121END(bad_get_user_8) 122#endif 123 124 _ASM_EXTABLE(1b,bad_get_user) 125 _ASM_EXTABLE(2b,bad_get_user) 126 _ASM_EXTABLE(3b,bad_get_user) 127#ifdef CONFIG_X86_64 128 _ASM_EXTABLE(4b,bad_get_user) 129#else 130 _ASM_EXTABLE(4b,bad_get_user_8) 131 _ASM_EXTABLE(5b,bad_get_user_8) 132#endif 133