1/* SPDX-License-Identifier: GPL-2.0 */ 2/* 3 * __get_user functions. 4 * 5 * (C) Copyright 1998 Linus Torvalds 6 * (C) Copyright 2005 Andi Kleen 7 * (C) Copyright 2008 Glauber Costa 8 * 9 * These functions have a non-standard call interface 10 * to make them more efficient, especially as they 11 * return an error value in addition to the "real" 12 * return value. 13 */ 14 15/* 16 * __get_user_X 17 * 18 * Inputs: %[r|e]ax contains the address. 19 * 20 * Outputs: %[r|e]ax is error code (0 or -EFAULT) 21 * %[r|e]dx contains zero-extended value 22 * %ecx contains the high half for 32-bit __get_user_8 23 * 24 * 25 * These functions should not modify any other registers, 26 * as they get called from within inline assembly. 27 */ 28 29#include <linux/linkage.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#include <asm/export.h> 37 38 .text 39ENTRY(__get_user_1) 40 mov PER_CPU_VAR(current_task), %_ASM_DX 41 cmp TASK_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 48ENDPROC(__get_user_1) 49EXPORT_SYMBOL(__get_user_1) 50 51ENTRY(__get_user_2) 52 add $1,%_ASM_AX 53 jc bad_get_user 54 mov PER_CPU_VAR(current_task), %_ASM_DX 55 cmp TASK_addr_limit(%_ASM_DX),%_ASM_AX 56 jae bad_get_user 57 ASM_STAC 582: movzwl -1(%_ASM_AX),%edx 59 xor %eax,%eax 60 ASM_CLAC 61 ret 62ENDPROC(__get_user_2) 63EXPORT_SYMBOL(__get_user_2) 64 65ENTRY(__get_user_4) 66 add $3,%_ASM_AX 67 jc bad_get_user 68 mov PER_CPU_VAR(current_task), %_ASM_DX 69 cmp TASK_addr_limit(%_ASM_DX),%_ASM_AX 70 jae bad_get_user 71 ASM_STAC 723: movl -3(%_ASM_AX),%edx 73 xor %eax,%eax 74 ASM_CLAC 75 ret 76ENDPROC(__get_user_4) 77EXPORT_SYMBOL(__get_user_4) 78 79ENTRY(__get_user_8) 80#ifdef CONFIG_X86_64 81 add $7,%_ASM_AX 82 jc bad_get_user 83 mov PER_CPU_VAR(current_task), %_ASM_DX 84 cmp TASK_addr_limit(%_ASM_DX),%_ASM_AX 85 jae bad_get_user 86 ASM_STAC 874: movq -7(%_ASM_AX),%rdx 88 xor %eax,%eax 89 ASM_CLAC 90 ret 91#else 92 add $7,%_ASM_AX 93 jc bad_get_user_8 94 mov PER_CPU_VAR(current_task), %_ASM_DX 95 cmp TASK_addr_limit(%_ASM_DX),%_ASM_AX 96 jae bad_get_user_8 97 ASM_STAC 984: movl -7(%_ASM_AX),%edx 995: movl -3(%_ASM_AX),%ecx 100 xor %eax,%eax 101 ASM_CLAC 102 ret 103#endif 104ENDPROC(__get_user_8) 105EXPORT_SYMBOL(__get_user_8) 106 107 108bad_get_user: 109 xor %edx,%edx 110 mov $(-EFAULT),%_ASM_AX 111 ASM_CLAC 112 ret 113END(bad_get_user) 114 115#ifdef CONFIG_X86_32 116bad_get_user_8: 117 xor %edx,%edx 118 xor %ecx,%ecx 119 mov $(-EFAULT),%_ASM_AX 120 ASM_CLAC 121 ret 122END(bad_get_user_8) 123#endif 124 125 _ASM_EXTABLE(1b,bad_get_user) 126 _ASM_EXTABLE(2b,bad_get_user) 127 _ASM_EXTABLE(3b,bad_get_user) 128#ifdef CONFIG_X86_64 129 _ASM_EXTABLE(4b,bad_get_user) 130#else 131 _ASM_EXTABLE(4b,bad_get_user_8) 132 _ASM_EXTABLE(5b,bad_get_user_8) 133#endif 134