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

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

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-only */
  2 /*
  3  * Copyright (C) 2012 Regents of the University of California
  4  *
  5  * This file was copied from include/asm-generic/uaccess.h
  6  */
  7 
  8 #ifndef _ASM_RISCV_UACCESS_H
  9 #define _ASM_RISCV_UACCESS_H
 10 
 11 #include <asm/asm-extable.h>
 12 #include <asm/pgtable.h>                /* for TASK_SIZE */
 13 
 14 /*
 15  * User space memory access functions
 16  */
 17 #ifdef CONFIG_MMU
 18 #include <linux/errno.h>
 19 #include <linux/compiler.h>
 20 #include <linux/thread_info.h>
 21 #include <asm/byteorder.h>
 22 #include <asm/extable.h>
 23 #include <asm/asm.h>
 24 #include <asm-generic/access_ok.h>
 25 
 26 #define __enable_user_access()                                                  \
 27         __asm__ __volatile__ ("csrs sstatus, %0" : : "r" (SR_SUM) : "memory")
 28 #define __disable_user_access()                                                 \
 29         __asm__ __volatile__ ("csrc sstatus, %0" : : "r" (SR_SUM) : "memory")
 30 
 31 /*
 32  * The exception table consists of pairs of addresses: the first is the
 33  * address of an instruction that is allowed to fault, and the second is
 34  * the address at which the program should continue.  No registers are
 35  * modified, so it is entirely up to the continuation code to figure out
 36  * what to do.
 37  *
 38  * All the routines below use bits of fixup code that are out of line
 39  * with the main instruction path.  This means when everything is well,
 40  * we don't even have to jump over them.  Further, they do not intrude
 41  * on our cache or tlb entries.
 42  */
 43 
 44 #define __LSW   0
 45 #define __MSW   1
 46 
 47 /*
 48  * The "__xxx" versions of the user access functions do not verify the address
 49  * space - it must have been done previously with a separate "access_ok()"
 50  * call.
 51  */
 52 
 53 #define __get_user_asm(insn, x, ptr, err)                       \
 54 do {                                                            \
 55         __typeof__(x) __x;                                      \
 56         __asm__ __volatile__ (                                  \
 57                 "1:\n"                                          \
 58                 "       " insn " %1, %2\n"                      \
 59                 "2:\n"                                          \
 60                 _ASM_EXTABLE_UACCESS_ERR_ZERO(1b, 2b, %0, %1)   \
 61                 : "+r" (err), "=&r" (__x)                       \
 62                 : "m" (*(ptr)));                                \
 63         (x) = __x;                                              \
 64 } while (0)
 65 
 66 #ifdef CONFIG_64BIT
 67 #define __get_user_8(x, ptr, err) \
 68         __get_user_asm("ld", x, ptr, err)
 69 #else /* !CONFIG_64BIT */
 70 #define __get_user_8(x, ptr, err)                               \
 71 do {                                                            \
 72         u32 __user *__ptr = (u32 __user *)(ptr);                \
 73         u32 __lo, __hi;                                         \
 74         __asm__ __volatile__ (                                  \
 75                 "1:\n"                                          \
 76                 "       lw %1, %3\n"                            \
 77                 "2:\n"                                          \
 78                 "       lw %2, %4\n"                            \
 79                 "3:\n"                                          \
 80                 _ASM_EXTABLE_UACCESS_ERR_ZERO(1b, 3b, %0, %1)   \
 81                 _ASM_EXTABLE_UACCESS_ERR_ZERO(2b, 3b, %0, %1)   \
 82                 : "+r" (err), "=&r" (__lo), "=r" (__hi)         \
 83                 : "m" (__ptr[__LSW]), "m" (__ptr[__MSW]));      \
 84         if (err)                                                \
 85                 __hi = 0;                                       \
 86         (x) = (__typeof__(x))((__typeof__((x)-(x)))(            \
 87                 (((u64)__hi << 32) | __lo)));                   \
 88 } while (0)
 89 #endif /* CONFIG_64BIT */
 90 
 91 #define __get_user_nocheck(x, __gu_ptr, __gu_err)               \
 92 do {                                                            \
 93         switch (sizeof(*__gu_ptr)) {                            \
 94         case 1:                                                 \
 95                 __get_user_asm("lb", (x), __gu_ptr, __gu_err);  \
 96                 break;                                          \
 97         case 2:                                                 \
 98                 __get_user_asm("lh", (x), __gu_ptr, __gu_err);  \
 99                 break;                                          \
100         case 4:                                                 \
101                 __get_user_asm("lw", (x), __gu_ptr, __gu_err);  \
102                 break;                                          \
103         case 8:                                                 \
104                 __get_user_8((x), __gu_ptr, __gu_err);  \
105                 break;                                          \
106         default:                                                \
107                 BUILD_BUG();                                    \
108         }                                                       \
109 } while (0)
110 
111 /**
112  * __get_user: - Get a simple variable from user space, with less checking.
113  * @x:   Variable to store result.
114  * @ptr: Source address, in user space.
115  *
116  * Context: User context only.  This function may sleep.
117  *
118  * This macro copies a single simple variable from user space to kernel
119  * space.  It supports simple types like char and int, but not larger
120  * data types like structures or arrays.
121  *
122  * @ptr must have pointer-to-simple-variable type, and the result of
123  * dereferencing @ptr must be assignable to @x without a cast.
124  *
125  * Caller must check the pointer with access_ok() before calling this
126  * function.
127  *
128  * Returns zero on success, or -EFAULT on error.
129  * On error, the variable @x is set to zero.
130  */
131 #define __get_user(x, ptr)                                      \
132 ({                                                              \
133         const __typeof__(*(ptr)) __user *__gu_ptr = (ptr);      \
134         long __gu_err = 0;                                      \
135                                                                 \
136         __chk_user_ptr(__gu_ptr);                               \
137                                                                 \
138         __enable_user_access();                                 \
139         __get_user_nocheck(x, __gu_ptr, __gu_err);              \
140         __disable_user_access();                                \
141                                                                 \
142         __gu_err;                                               \
143 })
144 
145 /**
146  * get_user: - Get a simple variable from user space.
147  * @x:   Variable to store result.
148  * @ptr: Source address, in user space.
149  *
150  * Context: User context only.  This function may sleep.
151  *
152  * This macro copies a single simple variable from user space to kernel
153  * space.  It supports simple types like char and int, but not larger
154  * data types like structures or arrays.
155  *
156  * @ptr must have pointer-to-simple-variable type, and the result of
157  * dereferencing @ptr must be assignable to @x without a cast.
158  *
159  * Returns zero on success, or -EFAULT on error.
160  * On error, the variable @x is set to zero.
161  */
162 #define get_user(x, ptr)                                        \
163 ({                                                              \
164         const __typeof__(*(ptr)) __user *__p = (ptr);           \
165         might_fault();                                          \
166         access_ok(__p, sizeof(*__p)) ?          \
167                 __get_user((x), __p) :                          \
168                 ((x) = (__force __typeof__(x))0, -EFAULT);      \
169 })
170 
171 #define __put_user_asm(insn, x, ptr, err)                       \
172 do {                                                            \
173         __typeof__(*(ptr)) __x = x;                             \
174         __asm__ __volatile__ (                                  \
175                 "1:\n"                                          \
176                 "       " insn " %z2, %1\n"                     \
177                 "2:\n"                                          \
178                 _ASM_EXTABLE_UACCESS_ERR(1b, 2b, %0)            \
179                 : "+r" (err), "=m" (*(ptr))                     \
180                 : "rJ" (__x));                                  \
181 } while (0)
182 
183 #ifdef CONFIG_64BIT
184 #define __put_user_8(x, ptr, err) \
185         __put_user_asm("sd", x, ptr, err)
186 #else /* !CONFIG_64BIT */
187 #define __put_user_8(x, ptr, err)                               \
188 do {                                                            \
189         u32 __user *__ptr = (u32 __user *)(ptr);                \
190         u64 __x = (__typeof__((x)-(x)))(x);                     \
191         __asm__ __volatile__ (                                  \
192                 "1:\n"                                          \
193                 "       sw %z3, %1\n"                           \
194                 "2:\n"                                          \
195                 "       sw %z4, %2\n"                           \
196                 "3:\n"                                          \
197                 _ASM_EXTABLE_UACCESS_ERR(1b, 3b, %0)            \
198                 _ASM_EXTABLE_UACCESS_ERR(2b, 3b, %0)            \
199                 : "+r" (err),                                   \
200                         "=m" (__ptr[__LSW]),                    \
201                         "=m" (__ptr[__MSW])                     \
202                 : "rJ" (__x), "rJ" (__x >> 32));                \
203 } while (0)
204 #endif /* CONFIG_64BIT */
205 
206 #define __put_user_nocheck(x, __gu_ptr, __pu_err)                                       \
207 do {                                                            \
208         switch (sizeof(*__gu_ptr)) {                            \
209         case 1:                                                 \
210                 __put_user_asm("sb", (x), __gu_ptr, __pu_err);  \
211                 break;                                          \
212         case 2:                                                 \
213                 __put_user_asm("sh", (x), __gu_ptr, __pu_err);  \
214                 break;                                          \
215         case 4:                                                 \
216                 __put_user_asm("sw", (x), __gu_ptr, __pu_err);  \
217                 break;                                          \
218         case 8:                                                 \
219                 __put_user_8((x), __gu_ptr, __pu_err);  \
220                 break;                                          \
221         default:                                                \
222                 BUILD_BUG();                                    \
223         }                                                       \
224 } while (0)
225 
226 /**
227  * __put_user: - Write a simple value into user space, with less checking.
228  * @x:   Value to copy to user space.
229  * @ptr: Destination address, in user space.
230  *
231  * Context: User context only.  This function may sleep.
232  *
233  * This macro copies a single simple value from kernel space to user
234  * space.  It supports simple types like char and int, but not larger
235  * data types like structures or arrays.
236  *
237  * @ptr must have pointer-to-simple-variable type, and @x must be assignable
238  * to the result of dereferencing @ptr. The value of @x is copied to avoid
239  * re-ordering where @x is evaluated inside the block that enables user-space
240  * access (thus bypassing user space protection if @x is a function).
241  *
242  * Caller must check the pointer with access_ok() before calling this
243  * function.
244  *
245  * Returns zero on success, or -EFAULT on error.
246  */
247 #define __put_user(x, ptr)                                      \
248 ({                                                              \
249         __typeof__(*(ptr)) __user *__gu_ptr = (ptr);            \
250         __typeof__(*__gu_ptr) __val = (x);                      \
251         long __pu_err = 0;                                      \
252                                                                 \
253         __chk_user_ptr(__gu_ptr);                               \
254                                                                 \
255         __enable_user_access();                                 \
256         __put_user_nocheck(__val, __gu_ptr, __pu_err);          \
257         __disable_user_access();                                \
258                                                                 \
259         __pu_err;                                               \
260 })
261 
262 /**
263  * put_user: - Write a simple value into user space.
264  * @x:   Value to copy to user space.
265  * @ptr: Destination address, in user space.
266  *
267  * Context: User context only.  This function may sleep.
268  *
269  * This macro copies a single simple value from kernel space to user
270  * space.  It supports simple types like char and int, but not larger
271  * data types like structures or arrays.
272  *
273  * @ptr must have pointer-to-simple-variable type, and @x must be assignable
274  * to the result of dereferencing @ptr.
275  *
276  * Returns zero on success, or -EFAULT on error.
277  */
278 #define put_user(x, ptr)                                        \
279 ({                                                              \
280         __typeof__(*(ptr)) __user *__p = (ptr);                 \
281         might_fault();                                          \
282         access_ok(__p, sizeof(*__p)) ?          \
283                 __put_user((x), __p) :                          \
284                 -EFAULT;                                        \
285 })
286 
287 
288 unsigned long __must_check __asm_copy_to_user(void __user *to,
289         const void *from, unsigned long n);
290 unsigned long __must_check __asm_copy_from_user(void *to,
291         const void __user *from, unsigned long n);
292 
293 static inline unsigned long
294 raw_copy_from_user(void *to, const void __user *from, unsigned long n)
295 {
296         return __asm_copy_from_user(to, from, n);
297 }
298 
299 static inline unsigned long
300 raw_copy_to_user(void __user *to, const void *from, unsigned long n)
301 {
302         return __asm_copy_to_user(to, from, n);
303 }
304 
305 extern long strncpy_from_user(char *dest, const char __user *src, long count);
306 
307 extern long __must_check strnlen_user(const char __user *str, long n);
308 
309 extern
310 unsigned long __must_check __clear_user(void __user *addr, unsigned long n);
311 
312 static inline
313 unsigned long __must_check clear_user(void __user *to, unsigned long n)
314 {
315         might_fault();
316         return access_ok(to, n) ?
317                 __clear_user(to, n) : n;
318 }
319 
320 #define __get_kernel_nofault(dst, src, type, err_label)                 \
321 do {                                                                    \
322         long __kr_err = 0;                                              \
323                                                                         \
324         __get_user_nocheck(*((type *)(dst)), (type *)(src), __kr_err);  \
325         if (unlikely(__kr_err))                                         \
326                 goto err_label;                                         \
327 } while (0)
328 
329 #define __put_kernel_nofault(dst, src, type, err_label)                 \
330 do {                                                                    \
331         long __kr_err = 0;                                              \
332                                                                         \
333         __put_user_nocheck(*((type *)(src)), (type *)(dst), __kr_err);  \
334         if (unlikely(__kr_err))                                         \
335                 goto err_label;                                         \
336 } while (0)
337 
338 #else /* CONFIG_MMU */
339 #include <asm-generic/uaccess.h>
340 #endif /* CONFIG_MMU */
341 #endif /* _ASM_RISCV_UACCESS_H */
342 

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