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

TOMOYO Linux Cross Reference
Linux/arch/mips/include/asm/uaccess.h

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ 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 /*
  2  * This file is subject to the terms and conditions of the GNU General Public
  3  * License.  See the file "COPYING" in the main directory of this archive
  4  * for more details.
  5  *
  6  * Copyright (C) 1996, 1997, 1998, 1999, 2000, 03, 04 by Ralf Baechle
  7  * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
  8  * Copyright (C) 2007  Maciej W. Rozycki
  9  * Copyright (C) 2014, Imagination Technologies Ltd.
 10  */
 11 #ifndef _ASM_UACCESS_H
 12 #define _ASM_UACCESS_H
 13 
 14 #include <linux/kernel.h>
 15 #include <linux/string.h>
 16 #include <asm/asm-eva.h>
 17 #include <asm/extable.h>
 18 
 19 #ifdef CONFIG_32BIT
 20 
 21 #define __UA_LIMIT 0x80000000UL
 22 #define TASK_SIZE_MAX   KSEG0
 23 
 24 #define __UA_ADDR       ".word"
 25 #define __UA_LA         "la"
 26 #define __UA_ADDU       "addu"
 27 #define __UA_t0         "$8"
 28 #define __UA_t1         "$9"
 29 
 30 #endif /* CONFIG_32BIT */
 31 
 32 #ifdef CONFIG_64BIT
 33 
 34 extern u64 __ua_limit;
 35 
 36 #define __UA_LIMIT      __ua_limit
 37 #define TASK_SIZE_MAX   XKSSEG
 38 
 39 #define __UA_ADDR       ".dword"
 40 #define __UA_LA         "dla"
 41 #define __UA_ADDU       "daddu"
 42 #define __UA_t0         "$12"
 43 #define __UA_t1         "$13"
 44 
 45 #endif /* CONFIG_64BIT */
 46 
 47 #include <asm-generic/access_ok.h>
 48 
 49 /*
 50  * put_user: - Write a simple value into user space.
 51  * @x:   Value to copy to user space.
 52  * @ptr: Destination address, in user space.
 53  *
 54  * Context: User context only. This function may sleep if pagefaults are
 55  *          enabled.
 56  *
 57  * This macro copies a single simple value from kernel space to user
 58  * space.  It supports simple types like char and int, but not larger
 59  * data types like structures or arrays.
 60  *
 61  * @ptr must have pointer-to-simple-variable type, and @x must be assignable
 62  * to the result of dereferencing @ptr.
 63  *
 64  * Returns zero on success, or -EFAULT on error.
 65  */
 66 #define put_user(x, ptr)                                                \
 67 ({                                                                      \
 68         __typeof__(*(ptr)) __user *__p = (ptr);                         \
 69                                                                         \
 70         might_fault();                                                  \
 71         access_ok(__p, sizeof(*__p)) ? __put_user((x), __p) : -EFAULT;  \
 72 })
 73 
 74 /*
 75  * get_user: - Get a simple variable from user space.
 76  * @x:   Variable to store result.
 77  * @ptr: Source address, in user space.
 78  *
 79  * Context: User context only. This function may sleep if pagefaults are
 80  *          enabled.
 81  *
 82  * This macro copies a single simple variable from user space to kernel
 83  * space.  It supports simple types like char and int, but not larger
 84  * data types like structures or arrays.
 85  *
 86  * @ptr must have pointer-to-simple-variable type, and the result of
 87  * dereferencing @ptr must be assignable to @x without a cast.
 88  *
 89  * Returns zero on success, or -EFAULT on error.
 90  * On error, the variable @x is set to zero.
 91  */
 92 #define get_user(x, ptr)                                                \
 93 ({                                                                      \
 94         const __typeof__(*(ptr)) __user *__p = (ptr);                   \
 95                                                                         \
 96         might_fault();                                                  \
 97         access_ok(__p, sizeof(*__p)) ? __get_user((x), __p) :           \
 98                                        ((x) = 0, -EFAULT);              \
 99 })
