fs: Allow a NULL pos pointer to __kernel_read
[linux-2.6-microblaze.git] / arch / x86 / lib / getuser.S
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 #ifdef CONFIG_X86_5LEVEL
39 #define LOAD_TASK_SIZE_MINUS_N(n) \
40         ALTERNATIVE __stringify(mov $((1 << 47) - 4096 - (n)),%rdx), \
41                     __stringify(mov $((1 << 56) - 4096 - (n)),%rdx), X86_FEATURE_LA57
42 #else
43 #define LOAD_TASK_SIZE_MINUS_N(n) \
44         mov $(TASK_SIZE_MAX - (n)),%_ASM_DX
45 #endif
46
47         .text
48 SYM_FUNC_START(__get_user_1)
49         LOAD_TASK_SIZE_MINUS_N(0)
50         cmp %_ASM_DX,%_ASM_AX
51         jae bad_get_user
52         sbb %_ASM_DX, %_ASM_DX          /* array_index_mask_nospec() */
53         and %_ASM_DX, %_ASM_AX
54         ASM_STAC
55 1:      movzbl (%_ASM_AX),%edx
56         xor %eax,%eax
57         ASM_CLAC
58         ret
59 SYM_FUNC_END(__get_user_1)
60 EXPORT_SYMBOL(__get_user_1)
61
62 SYM_FUNC_START(__get_user_2)
63         LOAD_TASK_SIZE_MINUS_N(1)
64         cmp %_ASM_DX,%_ASM_AX
65         jae bad_get_user
66         sbb %_ASM_DX, %_ASM_DX          /* array_index_mask_nospec() */
67         and %_ASM_DX, %_ASM_AX
68         ASM_STAC
69 2:      movzwl (%_ASM_AX),%edx
70         xor %eax,%eax
71         ASM_CLAC
72         ret
73 SYM_FUNC_END(__get_user_2)
74 EXPORT_SYMBOL(__get_user_2)
75
76 SYM_FUNC_START(__get_user_4)
77         LOAD_TASK_SIZE_MINUS_N(3)
78         cmp %_ASM_DX,%_ASM_AX
79         jae bad_get_user
80         sbb %_ASM_DX, %_ASM_DX          /* array_index_mask_nospec() */
81         and %_ASM_DX, %_ASM_AX
82         ASM_STAC
83 3:      movl (%_ASM_AX),%edx
84         xor %eax,%eax
85         ASM_CLAC
86         ret
87 SYM_FUNC_END(__get_user_4)
88 EXPORT_SYMBOL(__get_user_4)
89
90 SYM_FUNC_START(__get_user_8)
91 #ifdef CONFIG_X86_64
92         LOAD_TASK_SIZE_MINUS_N(7)
93         cmp %_ASM_DX,%_ASM_AX
94         jae bad_get_user
95         sbb %_ASM_DX, %_ASM_DX          /* array_index_mask_nospec() */
96         and %_ASM_DX, %_ASM_AX
97         ASM_STAC
98 4:      movq (%_ASM_AX),%rdx
99         xor %eax,%eax
100         ASM_CLAC
101         ret
102 #else
103         LOAD_TASK_SIZE_MINUS_N(7)
104         cmp %_ASM_DX,%_ASM_AX
105         jae bad_get_user_8
106         sbb %_ASM_DX, %_ASM_DX          /* array_index_mask_nospec() */
107         and %_ASM_DX, %_ASM_AX
108         ASM_STAC
109 4:      movl (%_ASM_AX),%edx
110 5:      movl 4(%_ASM_AX),%ecx
111         xor %eax,%eax
112         ASM_CLAC
113         ret
114 #endif
115 SYM_FUNC_END(__get_user_8)
116 EXPORT_SYMBOL(__get_user_8)
117
118
119 SYM_CODE_START_LOCAL(.Lbad_get_user_clac)
120         ASM_CLAC
121 bad_get_user:
122         xor %edx,%edx
123         mov $(-EFAULT),%_ASM_AX
124         ret
125 SYM_CODE_END(.Lbad_get_user_clac)
126
127 #ifdef CONFIG_X86_32
128 SYM_CODE_START_LOCAL(.Lbad_get_user_8_clac)
129         ASM_CLAC
130 bad_get_user_8:
131         xor %edx,%edx
132         xor %ecx,%ecx
133         mov $(-EFAULT),%_ASM_AX
134         ret
135 SYM_CODE_END(.Lbad_get_user_8_clac)
136 #endif
137
138         _ASM_EXTABLE_UA(1b, .Lbad_get_user_clac)
139         _ASM_EXTABLE_UA(2b, .Lbad_get_user_clac)
140         _ASM_EXTABLE_UA(3b, .Lbad_get_user_clac)
141 #ifdef CONFIG_X86_64
142         _ASM_EXTABLE_UA(4b, .Lbad_get_user_clac)
143 #else
144         _ASM_EXTABLE_UA(4b, .Lbad_get_user_8_clac)
145         _ASM_EXTABLE_UA(5b, .Lbad_get_user_8_clac)
146 #endif