xref: /linux/arch/x86/lib/getuser.S (revision a3a4a816b4b194c45d0217e8b9e08b2639802cda)
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