100 
101 /*
102  * __put_user: - Write a simple value into user space, with less checking.
103  * @x:   Value to copy to user space.
104  * @ptr: Destination address, in user space.
105  *
106  * Context: User context only. This function may sleep if pagefaults are
107  *          enabled.
108  *
109  * This macro copies a single simple value from kernel space to user
110  * space.  It supports simple types like char and int, but not larger
111  * data types like structures or arrays.
112  *
113  * @ptr must have pointer-to-simple-variable type, and @x must be assignable
114  * to the result of dereferencing @ptr.
115  *
116  * Caller must check the pointer with access_ok() before calling this
117  * function.
118  *
119  * Returns zero on success, or -EFAULT on error.
120  */
121 #define __put_user(x, ptr)                                              \
122 ({                                                                      \
123         __typeof__(*(ptr)) __user *__pu_ptr = (ptr);                    \
124         __typeof__(*(ptr)) __pu_val = (x);                              \
125         int __pu_err = 0;                                               \
126                                                                         \
127         __chk_user_ptr(__pu_ptr);                                       \
128         switch (sizeof(*__pu_ptr)) {                                    \
129         case 1:                                                         \
130                 __put_data_asm(user_sb, __pu_ptr);                      \
131                 break;                                                  \
132         case 2:                                                         \
133                 __put_data_asm(user_sh, __pu_ptr);                      \
134                 break;                                                  \
135         case 4:                                                         \
136                 __put_data_asm(user_sw, __pu_ptr);                      \
137                 break;                                                  \
138         case 8:                                                         \
139                 __PUT_DW(user_sd, __pu_ptr);                            \
140                 break;                                                  \
141         default:                                                        \
142                 BUILD_BUG();                                            \
143         }                                                               \
144                                                                         \
145         __pu_err;                                                       \
146 })
147 
148 /*
149  * __get_user: - Get a simple variable from user space, with less checking.
150  * @x:   Variable to store result.
151  * @ptr: Source address, in user space.
152  *
153  * Context: User context only. This function may sleep if pagefaults are
154  *          enabled.
155  *
156  * This macro copies a single simple variable from user space to kernel
157  * space.  It supports simple types like char and int, but not larger
158  * data types like structures or arrays.
159  *
160  * @ptr must have pointer-to-simple-variable type, and the result of
161  * dereferencing @ptr must be assignable to @x without a cast.
162  *
163  * Caller must check the pointer with access_ok() before calling this
164  * function.
165  *
166  * Returns zero on success, or -EFAULT on error.
167  * On error, the variable @x is set to zero.
168  */
169 #define __get_user(x, ptr)                                              \
170 ({                                                                      \
171         const __typeof__(*(ptr)) __user *__gu_ptr = (ptr);              \
172         int __gu_err = 0;                                               \
173                                                                         \
174         __chk_user_ptr(__gu_ptr);                                       \
175         switch (sizeof(*__gu_ptr)) {                                    \
176         case 1:                                                         \
177                 __get_data_asm((x), user_lb, __gu_ptr);                 \
178                 break;                                                  \
179         case 2:                                                         \
180                 __get_data_asm((x), user_lh, __gu_ptr);                 \
181                 break;                                                  \
182         case 4:                                                         \
183                 __get_data_asm((x), user_lw, __gu_ptr);                 \
184                 break;                                                  \
185         case 8:                                                         \
186                 __GET_DW((x), user_ld, __gu_ptr);                       \
187                 break;                                                  \
188         default:                                                        \
189                 BUILD_BUG();                                            \
190         }                                                               \
191                                                                         \
192         __gu_err;                                                       \
193 })
194 
195 struct __large_struct { unsigned long buf[100]; };
196 #define __m(x) (*(struct __large_struct __user *)(x))
197 
198 #ifdef CONFIG_32BIT
199 #define __GET_DW(val, insn, ptr) __get_data_asm_ll32(val, insn, ptr)
200 #endif
201 #ifdef CONFIG_64BIT
202 #define __GET_DW(val, insn, ptr) __get_data_asm(val, insn, ptr)
203 #endif
204 
205 #define __get_data_asm(val, insn, addr)                                 \
206 {                                                                       \
207         long __gu_tmp;                                                  \
208                                                                         \
209         __asm__ __volatile__(                                           \
210         "1:     "insn("%1", "%3")"                              \n"     \
211         "2:                                                     \n"     \
212         "       .insn                                           \n"     \
213         "       .section .fixup,\"ax\"                          \n"     \
214         "3:     li      %0, %4                                  \n"     \
215         "       move    %1, $0                                  \n"     \
216         "       j       2b                                      \n"     \
217         "       .previous                                       \n"     \
218         "       .section __ex_table,\"a\"                       \n"     \
219         "       "__UA_ADDR "\t1b, 3b                            \n"     \
220         "       .previous                                       \n"     \
221         : "=r" (__gu_err), "=r" (__gu_tmp)                              \
222         : "" (0), "o" (__m(addr)), "i" (-EFAULT));                     \
223                                                                         \
224         (val) = (__typeof__(*(addr))) __gu_tmp;                         \
225 }
226 
227 /*
228  * Get a long long 64 using 32 bit registers.
229  */
230 #define __get_data_asm_ll32(val, insn, addr)                            \
231 {                                                                       \
232         union {                                                         \
233                 unsigned long long      l;                              \
234                 __typeof__(*(addr))     t;                              \
235         } __gu_tmp;                                                     \
236                                                                         \
237         __asm__ __volatile__(                                           \
238         "1:     " insn("%1", "(%3)")"                           \n"     \
239         "2:     " insn("%D1", "4(%3)")"                         \n"     \
240         "3:                                                     \n"     \
241         "       .insn                                           \n"     \
242         "       .section        .fixup,\"ax\"                   \n"     \
243         "4:     li      %0, %4                                  \n"     \
244         "       move    %1, $0                                  \n"     \
245         "       move    %D1, $0                                 \n"     \
246         "       j       3b                                      \n"     \
247         "       .previous                                       \n"     \
248         "       .section        __ex_table,\"a\"                \n"     \
249         "       " __UA_ADDR "   1b, 4b                          \n"     \
250         "       " __UA_ADDR "   2b, 4b                          \n"     \
251         "       .previous                                       \n"     \
252         : "=r" (__gu_err), "=&r" (__gu_tmp.l)                           \
253         : "" (0), "r" (addr), "i" (-EFAULT));                          \
254                                                                         \
255         (val) = __gu_tmp.t;                                             \
256 }
257 
258 #define __get_kernel_nofault(dst, src, type, err_label)                 \
259 do {                                                                    \
260         int __gu_err;                                                   \
261                                                                         \
262         switch (sizeof(type)) {                                         \
263         case 1:                                                         \
264                 __get_data_asm(*(type *)(dst), kernel_lb,               \
265                                (__force type *)(src));                  \
266                 break;                                                  \
267         case 2:                                                         \
268                 __get_data_asm(*(type *)(dst), kernel_lh,               \
269                                (__force type *)(src));                  \
270                 break;                                                  \
271         case 4:                                                         \
272                  __get_data_asm(*(type *)(dst), kernel_lw,              \
273                                (__force type *)(src));                  \
274                 break;                                                  \
275         case 8:                                                         \
276                 __GET_DW(*(type *)(dst), kernel_ld,                     \
277                          (__force type *)(src));                        \
278                 break;                                                  \
279         default:                                                        \
280                 BUILD_BUG();                                            \
281                 break;                                                  \
282         }                                                               \
283         if (unlikely(__gu_err))                                         \
284                 goto err_label;                                         \
285 } while (0)
286 
287 /*
288  * Yuck.  We need two variants, one for 64bit operation and one
289  * for 32 bit mode and old iron.
290  */
291 #ifdef CONFIG_32BIT
292 #define __PUT_DW(insn, ptr) __put_data_asm_ll32(insn, ptr)
293 #endif
294 #ifdef CONFIG_64BIT
295 #define __PUT_DW(insn, ptr) __put_data_asm(insn, ptr)
296 #endif
297 
298 #define __put_data_asm(insn, ptr)                                       \
299 {                                                                       \
300         __asm__ __volatile__(                                           \
301         "1:     "insn("%z2", "%3")"     # __put_data_asm        \n"     \
302         "2:                                                     \n"     \
303         "       .insn                                           \n"     \
304         "       .section        .fixup,\"ax\"                   \n"     \
305         "3:     li      %0, %4                                  \n"     \
306         "       j       2b                                      \n"     \
307         "       .previous                                       \n"     \
308         "       .section        __ex_table,\"a\"                \n"     \
309         "       " __UA_ADDR "   1b, 3b                          \n"     \
310         "       .previous                                       \n"     \
311         : "=r" (__pu_err)                                               \
312         : "" (0), "Jr" (__pu_val), "o" (__m(ptr)),                     \
313           "i" (-EFAULT));                                               \
314 }
315 
316 #define __put_data_asm_ll32(insn, ptr)                                  \
317 {                                                                       \
318         __asm__ __volatile__(                                           \
319         "1:     "insn("%2", "(%3)")"    # __put_data_asm_ll32   \n"     \
320         "2:     "insn("%D2", "4(%3)")"                          \n"     \
321         "3:                                                     \n"     \
322         "       .insn                                           \n"     \
323         "       .section        .fixup,\"ax\"                   \n"     \
324         "4:     li      %0, %4                                  \n"     \
325         "       j       3b                                      \n"     \
326         "       .previous                                       \n"     \
327         "       .section        __ex_table,\"a\"                \n"     \
328         "       " __UA_ADDR "   1b, 4b                          \n"     \
329         "       " __UA_ADDR "   2b, 4b                          \n"     \
330         "       .previous"                                              \
331         : "=r" (__pu_err)                                               \
332         : "" (0), "r" (__pu_val), "r" (ptr),                           \
333           "i" (-EFAULT));                                               \
334 }
335 
336 #define __put_kernel_nofault(dst, src, type, err_label)                 \
337 do {                                                                    \
338         type __pu_val;                                  \
339         int __pu_err = 0;                                               \
340                                                                         \
341         __pu_val = *(__force type *)(src);                              \
342         switch (sizeof(type)) {                                         \
343         case 1:                                                         \
344                 __put_data_asm(kernel_sb, (type *)(dst));               \
345                 break;                                                  \
346         case 2:                                                         \
347                 __put_data_asm(kernel_sh, (type *)(dst));               \
348                 break;                                                  \
349         case 4:                                                         \
350                 __put_data_asm(kernel_sw, (type *)(dst))                \
351                 break;                                                  \
352         case 8:                                                         \
353                 __PUT_DW(kernel_sd, (type *)(dst));                     \
354                 break;                                                  \
355         default:                                                        \
356                 BUILD_BUG();                                            \
357                 break;                                                  \
358         }                                                               \
359         if (unlikely(__pu_err))                                         \
360                 goto err_label;                                         \
361 } while (0)
362 
363 
364 /*
365  * We're generating jump to subroutines which will be outside the range of
366  * jump instructions
367  */
368 #ifdef MODULE
369 #define __MODULE_JAL(destination)                                       \
370         ".set\tnoat\n\t"                                                \
371         __UA_LA "\t$1, " #destination "\n\t"                            \
372         "jalr\t$1\n\t"                                                  \
373         ".set\tat\n\t"
374 #else
375 #define __MODULE_JAL(destination)                                       \
376         "jal\t" #destination "\n\t"
377 #endif
378 
379 #if defined(CONFIG_CPU_DADDI_WORKAROUNDS) || (defined(CONFIG_EVA) &&    \
380                                               defined(CONFIG_CPU_HAS_PREFETCH))
381 #define DADDI_SCRATCH "$3"
382 #else
383 #define DADDI_SCRATCH "$0"
384 #endif
385 
386 extern size_t __raw_copy_from_user(void *__to, const void *__from, size_t __n);
387 extern size_t __raw_copy_to_user(void *__to, const void *__from, size_t __n);
388 
389 static inline unsigned long
390 raw_copy_from_user(void *to, const void __user *from, unsigned long n)
391 {
392         register void *__cu_to_r __asm__("$4");
393         register const void __user *__cu_from_r __asm__("$5");
394         register long __cu_len_r __asm__("$6");
395 
396         __cu_to_r = to;
397         __cu_from_r = from;
398         __cu_len_r = n;
399 
400         __asm__ __volatile__(
401                 ".set\tnoreorder\n\t"
402                 __MODULE_JAL(__raw_copy_from_user)
403                 ".set\tnoat\n\t"
404                 __UA_ADDU "\t$1, %1, %2\n\t"
405                 ".set\tat\n\t"
406                 ".set\treorder"
407                 : "+r" (__cu_to_r), "+r" (__cu_from_r), "+r" (__cu_len_r)
408                 :
409                 : "$8", "$9", "$10", "$11", "$12", "$14", "$15", "$24", "$31",
410                   DADDI_SCRATCH, "memory");
411 
412         return __cu_len_r;
413 }
414 
415 static inline unsigned long
416 raw_copy_to_user(void __user *to, const void *from, unsigned long n)
417 {
418         register void __user *__cu_to_r __asm__("$4");
419         register const void *__cu_from_r __asm__("$5");
420         register long __cu_len_r __asm__("$6");
421 
422         __cu_to_r = (to);
423         __cu_from_r = (from);
424         __cu_len_r = (n);
425 
426         __asm__ __volatile__(
427                 __MODULE_JAL(__raw_copy_to_user)
428                 : "+r" (__cu_to_r), "+r" (__cu_from_r), "+r" (__cu_len_r)
429                 :
430                 : "$8", "$9", "$10", "$11", "$12", "$14", "$15", "$24", "$31",
431                   DADDI_SCRATCH, "memory");
432 
433         return __cu_len_r;
434 }
435 
436 #define INLINE_COPY_FROM_USER
437 #define INLINE_COPY_TO_USER
438 
439 extern __kernel_size_t __bzero(void __user *addr, __kernel_size_t size);
440 
441 /*
442  * __clear_user: - Zero a block of memory in user space, with less checking.
443  * @to:   Destination address, in user space.
444  * @n:    Number of bytes to zero.
445  *
446  * Zero a block of memory in user space.  Caller must check
447  * the specified block with access_ok() before calling this function.
448  *
449  * Returns number of bytes that could not be cleared.
450  * On success, this will be zero.
451  */
452 static inline __kernel_size_t
453 __clear_user(void __user *addr, __kernel_size_t size)
454 {
455         __kernel_size_t res;
456 
457 #ifdef CONFIG_CPU_MICROMIPS
458 /* micromips memset / bzero also clobbers t7 & t8 */
459 #define bzero_clobbers "$4", "$5", "$6", __UA_t0, __UA_t1, "$15", "$24", "$31"
460 #else
461 #define bzero_clobbers "$4", "$5", "$6", __UA_t0, __UA_t1, "$31"
462 #endif /* CONFIG_CPU_MICROMIPS */
463 
464         might_fault();
465         __asm__ __volatile__(
466                 "move\t$4, %1\n\t"
467                 "move\t$5, $0\n\t"
468                 "move\t$6, %2\n\t"
469                 __MODULE_JAL(__bzero)
470                 "move\t%0, $6"
471                 : "=r" (res)
472                 : "r" (addr), "r" (size)
473                 : bzero_clobbers);
474 
475         return res;
476 }
477 
478 #define clear_user(addr,n)                                              \
479 ({                                                                      \
480         void __user * __cl_addr = (addr);                               \
481         unsigned long __cl_size = (n);                                  \
482         if (__cl_size && access_ok(__cl_addr, __cl_size))               \
483                 __cl_size = __clear_user(__cl_addr, __cl_size);         \
484         __cl_size;                                                      \
485 })
486 
487 extern long __strncpy_from_user_asm(char *__to, const char __user *__from, long __len);
488 
489 /*
490  * strncpy_from_user: - Copy a NUL terminated string from userspace.
491  * @dst:   Destination address, in kernel space.  This buffer must be at
492  *         least @count bytes long.
493  * @src:   Source address, in user space.
494  * @count: Maximum number of bytes to copy, including the trailing NUL.
495  *
496  * Copies a NUL-terminated string from userspace to kernel space.
497  *
498  * On success, returns the length of the string (not including the trailing
499  * NUL).
500  *
501  * If access to userspace fails, returns -EFAULT (some data may have been
502  * copied).
503  *
504  * If @count is smaller than the length of the string, copies @count bytes
505  * and returns @count.
506  */
507 static inline long
508 strncpy_from_user(char *__to, const char __user *__from, long __len)
509 {
510         long res;
511 
512         if (!access_ok(__from, __len))
513                 return -EFAULT;
514 
515         might_fault();
516         __asm__ __volatile__(
517                 "move\t$4, %1\n\t"
518                 "move\t$5, %2\n\t"
519                 "move\t$6, %3\n\t"
520                 __MODULE_JAL(__strncpy_from_user_asm)
521                 "move\t%0, $2"
522                 : "=r" (res)
523                 : "r" (__to), "r" (__from), "r" (__len)
524                 : "$2", "$3", "$4", "$5", "$6", __UA_t0, "$31", "memory");
525 
526         return res;
527 }
528 
529 extern long __strnlen_user_asm(const char __user *s, long n);
530 
531 /*
532  * strnlen_user: - Get the size of a string in user space.
533  * @str: The string to measure.
534  *
535  * Context: User context only. This function may sleep if pagefaults are
536  *          enabled.
537  *
538  * Get the size of a NUL-terminated string in user space.
539  *
540  * Returns the size of the string INCLUDING the terminating NUL.
541  * On exception, returns 0.
542  * If the string is too long, returns a value greater than @n.
543  */
544 static inline long strnlen_user(const char __user *s, long n)
545 {
546         long res;
547 
548         if (!access_ok(s, 1))
549                 return 0;
550 
551         might_fault();
552         __asm__ __volatile__(
553                 "move\t$4, %1\n\t"
554                 "move\t$5, %2\n\t"
555                 __MODULE_JAL(__strnlen_user_asm)
556                 "move\t%0, $2"
557                 : "=r" (res)
558                 : "r" (s), "r" (n)
559                 : "$2", "$4", "$5", __UA_t0, "$31");
560 
561         return res;
562 }
563 
564 #endif /* _ASM_UACCESS_H */
565 

~ [ 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