Merge tag 'rust-6.9' of https://github.com/Rust-for-Linux/linux
[sfrench/cifs-2.6.git] / arch / powerpc / include / asm / uaccess.h
1 /* SPDX-License-Identifier: GPL-2.0 */
2 #ifndef _ARCH_POWERPC_UACCESS_H
3 #define _ARCH_POWERPC_UACCESS_H
4
5 #include <asm/processor.h>
6 #include <asm/page.h>
7 #include <asm/extable.h>
8 #include <asm/kup.h>
9
10 #ifdef __powerpc64__
11 /* We use TASK_SIZE_USER64 as TASK_SIZE is not constant */
12 #define TASK_SIZE_MAX           TASK_SIZE_USER64
13 #endif
14
15 #include <asm-generic/access_ok.h>
16
17 /*
18  * These are the main single-value transfer routines.  They automatically
19  * use the right size if we just have the right pointer type.
20  *
21  * This gets kind of ugly. We want to return _two_ values in "get_user()"
22  * and yet we don't want to do any pointers, because that is too much
23  * of a performance impact. Thus we have a few rather ugly macros here,
24  * and hide all the ugliness from the user.
25  *
26  * The "__xxx" versions of the user access functions are versions that
27  * do not verify the address space, that must have been done previously
28  * with a separate "access_ok()" call (this is used when we do multiple
29  * accesses to the same area of user memory).
30  *
31  * As we use the same address space for kernel and user data on the
32  * PowerPC, we can just do these as direct assignments.  (Of course, the
33  * exception handling means that it's no longer "just"...)
34  *
35  */
36 #define __put_user(x, ptr)                                      \
37 ({                                                              \
38         long __pu_err;                                          \
39         __typeof__(*(ptr)) __user *__pu_addr = (ptr);           \
40         __typeof__(*(ptr)) __pu_val = (__typeof__(*(ptr)))(x);  \
41         __typeof__(sizeof(*(ptr))) __pu_size = sizeof(*(ptr));  \
42                                                                 \
43         might_fault();                                          \
44         do {                                                    \
45                 __label__ __pu_failed;                          \
46                                                                 \
47                 allow_write_to_user(__pu_addr, __pu_size);      \
48                 __put_user_size_goto(__pu_val, __pu_addr, __pu_size, __pu_failed);      \
49                 prevent_write_to_user(__pu_addr, __pu_size);    \
50                 __pu_err = 0;                                   \
51                 break;                                          \
52                                                                 \
53 __pu_failed:                                                    \
54                 prevent_write_to_user(__pu_addr, __pu_size);    \
55                 __pu_err = -EFAULT;                             \
56         } while (0);                                            \
57                                                                 \
58         __pu_err;                                               \
59 })
60
61 #define put_user(x, ptr)                                                \
62 ({                                                                      \
63         __typeof__(*(ptr)) __user *_pu_addr = (ptr);                    \
64                                                                         \
65         access_ok(_pu_addr, sizeof(*(ptr))) ?                           \
66                   __put_user(x, _pu_addr) : -EFAULT;                    \
67 })
68
69 /*
70  * We don't tell gcc that we are accessing memory, but this is OK
71  * because we do not write to any memory gcc knows about, so there
72  * are no aliasing issues.
73  */
74 /* -mprefixed can generate offsets beyond range, fall back hack */
75 #ifdef CONFIG_PPC_KERNEL_PREFIXED
76 #define __put_user_asm_goto(x, addr, label, op)                 \
77         asm goto(                                       \
78                 "1:     " op " %0,0(%1) # put_user\n"           \
79                 EX_TABLE(1b, %l2)                               \
80                 :                                               \
81                 : "r" (x), "b" (addr)                           \
82                 :                                               \
83                 : label)
84 #else
85 #define __put_user_asm_goto(x, addr, label, op)                 \
86         asm goto(                                       \
87                 "1:     " op "%U1%X1 %0,%1      # put_user\n"   \
88                 EX_TABLE(1b, %l2)                               \
89                 :                                               \
90                 : "r" (x), "m<>" (*addr)                        \
91                 :                                               \
92                 : label)
93 #endif
94
95 #ifdef __powerpc64__
96 #define __put_user_asm2_goto(x, ptr, label)                     \
97         __put_user_asm_goto(x, ptr, label, "std")
98 #else /* __powerpc64__ */
99 #define __put_user_asm2_goto(x, addr, label)                    \
100         asm goto(                                       \
101                 "1:     stw%X1 %0, %1\n"                        \
102                 "2:     stw%X1 %L0, %L1\n"                      \
103                 EX_TABLE(1b, %l2)                               \
104                 EX_TABLE(2b, %l2)                               \
105                 :                                               \
106                 : "r" (x), "m" (*addr)                          \
107                 :                                               \
108                 : label)
109 #endif /* __powerpc64__ */
110
111 #define __put_user_size_goto(x, ptr, size, label)               \
112 do {                                                            \
113         __typeof__(*(ptr)) __user *__pus_addr = (ptr);          \
114                                                                 \
115         switch (size) {                                         \
116         case 1: __put_user_asm_goto(x, __pus_addr, label, "stb"); break;        \
117         case 2: __put_user_asm_goto(x, __pus_addr, label, "sth"); break;        \
118         case 4: __put_user_asm_goto(x, __pus_addr, label, "stw"); break;        \
119         case 8: __put_user_asm2_goto(x, __pus_addr, label); break;              \
120         default: BUILD_BUG();                                   \
121         }                                                       \
122 } while (0)
123
124 /*
125  * This does an atomic 128 byte aligned load from userspace.
126  * Upto caller to do enable_kernel_vmx() before calling!
127  */
128 #define __get_user_atomic_128_aligned(kaddr, uaddr, err)                \
129         __asm__ __volatile__(                           \
130                 ".machine push\n"                       \
131                 ".machine altivec\n"                    \
132                 "1:     lvx  0,0,%1     # get user\n"   \
133                 "       stvx 0,0,%2     # put kernel\n" \
134                 ".machine pop\n"                        \
135                 "2:\n"                                  \
136                 ".section .fixup,\"ax\"\n"              \
137                 "3:     li %0,%3\n"                     \
138                 "       b 2b\n"                         \
139                 ".previous\n"                           \
140                 EX_TABLE(1b, 3b)                        \
141                 : "=r" (err)                    \
142                 : "b" (uaddr), "b" (kaddr), "i" (-EFAULT), "0" (err))
143
144 #ifdef CONFIG_CC_HAS_ASM_GOTO_OUTPUT
145
146 /* -mprefixed can generate offsets beyond range, fall back hack */
147 #ifdef CONFIG_PPC_KERNEL_PREFIXED
148 #define __get_user_asm_goto(x, addr, label, op)                 \
149         asm_goto_output(                                        \
150                 "1:     "op" %0,0(%1)   # get_user\n"           \
151                 EX_TABLE(1b, %l2)                               \
152                 : "=r" (x)                                      \
153                 : "b" (addr)                                    \
154                 :                                               \
155                 : label)
156 #else
157 #define __get_user_asm_goto(x, addr, label, op)                 \
158         asm_goto_output(                                        \
159                 "1:     "op"%U1%X1 %0, %1       # get_user\n"   \
160                 EX_TABLE(1b, %l2)                               \
161                 : "=r" (x)                                      \
162                 : "m<>" (*addr)                                 \
163                 :                                               \
164                 : label)
165 #endif
166
167 #ifdef __powerpc64__
168 #define __get_user_asm2_goto(x, addr, label)                    \
169         __get_user_asm_goto(x, addr, label, "ld")
170 #else /* __powerpc64__ */
171 #define __get_user_asm2_goto(x, addr, label)                    \
172         asm_goto_output(                                        \
173                 "1:     lwz%X1 %0, %1\n"                        \
174                 "2:     lwz%X1 %L0, %L1\n"                      \
175                 EX_TABLE(1b, %l2)                               \
176                 EX_TABLE(2b, %l2)                               \
177                 : "=&r" (x)                                     \
178                 : "m" (*addr)                                   \
179                 :                                               \
180                 : label)
181 #endif /* __powerpc64__ */
182
183 #define __get_user_size_goto(x, ptr, size, label)                               \
184 do {                                                                            \
185         BUILD_BUG_ON(size > sizeof(x));                                         \
186         switch (size) {                                                         \
187         case 1: __get_user_asm_goto(x, (u8 __user *)ptr, label, "lbz"); break;  \
188         case 2: __get_user_asm_goto(x, (u16 __user *)ptr, label, "lhz"); break; \
189         case 4: __get_user_asm_goto(x, (u32 __user *)ptr, label, "lwz"); break; \
190         case 8: __get_user_asm2_goto(x, (u64 __user *)ptr, label);  break;      \
191         default: x = 0; BUILD_BUG();                                            \
192         }                                                                       \
193 } while (0)
194
195 #define __get_user_size_allowed(x, ptr, size, retval)                   \
196 do {                                                                    \
197                 __label__ __gus_failed;                                 \
198                                                                         \
199                 __get_user_size_goto(x, ptr, size, __gus_failed);       \
200                 retval = 0;                                             \
201                 break;                                                  \
202 __gus_failed:                                                           \
203                 x = 0;                                                  \
204                 retval = -EFAULT;                                       \
205 } while (0)
206
207 #else /* CONFIG_CC_HAS_ASM_GOTO_OUTPUT */
208
209 #define __get_user_asm(x, addr, err, op)                \
210         __asm__ __volatile__(                           \
211                 "1:     "op"%U2%X2 %1, %2       # get_user\n"   \
212                 "2:\n"                                  \
213                 ".section .fixup,\"ax\"\n"              \
214                 "3:     li %0,%3\n"                     \
215                 "       li %1,0\n"                      \
216                 "       b 2b\n"                         \
217                 ".previous\n"                           \
218                 EX_TABLE(1b, 3b)                        \
219                 : "=r" (err), "=r" (x)                  \
220                 : "m<>" (*addr), "i" (-EFAULT), "0" (err))
221
222 #ifdef __powerpc64__
223 #define __get_user_asm2(x, addr, err)                   \
224         __get_user_asm(x, addr, err, "ld")
225 #else /* __powerpc64__ */
226 #define __get_user_asm2(x, addr, err)                   \
227         __asm__ __volatile__(                           \
228                 "1:     lwz%X2 %1, %2\n"                        \
229                 "2:     lwz%X2 %L1, %L2\n"              \
230                 "3:\n"                                  \
231                 ".section .fixup,\"ax\"\n"              \
232                 "4:     li %0,%3\n"                     \
233                 "       li %1,0\n"                      \
234                 "       li %1+1,0\n"                    \
235                 "       b 3b\n"                         \
236                 ".previous\n"                           \
237                 EX_TABLE(1b, 4b)                        \
238                 EX_TABLE(2b, 4b)                        \
239                 : "=r" (err), "=&r" (x)                 \
240                 : "m" (*addr), "i" (-EFAULT), "0" (err))
241 #endif /* __powerpc64__ */
242
243 #define __get_user_size_allowed(x, ptr, size, retval)           \
244 do {                                                            \
245         retval = 0;                                             \
246         BUILD_BUG_ON(size > sizeof(x));                         \
247         switch (size) {                                         \
248         case 1: __get_user_asm(x, (u8 __user *)ptr, retval, "lbz"); break;      \
249         case 2: __get_user_asm(x, (u16 __user *)ptr, retval, "lhz"); break;     \
250         case 4: __get_user_asm(x, (u32 __user *)ptr, retval, "lwz"); break;     \
251         case 8: __get_user_asm2(x, (u64 __user *)ptr, retval);  break;  \
252         default: x = 0; BUILD_BUG();                            \
253         }                                                       \
254 } while (0)
255
256 #define __get_user_size_goto(x, ptr, size, label)               \
257 do {                                                            \
258         long __gus_retval;                                      \
259                                                                 \
260         __get_user_size_allowed(x, ptr, size, __gus_retval);    \
261         if (__gus_retval)                                       \
262                 goto label;                                     \
263 } while (0)
264
265 #endif /* CONFIG_CC_HAS_ASM_GOTO_OUTPUT */
266
267 /*
268  * This is a type: either unsigned long, if the argument fits into
269  * that type, or otherwise unsigned long long.
270  */
271 #define __long_type(x) \
272         __typeof__(__builtin_choose_expr(sizeof(x) > sizeof(0UL), 0ULL, 0UL))
273
274 #define __get_user(x, ptr)                                      \
275 ({                                                              \
276         long __gu_err;                                          \
277         __long_type(*(ptr)) __gu_val;                           \
278         __typeof__(*(ptr)) __user *__gu_addr = (ptr);   \
279         __typeof__(sizeof(*(ptr))) __gu_size = sizeof(*(ptr));  \
280                                                                 \
281         might_fault();                                  \
282         allow_read_from_user(__gu_addr, __gu_size);             \
283         __get_user_size_allowed(__gu_val, __gu_addr, __gu_size, __gu_err);      \
284         prevent_read_from_user(__gu_addr, __gu_size);           \
285         (x) = (__typeof__(*(ptr)))__gu_val;                     \
286                                                                 \
287         __gu_err;                                               \
288 })
289
290 #define get_user(x, ptr)                                                \
291 ({                                                                      \
292         __typeof__(*(ptr)) __user *_gu_addr = (ptr);                    \
293                                                                         \
294         access_ok(_gu_addr, sizeof(*(ptr))) ?                           \
295                   __get_user(x, _gu_addr) :                             \
296                   ((x) = (__force __typeof__(*(ptr)))0, -EFAULT);       \
297 })
298
299 /* more complex routines */
300
301 extern unsigned long __copy_tofrom_user(void __user *to,
302                 const void __user *from, unsigned long size);
303
304 #ifdef __powerpc64__
305 static inline unsigned long
306 raw_copy_in_user(void __user *to, const void __user *from, unsigned long n)
307 {
308         unsigned long ret;
309
310         allow_read_write_user(to, from, n);
311         ret = __copy_tofrom_user(to, from, n);
312         prevent_read_write_user(to, from, n);
313         return ret;
314 }
315 #endif /* __powerpc64__ */
316
317 static inline unsigned long raw_copy_from_user(void *to,
318                 const void __user *from, unsigned long n)
319 {
320         unsigned long ret;
321
322         allow_read_from_user(from, n);
323         ret = __copy_tofrom_user((__force void __user *)to, from, n);
324         prevent_read_from_user(from, n);
325         return ret;
326 }
327
328 static inline unsigned long
329 raw_copy_to_user(void __user *to, const void *from, unsigned long n)
330 {
331         unsigned long ret;
332
333         allow_write_to_user(to, n);
334         ret = __copy_tofrom_user(to, (__force const void __user *)from, n);
335         prevent_write_to_user(to, n);
336         return ret;
337 }
338
339 unsigned long __arch_clear_user(void __user *addr, unsigned long size);
340
341 static inline unsigned long __clear_user(void __user *addr, unsigned long size)
342 {
343         unsigned long ret;
344
345         might_fault();
346         allow_write_to_user(addr, size);
347         ret = __arch_clear_user(addr, size);
348         prevent_write_to_user(addr, size);
349         return ret;
350 }
351
352 static inline unsigned long clear_user(void __user *addr, unsigned long size)
353 {
354         return likely(access_ok(addr, size)) ? __clear_user(addr, size) : size;
355 }
356
357 extern long strncpy_from_user(char *dst, const char __user *src, long count);
358 extern __must_check long strnlen_user(const char __user *str, long n);
359
360 #ifdef CONFIG_ARCH_HAS_COPY_MC
361 unsigned long __must_check
362 copy_mc_generic(void *to, const void *from, unsigned long size);
363
364 static inline unsigned long __must_check
365 copy_mc_to_kernel(void *to, const void *from, unsigned long size)
366 {
367         return copy_mc_generic(to, from, size);
368 }
369 #define copy_mc_to_kernel copy_mc_to_kernel
370
371 static inline unsigned long __must_check
372 copy_mc_to_user(void __user *to, const void *from, unsigned long n)
373 {
374         if (check_copy_size(from, n, true)) {
375                 if (access_ok(to, n)) {
376                         allow_write_to_user(to, n);
377                         n = copy_mc_generic((void __force *)to, from, n);
378                         prevent_write_to_user(to, n);
379                 }
380         }
381
382         return n;
383 }
384 #endif
385
386 extern long __copy_from_user_flushcache(void *dst, const void __user *src,
387                 unsigned size);
388
389 static __must_check __always_inline bool user_access_begin(const void __user *ptr, size_t len)
390 {
391         if (unlikely(!access_ok(ptr, len)))
392                 return false;
393
394         might_fault();
395
396         allow_read_write_user((void __user *)ptr, ptr, len);
397         return true;
398 }
399 #define user_access_begin       user_access_begin
400 #define user_access_end         prevent_current_access_user
401 #define user_access_save        prevent_user_access_return
402 #define user_access_restore     restore_user_access
403
404 static __must_check __always_inline bool
405 user_read_access_begin(const void __user *ptr, size_t len)
406 {
407         if (unlikely(!access_ok(ptr, len)))
408                 return false;
409
410         might_fault();
411
412         allow_read_from_user(ptr, len);
413         return true;
414 }
415 #define user_read_access_begin  user_read_access_begin
416 #define user_read_access_end            prevent_current_read_from_user
417
418 static __must_check __always_inline bool
419 user_write_access_begin(const void __user *ptr, size_t len)
420 {
421         if (unlikely(!access_ok(ptr, len)))
422                 return false;
423
424         might_fault();
425
426         allow_write_to_user((void __user *)ptr, len);
427         return true;
428 }
429 #define user_write_access_begin user_write_access_begin
430 #define user_write_access_end           prevent_current_write_to_user
431
432 #define unsafe_get_user(x, p, e) do {                                   \
433         __long_type(*(p)) __gu_val;                             \
434         __typeof__(*(p)) __user *__gu_addr = (p);               \
435                                                                 \
436         __get_user_size_goto(__gu_val, __gu_addr, sizeof(*(p)), e); \
437         (x) = (__typeof__(*(p)))__gu_val;                       \
438 } while (0)
439
440 #define unsafe_put_user(x, p, e) \
441         __put_user_size_goto((__typeof__(*(p)))(x), (p), sizeof(*(p)), e)
442
443 #define unsafe_copy_from_user(d, s, l, e) \
444 do {                                                                                    \
445         u8 *_dst = (u8 *)(d);                                                           \
446         const u8 __user *_src = (const u8 __user *)(s);                                 \
447         size_t _len = (l);                                                              \
448         int _i;                                                                         \
449                                                                                         \
450         for (_i = 0; _i < (_len & ~(sizeof(u64) - 1)); _i += sizeof(u64))               \
451                 unsafe_get_user(*(u64 *)(_dst + _i), (u64 __user *)(_src + _i), e);     \
452         if (_len & 4) {                                                                 \
453                 unsafe_get_user(*(u32 *)(_dst + _i), (u32 __user *)(_src + _i), e);     \
454                 _i += 4;                                                                \
455         }                                                                               \
456         if (_len & 2) {                                                                 \
457                 unsafe_get_user(*(u16 *)(_dst + _i), (u16 __user *)(_src + _i), e);     \
458                 _i += 2;                                                                \
459         }                                                                               \
460         if (_len & 1)                                                                   \
461                 unsafe_get_user(*(u8 *)(_dst + _i), (u8 __user *)(_src + _i), e);       \
462 } while (0)
463
464 #define unsafe_copy_to_user(d, s, l, e) \
465 do {                                                                    \
466         u8 __user *_dst = (u8 __user *)(d);                             \
467         const u8 *_src = (const u8 *)(s);                               \
468         size_t _len = (l);                                              \
469         int _i;                                                         \
470                                                                         \
471         for (_i = 0; _i < (_len & ~(sizeof(u64) - 1)); _i += sizeof(u64))       \
472                 unsafe_put_user(*(u64 *)(_src + _i), (u64 __user *)(_dst + _i), e); \
473         if (_len & 4) {                                                 \
474                 unsafe_put_user(*(u32*)(_src + _i), (u32 __user *)(_dst + _i), e); \
475                 _i += 4;                                                \
476         }                                                               \
477         if (_len & 2) {                                                 \
478                 unsafe_put_user(*(u16*)(_src + _i), (u16 __user *)(_dst + _i), e); \
479                 _i += 2;                                                \
480         }                                                               \
481         if (_len & 1) \
482                 unsafe_put_user(*(u8*)(_src + _i), (u8 __user *)(_dst + _i), e); \
483 } while (0)
484
485 #define __get_kernel_nofault(dst, src, type, err_label)                 \
486         __get_user_size_goto(*((type *)(dst)),                          \
487                 (__force type __user *)(src), sizeof(type), err_label)
488
489 #define __put_kernel_nofault(dst, src, type, err_label)                 \
490         __put_user_size_goto(*((type *)(src)),                          \
491                 (__force type __user *)(dst), sizeof(type), err_label)
492
493 #endif  /* _ARCH_POWERPC_UACCESS_H */