xref: /openbmc/linux/arch/x86/lib/usercopy_32.c (revision cfbb9be8)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * User address space access functions.
4  * The non inlined parts of asm-i386/uaccess.h are here.
5  *
6  * Copyright 1997 Andi Kleen <ak@muc.de>
7  * Copyright 1997 Linus Torvalds
8  */
9 #include <linux/export.h>
10 #include <linux/uaccess.h>
11 #include <asm/mmx.h>
12 #include <asm/asm.h>
13 
14 #ifdef CONFIG_X86_INTEL_USERCOPY
15 /*
16  * Alignment at which movsl is preferred for bulk memory copies.
17  */
18 struct movsl_mask movsl_mask __read_mostly;
19 #endif
20 
21 static inline int __movsl_is_ok(unsigned long a1, unsigned long a2, unsigned long n)
22 {
23 #ifdef CONFIG_X86_INTEL_USERCOPY
24 	if (n >= 64 && ((a1 ^ a2) & movsl_mask.mask))
25 		return 0;
26 #endif
27 	return 1;
28 }
29 #define movsl_is_ok(a1, a2, n) \
30 	__movsl_is_ok((unsigned long)(a1), (unsigned long)(a2), (n))
31 
32 /*
33  * Zero Userspace
34  */
35 
36 #define __do_clear_user(addr,size)					\
37 do {									\
38 	int __d0;							\
39 	might_fault();							\
40 	__asm__ __volatile__(						\
41 		ASM_STAC "\n"						\
42 		"0:	rep; stosl\n"					\
43 		"	movl %2,%0\n"					\
44 		"1:	rep; stosb\n"					\
45 		"2: " ASM_CLAC "\n"					\
46 		".section .fixup,\"ax\"\n"				\
47 		"3:	lea 0(%2,%0,4),%0\n"				\
48 		"	jmp 2b\n"					\
49 		".previous\n"						\
50 		_ASM_EXTABLE(0b,3b)					\
51 		_ASM_EXTABLE(1b,2b)					\
52 		: "=&c"(size), "=&D" (__d0)				\
53 		: "r"(size & 3), "0"(size / 4), "1"(addr), "a"(0));	\
54 } while (0)
55 
56 /**
57  * clear_user: - Zero a block of memory in user space.
58  * @to:   Destination address, in user space.
59  * @n:    Number of bytes to zero.
60  *
61  * Zero a block of memory in user space.
62  *
63  * Returns number of bytes that could not be cleared.
64  * On success, this will be zero.
65  */
66 unsigned long
67 clear_user(void __user *to, unsigned long n)
68 {
69 	might_fault();
70 	if (access_ok(VERIFY_WRITE, to, n))
71 		__do_clear_user(to, n);
72 	return n;
73 }
74 EXPORT_SYMBOL(clear_user);
75 
76 /**
77  * __clear_user: - Zero a block of memory in user space, with less checking.
78  * @to:   Destination address, in user space.
79  * @n:    Number of bytes to zero.
80  *
81  * Zero a block of memory in user space.  Caller must check
82  * the specified block with access_ok() before calling this function.
83  *
84  * Returns number of bytes that could not be cleared.
85  * On success, this will be zero.
86  */
87 unsigned long
88 __clear_user(void __user *to, unsigned long n)
89 {
90 	__do_clear_user(to, n);
91 	return n;
92 }
93 EXPORT_SYMBOL(__clear_user);
94 
95 #ifdef CONFIG_X86_INTEL_USERCOPY
96 static unsigned long
97 __copy_user_intel(void __user *to, const void *from, unsigned long size)
98 {
99 	int d0, d1;
100 	__asm__ __volatile__(
101 		       "       .align 2,0x90\n"
102 		       "1:     movl 32(%4), %%eax\n"
103 		       "       cmpl $67, %0\n"
104 		       "       jbe 3f\n"
105 		       "2:     movl 64(%4), %%eax\n"
106 		       "       .align 2,0x90\n"
107 		       "3:     movl 0(%4), %%eax\n"
108 		       "4:     movl 4(%4), %%edx\n"
109 		       "5:     movl %%eax, 0(%3)\n"
110 		       "6:     movl %%edx, 4(%3)\n"
111 		       "7:     movl 8(%4), %%eax\n"
112 		       "8:     movl 12(%4),%%edx\n"
113 		       "9:     movl %%eax, 8(%3)\n"
114 		       "10:    movl %%edx, 12(%3)\n"
115 		       "11:    movl 16(%4), %%eax\n"
116 		       "12:    movl 20(%4), %%edx\n"
117 		       "13:    movl %%eax, 16(%3)\n"
118 		       "14:    movl %%edx, 20(%3)\n"
119 		       "15:    movl 24(%4), %%eax\n"
120 		       "16:    movl 28(%4), %%edx\n"
121 		       "17:    movl %%eax, 24(%3)\n"
122 		       "18:    movl %%edx, 28(%3)\n"
123 		       "19:    movl 32(%4), %%eax\n"
124 		       "20:    movl 36(%4), %%edx\n"
125 		       "21:    movl %%eax, 32(%3)\n"
126 		       "22:    movl %%edx, 36(%3)\n"
127 		       "23:    movl 40(%4), %%eax\n"
128 		       "24:    movl 44(%4), %%edx\n"
129 		       "25:    movl %%eax, 40(%3)\n"
130 		       "26:    movl %%edx, 44(%3)\n"
131 		       "27:    movl 48(%4), %%eax\n"
132 		       "28:    movl 52(%4), %%edx\n"
133 		       "29:    movl %%eax, 48(%3)\n"
134 		       "30:    movl %%edx, 52(%3)\n"
135 		       "31:    movl 56(%4), %%eax\n"
136 		       "32:    movl 60(%4), %%edx\n"
137 		       "33:    movl %%eax, 56(%3)\n"
138 		       "34:    movl %%edx, 60(%3)\n"
139 		       "       addl $-64, %0\n"
140 		       "       addl $64, %4\n"
141 		       "       addl $64, %3\n"
142 		       "       cmpl $63, %0\n"
143 		       "       ja  1b\n"
144 		       "35:    movl  %0, %%eax\n"
145 		       "       shrl  $2, %0\n"
146 		       "       andl  $3, %%eax\n"
147 		       "       cld\n"
148 		       "99:    rep; movsl\n"
149 		       "36:    movl %%eax, %0\n"
150 		       "37:    rep; movsb\n"
151 		       "100:\n"
152 		       ".section .fixup,\"ax\"\n"
153 		       "101:   lea 0(%%eax,%0,4),%0\n"
154 		       "       jmp 100b\n"
155 		       ".previous\n"
156 		       _ASM_EXTABLE(1b,100b)
157 		       _ASM_EXTABLE(2b,100b)
158 		       _ASM_EXTABLE(3b,100b)
159 		       _ASM_EXTABLE(4b,100b)
160 		       _ASM_EXTABLE(5b,100b)
161 		       _ASM_EXTABLE(6b,100b)
162 		       _ASM_EXTABLE(7b,100b)
163 		       _ASM_EXTABLE(8b,100b)
164 		       _ASM_EXTABLE(9b,100b)
165 		       _ASM_EXTABLE(10b,100b)
166 		       _ASM_EXTABLE(11b,100b)
167 		       _ASM_EXTABLE(12b,100b)
168 		       _ASM_EXTABLE(13b,100b)
169 		       _ASM_EXTABLE(14b,100b)
170 		       _ASM_EXTABLE(15b,100b)
171 		       _ASM_EXTABLE(16b,100b)
172 		       _ASM_EXTABLE(17b,100b)
173 		       _ASM_EXTABLE(18b,100b)
174 		       _ASM_EXTABLE(19b,100b)
175 		       _ASM_EXTABLE(20b,100b)
176 		       _ASM_EXTABLE(21b,100b)
177 		       _ASM_EXTABLE(22b,100b)
178 		       _ASM_EXTABLE(23b,100b)
179 		       _ASM_EXTABLE(24b,100b)
180 		       _ASM_EXTABLE(25b,100b)
181 		       _ASM_EXTABLE(26b,100b)
182 		       _ASM_EXTABLE(27b,100b)
183 		       _ASM_EXTABLE(28b,100b)
184 		       _ASM_EXTABLE(29b,100b)
185 		       _ASM_EXTABLE(30b,100b)
186 		       _ASM_EXTABLE(31b,100b)
187 		       _ASM_EXTABLE(32b,100b)
188 		       _ASM_EXTABLE(33b,100b)
189 		       _ASM_EXTABLE(34b,100b)
190 		       _ASM_EXTABLE(35b,100b)
191 		       _ASM_EXTABLE(36b,100b)
192 		       _ASM_EXTABLE(37b,100b)
193 		       _ASM_EXTABLE(99b,101b)
194 		       : "=&c"(size), "=&D" (d0), "=&S" (d1)
195 		       :  "1"(to), "2"(from), "0"(size)
196 		       : "eax", "edx", "memory");
197 	return size;
198 }
199 
200 static unsigned long __copy_user_intel_nocache(void *to,
201 				const void __user *from, unsigned long size)
202 {
203 	int d0, d1;
204 
205 	__asm__ __volatile__(
206 	       "        .align 2,0x90\n"
207 	       "0:      movl 32(%4), %%eax\n"
208 	       "        cmpl $67, %0\n"
209 	       "        jbe 2f\n"
210 	       "1:      movl 64(%4), %%eax\n"
211 	       "        .align 2,0x90\n"
212 	       "2:      movl 0(%4), %%eax\n"
213 	       "21:     movl 4(%4), %%edx\n"
214 	       "        movnti %%eax, 0(%3)\n"
215 	       "        movnti %%edx, 4(%3)\n"
216 	       "3:      movl 8(%4), %%eax\n"
217 	       "31:     movl 12(%4),%%edx\n"
218 	       "        movnti %%eax, 8(%3)\n"
219 	       "        movnti %%edx, 12(%3)\n"
220 	       "4:      movl 16(%4), %%eax\n"
221 	       "41:     movl 20(%4), %%edx\n"
222 	       "        movnti %%eax, 16(%3)\n"
223 	       "        movnti %%edx, 20(%3)\n"
224 	       "10:     movl 24(%4), %%eax\n"
225 	       "51:     movl 28(%4), %%edx\n"
226 	       "        movnti %%eax, 24(%3)\n"
227 	       "        movnti %%edx, 28(%3)\n"
228 	       "11:     movl 32(%4), %%eax\n"
229 	       "61:     movl 36(%4), %%edx\n"
230 	       "        movnti %%eax, 32(%3)\n"
231 	       "        movnti %%edx, 36(%3)\n"
232 	       "12:     movl 40(%4), %%eax\n"
233 	       "71:     movl 44(%4), %%edx\n"
234 	       "        movnti %%eax, 40(%3)\n"
235 	       "        movnti %%edx, 44(%3)\n"
236 	       "13:     movl 48(%4), %%eax\n"
237 	       "81:     movl 52(%4), %%edx\n"
238 	       "        movnti %%eax, 48(%3)\n"
239 	       "        movnti %%edx, 52(%3)\n"
240 	       "14:     movl 56(%4), %%eax\n"
241 	       "91:     movl 60(%4), %%edx\n"
242 	       "        movnti %%eax, 56(%3)\n"
243 	       "        movnti %%edx, 60(%3)\n"
244 	       "        addl $-64, %0\n"
245 	       "        addl $64, %4\n"
246 	       "        addl $64, %3\n"
247 	       "        cmpl $63, %0\n"
248 	       "        ja  0b\n"
249 	       "        sfence \n"
250 	       "5:      movl  %0, %%eax\n"
251 	       "        shrl  $2, %0\n"
252 	       "        andl $3, %%eax\n"
253 	       "        cld\n"
254 	       "6:      rep; movsl\n"
255 	       "        movl %%eax,%0\n"
256 	       "7:      rep; movsb\n"
257 	       "8:\n"
258 	       ".section .fixup,\"ax\"\n"
259 	       "9:      lea 0(%%eax,%0,4),%0\n"
260 	       "16:     jmp 8b\n"
261 	       ".previous\n"
262 	       _ASM_EXTABLE(0b,16b)
263 	       _ASM_EXTABLE(1b,16b)
264 	       _ASM_EXTABLE(2b,16b)
265 	       _ASM_EXTABLE(21b,16b)
266 	       _ASM_EXTABLE(3b,16b)
267 	       _ASM_EXTABLE(31b,16b)
268 	       _ASM_EXTABLE(4b,16b)
269 	       _ASM_EXTABLE(41b,16b)
270 	       _ASM_EXTABLE(10b,16b)
271 	       _ASM_EXTABLE(51b,16b)
272 	       _ASM_EXTABLE(11b,16b)
273 	       _ASM_EXTABLE(61b,16b)
274 	       _ASM_EXTABLE(12b,16b)
275 	       _ASM_EXTABLE(71b,16b)
276 	       _ASM_EXTABLE(13b,16b)
277 	       _ASM_EXTABLE(81b,16b)
278 	       _ASM_EXTABLE(14b,16b)
279 	       _ASM_EXTABLE(91b,16b)
280 	       _ASM_EXTABLE(6b,9b)
281 	       _ASM_EXTABLE(7b,16b)
282 	       : "=&c"(size), "=&D" (d0), "=&S" (d1)
283 	       :  "1"(to), "2"(from), "0"(size)
284 	       : "eax", "edx", "memory");
285 	return size;
286 }
287 
288 #else
289 
290 /*
291  * Leave these declared but undefined.  They should not be any references to
292  * them
293  */
294 unsigned long __copy_user_intel(void __user *to, const void *from,
295 					unsigned long size);
296 #endif /* CONFIG_X86_INTEL_USERCOPY */
297 
298 /* Generic arbitrary sized copy.  */
299 #define __copy_user(to, from, size)					\
300 do {									\
301 	int __d0, __d1, __d2;						\
302 	__asm__ __volatile__(						\
303 		"	cmp  $7,%0\n"					\
304 		"	jbe  1f\n"					\
305 		"	movl %1,%0\n"					\
306 		"	negl %0\n"					\
307 		"	andl $7,%0\n"					\
308 		"	subl %0,%3\n"					\
309 		"4:	rep; movsb\n"					\
310 		"	movl %3,%0\n"					\
311 		"	shrl $2,%0\n"					\
312 		"	andl $3,%3\n"					\
313 		"	.align 2,0x90\n"				\
314 		"0:	rep; movsl\n"					\
315 		"	movl %3,%0\n"					\
316 		"1:	rep; movsb\n"					\
317 		"2:\n"							\
318 		".section .fixup,\"ax\"\n"				\
319 		"5:	addl %3,%0\n"					\
320 		"	jmp 2b\n"					\
321 		"3:	lea 0(%3,%0,4),%0\n"				\
322 		"	jmp 2b\n"					\
323 		".previous\n"						\
324 		_ASM_EXTABLE(4b,5b)					\
325 		_ASM_EXTABLE(0b,3b)					\
326 		_ASM_EXTABLE(1b,2b)					\
327 		: "=&c"(size), "=&D" (__d0), "=&S" (__d1), "=r"(__d2)	\
328 		: "3"(size), "0"(size), "1"(to), "2"(from)		\
329 		: "memory");						\
330 } while (0)
331 
332 unsigned long __copy_user_ll(void *to, const void *from, unsigned long n)
333 {
334 	__uaccess_begin_nospec();
335 	if (movsl_is_ok(to, from, n))
336 		__copy_user(to, from, n);
337 	else
338 		n = __copy_user_intel(to, from, n);
339 	__uaccess_end();
340 	return n;
341 }
342 EXPORT_SYMBOL(__copy_user_ll);
343 
344 unsigned long __copy_from_user_ll_nocache_nozero(void *to, const void __user *from,
345 					unsigned long n)
346 {
347 	__uaccess_begin_nospec();
348 #ifdef CONFIG_X86_INTEL_USERCOPY
349 	if (n > 64 && static_cpu_has(X86_FEATURE_XMM2))
350 		n = __copy_user_intel_nocache(to, from, n);
351 	else
352 		__copy_user(to, from, n);
353 #else
354 	__copy_user(to, from, n);
355 #endif
356 	__uaccess_end();
357 	return n;
358 }
359 EXPORT_SYMBOL(__copy_from_user_ll_nocache_nozero);
360