~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/x86/lib/usercopy_32.c

Version: ~ [ linux-6.11-rc3 ] ~ [ linux-6.10.4 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.45 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.104 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.164 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.223 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.281 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.319 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php