1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0 */
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * S390 version
4*4882a593Smuzhiyun * Copyright IBM Corp. 1999, 2000
5*4882a593Smuzhiyun * Author(s): Hartmut Penner (hp@de.ibm.com),
6*4882a593Smuzhiyun * Martin Schwidefsky (schwidefsky@de.ibm.com)
7*4882a593Smuzhiyun *
8*4882a593Smuzhiyun * Derived from "include/asm-i386/uaccess.h"
9*4882a593Smuzhiyun */
10*4882a593Smuzhiyun #ifndef __S390_UACCESS_H
11*4882a593Smuzhiyun #define __S390_UACCESS_H
12*4882a593Smuzhiyun
13*4882a593Smuzhiyun /*
14*4882a593Smuzhiyun * User space memory access functions
15*4882a593Smuzhiyun */
16*4882a593Smuzhiyun #include <asm/processor.h>
17*4882a593Smuzhiyun #include <asm/ctl_reg.h>
18*4882a593Smuzhiyun #include <asm/extable.h>
19*4882a593Smuzhiyun #include <asm/facility.h>
20*4882a593Smuzhiyun
21*4882a593Smuzhiyun /*
22*4882a593Smuzhiyun * The fs value determines whether argument validity checking should be
23*4882a593Smuzhiyun * performed or not. If get_fs() == USER_DS, checking is performed, with
24*4882a593Smuzhiyun * get_fs() == KERNEL_DS, checking is bypassed.
25*4882a593Smuzhiyun *
26*4882a593Smuzhiyun * For historical reasons, these macros are grossly misnamed.
27*4882a593Smuzhiyun */
28*4882a593Smuzhiyun
29*4882a593Smuzhiyun #define KERNEL_DS (0)
30*4882a593Smuzhiyun #define KERNEL_DS_SACF (1)
31*4882a593Smuzhiyun #define USER_DS (2)
32*4882a593Smuzhiyun #define USER_DS_SACF (3)
33*4882a593Smuzhiyun
34*4882a593Smuzhiyun #define get_fs() (current->thread.mm_segment)
35*4882a593Smuzhiyun #define uaccess_kernel() ((get_fs() & 2) == KERNEL_DS)
36*4882a593Smuzhiyun
37*4882a593Smuzhiyun void set_fs(mm_segment_t fs);
38*4882a593Smuzhiyun
__range_ok(unsigned long addr,unsigned long size)39*4882a593Smuzhiyun static inline int __range_ok(unsigned long addr, unsigned long size)
40*4882a593Smuzhiyun {
41*4882a593Smuzhiyun return 1;
42*4882a593Smuzhiyun }
43*4882a593Smuzhiyun
44*4882a593Smuzhiyun #define __access_ok(addr, size) \
45*4882a593Smuzhiyun ({ \
46*4882a593Smuzhiyun __chk_user_ptr(addr); \
47*4882a593Smuzhiyun __range_ok((unsigned long)(addr), (size)); \
48*4882a593Smuzhiyun })
49*4882a593Smuzhiyun
50*4882a593Smuzhiyun #define access_ok(addr, size) __access_ok(addr, size)
51*4882a593Smuzhiyun
52*4882a593Smuzhiyun unsigned long __must_check
53*4882a593Smuzhiyun raw_copy_from_user(void *to, const void __user *from, unsigned long n);
54*4882a593Smuzhiyun
55*4882a593Smuzhiyun unsigned long __must_check
56*4882a593Smuzhiyun raw_copy_to_user(void __user *to, const void *from, unsigned long n);
57*4882a593Smuzhiyun
58*4882a593Smuzhiyun #ifndef CONFIG_KASAN
59*4882a593Smuzhiyun #define INLINE_COPY_FROM_USER
60*4882a593Smuzhiyun #define INLINE_COPY_TO_USER
61*4882a593Smuzhiyun #endif
62*4882a593Smuzhiyun
63*4882a593Smuzhiyun int __put_user_bad(void) __attribute__((noreturn));
64*4882a593Smuzhiyun int __get_user_bad(void) __attribute__((noreturn));
65*4882a593Smuzhiyun
66*4882a593Smuzhiyun #ifdef CONFIG_HAVE_MARCH_Z10_FEATURES
67*4882a593Smuzhiyun
68*4882a593Smuzhiyun #define __put_get_user_asm(to, from, size, spec) \
69*4882a593Smuzhiyun ({ \
70*4882a593Smuzhiyun register unsigned long __reg0 asm("0") = spec; \
71*4882a593Smuzhiyun int __rc; \
72*4882a593Smuzhiyun \
73*4882a593Smuzhiyun asm volatile( \
74*4882a593Smuzhiyun "0: mvcos %1,%3,%2\n" \
75*4882a593Smuzhiyun "1: xr %0,%0\n" \
76*4882a593Smuzhiyun "2:\n" \
77*4882a593Smuzhiyun ".pushsection .fixup, \"ax\"\n" \
78*4882a593Smuzhiyun "3: lhi %0,%5\n" \
79*4882a593Smuzhiyun " jg 2b\n" \
80*4882a593Smuzhiyun ".popsection\n" \
81*4882a593Smuzhiyun EX_TABLE(0b,3b) EX_TABLE(1b,3b) \
82*4882a593Smuzhiyun : "=d" (__rc), "+Q" (*(to)) \
83*4882a593Smuzhiyun : "d" (size), "Q" (*(from)), \
84*4882a593Smuzhiyun "d" (__reg0), "K" (-EFAULT) \
85*4882a593Smuzhiyun : "cc"); \
86*4882a593Smuzhiyun __rc; \
87*4882a593Smuzhiyun })
88*4882a593Smuzhiyun
__put_user_fn(void * x,void __user * ptr,unsigned long size)89*4882a593Smuzhiyun static __always_inline int __put_user_fn(void *x, void __user *ptr, unsigned long size)
90*4882a593Smuzhiyun {
91*4882a593Smuzhiyun unsigned long spec = 0x010000UL;
92*4882a593Smuzhiyun int rc;
93*4882a593Smuzhiyun
94*4882a593Smuzhiyun switch (size) {
95*4882a593Smuzhiyun case 1:
96*4882a593Smuzhiyun rc = __put_get_user_asm((unsigned char __user *)ptr,
97*4882a593Smuzhiyun (unsigned char *)x,
98*4882a593Smuzhiyun size, spec);
99*4882a593Smuzhiyun break;
100*4882a593Smuzhiyun case 2:
101*4882a593Smuzhiyun rc = __put_get_user_asm((unsigned short __user *)ptr,
102*4882a593Smuzhiyun (unsigned short *)x,
103*4882a593Smuzhiyun size, spec);
104*4882a593Smuzhiyun break;
105*4882a593Smuzhiyun case 4:
106*4882a593Smuzhiyun rc = __put_get_user_asm((unsigned int __user *)ptr,
107*4882a593Smuzhiyun (unsigned int *)x,
108*4882a593Smuzhiyun size, spec);
109*4882a593Smuzhiyun break;
110*4882a593Smuzhiyun case 8:
111*4882a593Smuzhiyun rc = __put_get_user_asm((unsigned long __user *)ptr,
112*4882a593Smuzhiyun (unsigned long *)x,
113*4882a593Smuzhiyun size, spec);
114*4882a593Smuzhiyun break;
115*4882a593Smuzhiyun default:
116*4882a593Smuzhiyun __put_user_bad();
117*4882a593Smuzhiyun break;
118*4882a593Smuzhiyun }
119*4882a593Smuzhiyun return rc;
120*4882a593Smuzhiyun }
121*4882a593Smuzhiyun
__get_user_fn(void * x,const void __user * ptr,unsigned long size)122*4882a593Smuzhiyun static __always_inline int __get_user_fn(void *x, const void __user *ptr, unsigned long size)
123*4882a593Smuzhiyun {
124*4882a593Smuzhiyun unsigned long spec = 0x01UL;
125*4882a593Smuzhiyun int rc;
126*4882a593Smuzhiyun
127*4882a593Smuzhiyun switch (size) {
128*4882a593Smuzhiyun case 1:
129*4882a593Smuzhiyun rc = __put_get_user_asm((unsigned char *)x,
130*4882a593Smuzhiyun (unsigned char __user *)ptr,
131*4882a593Smuzhiyun size, spec);
132*4882a593Smuzhiyun break;
133*4882a593Smuzhiyun case 2:
134*4882a593Smuzhiyun rc = __put_get_user_asm((unsigned short *)x,
135*4882a593Smuzhiyun (unsigned short __user *)ptr,
136*4882a593Smuzhiyun size, spec);
137*4882a593Smuzhiyun break;
138*4882a593Smuzhiyun case 4:
139*4882a593Smuzhiyun rc = __put_get_user_asm((unsigned int *)x,
140*4882a593Smuzhiyun (unsigned int __user *)ptr,
141*4882a593Smuzhiyun size, spec);
142*4882a593Smuzhiyun break;
143*4882a593Smuzhiyun case 8:
144*4882a593Smuzhiyun rc = __put_get_user_asm((unsigned long *)x,
145*4882a593Smuzhiyun (unsigned long __user *)ptr,
146*4882a593Smuzhiyun size, spec);
147*4882a593Smuzhiyun break;
148*4882a593Smuzhiyun default:
149*4882a593Smuzhiyun __get_user_bad();
150*4882a593Smuzhiyun break;
151*4882a593Smuzhiyun }
152*4882a593Smuzhiyun return rc;
153*4882a593Smuzhiyun }
154*4882a593Smuzhiyun
155*4882a593Smuzhiyun #else /* CONFIG_HAVE_MARCH_Z10_FEATURES */
156*4882a593Smuzhiyun
__put_user_fn(void * x,void __user * ptr,unsigned long size)157*4882a593Smuzhiyun static inline int __put_user_fn(void *x, void __user *ptr, unsigned long size)
158*4882a593Smuzhiyun {
159*4882a593Smuzhiyun size = raw_copy_to_user(ptr, x, size);
160*4882a593Smuzhiyun return size ? -EFAULT : 0;
161*4882a593Smuzhiyun }
162*4882a593Smuzhiyun
__get_user_fn(void * x,const void __user * ptr,unsigned long size)163*4882a593Smuzhiyun static inline int __get_user_fn(void *x, const void __user *ptr, unsigned long size)
164*4882a593Smuzhiyun {
165*4882a593Smuzhiyun size = raw_copy_from_user(x, ptr, size);
166*4882a593Smuzhiyun return size ? -EFAULT : 0;
167*4882a593Smuzhiyun }
168*4882a593Smuzhiyun
169*4882a593Smuzhiyun #endif /* CONFIG_HAVE_MARCH_Z10_FEATURES */
170*4882a593Smuzhiyun
171*4882a593Smuzhiyun /*
172*4882a593Smuzhiyun * These are the main single-value transfer routines. They automatically
173*4882a593Smuzhiyun * use the right size if we just have the right pointer type.
174*4882a593Smuzhiyun */
175*4882a593Smuzhiyun #define __put_user(x, ptr) \
176*4882a593Smuzhiyun ({ \
177*4882a593Smuzhiyun __typeof__(*(ptr)) __x = (x); \
178*4882a593Smuzhiyun int __pu_err = -EFAULT; \
179*4882a593Smuzhiyun __chk_user_ptr(ptr); \
180*4882a593Smuzhiyun switch (sizeof (*(ptr))) { \
181*4882a593Smuzhiyun case 1: \
182*4882a593Smuzhiyun case 2: \
183*4882a593Smuzhiyun case 4: \
184*4882a593Smuzhiyun case 8: \
185*4882a593Smuzhiyun __pu_err = __put_user_fn(&__x, ptr, \
186*4882a593Smuzhiyun sizeof(*(ptr))); \
187*4882a593Smuzhiyun break; \
188*4882a593Smuzhiyun default: \
189*4882a593Smuzhiyun __put_user_bad(); \
190*4882a593Smuzhiyun break; \
191*4882a593Smuzhiyun } \
192*4882a593Smuzhiyun __builtin_expect(__pu_err, 0); \
193*4882a593Smuzhiyun })
194*4882a593Smuzhiyun
195*4882a593Smuzhiyun #define put_user(x, ptr) \
196*4882a593Smuzhiyun ({ \
197*4882a593Smuzhiyun might_fault(); \
198*4882a593Smuzhiyun __put_user(x, ptr); \
199*4882a593Smuzhiyun })
200*4882a593Smuzhiyun
201*4882a593Smuzhiyun
202*4882a593Smuzhiyun #define __get_user(x, ptr) \
203*4882a593Smuzhiyun ({ \
204*4882a593Smuzhiyun int __gu_err = -EFAULT; \
205*4882a593Smuzhiyun __chk_user_ptr(ptr); \
206*4882a593Smuzhiyun switch (sizeof(*(ptr))) { \
207*4882a593Smuzhiyun case 1: { \
208*4882a593Smuzhiyun unsigned char __x = 0; \
209*4882a593Smuzhiyun __gu_err = __get_user_fn(&__x, ptr, \
210*4882a593Smuzhiyun sizeof(*(ptr))); \
211*4882a593Smuzhiyun (x) = *(__force __typeof__(*(ptr)) *) &__x; \
212*4882a593Smuzhiyun break; \
213*4882a593Smuzhiyun }; \
214*4882a593Smuzhiyun case 2: { \
215*4882a593Smuzhiyun unsigned short __x = 0; \
216*4882a593Smuzhiyun __gu_err = __get_user_fn(&__x, ptr, \
217*4882a593Smuzhiyun sizeof(*(ptr))); \
218*4882a593Smuzhiyun (x) = *(__force __typeof__(*(ptr)) *) &__x; \
219*4882a593Smuzhiyun break; \
220*4882a593Smuzhiyun }; \
221*4882a593Smuzhiyun case 4: { \
222*4882a593Smuzhiyun unsigned int __x = 0; \
223*4882a593Smuzhiyun __gu_err = __get_user_fn(&__x, ptr, \
224*4882a593Smuzhiyun sizeof(*(ptr))); \
225*4882a593Smuzhiyun (x) = *(__force __typeof__(*(ptr)) *) &__x; \
226*4882a593Smuzhiyun break; \
227*4882a593Smuzhiyun }; \
228*4882a593Smuzhiyun case 8: { \
229*4882a593Smuzhiyun unsigned long long __x = 0; \
230*4882a593Smuzhiyun __gu_err = __get_user_fn(&__x, ptr, \
231*4882a593Smuzhiyun sizeof(*(ptr))); \
232*4882a593Smuzhiyun (x) = *(__force __typeof__(*(ptr)) *) &__x; \
233*4882a593Smuzhiyun break; \
234*4882a593Smuzhiyun }; \
235*4882a593Smuzhiyun default: \
236*4882a593Smuzhiyun __get_user_bad(); \
237*4882a593Smuzhiyun break; \
238*4882a593Smuzhiyun } \
239*4882a593Smuzhiyun __builtin_expect(__gu_err, 0); \
240*4882a593Smuzhiyun })
241*4882a593Smuzhiyun
242*4882a593Smuzhiyun #define get_user(x, ptr) \
243*4882a593Smuzhiyun ({ \
244*4882a593Smuzhiyun might_fault(); \
245*4882a593Smuzhiyun __get_user(x, ptr); \
246*4882a593Smuzhiyun })
247*4882a593Smuzhiyun
248*4882a593Smuzhiyun unsigned long __must_check
249*4882a593Smuzhiyun raw_copy_in_user(void __user *to, const void __user *from, unsigned long n);
250*4882a593Smuzhiyun
251*4882a593Smuzhiyun /*
252*4882a593Smuzhiyun * Copy a null terminated string from userspace.
253*4882a593Smuzhiyun */
254*4882a593Smuzhiyun
255*4882a593Smuzhiyun long __strncpy_from_user(char *dst, const char __user *src, long count);
256*4882a593Smuzhiyun
257*4882a593Smuzhiyun static inline long __must_check
strncpy_from_user(char * dst,const char __user * src,long count)258*4882a593Smuzhiyun strncpy_from_user(char *dst, const char __user *src, long count)
259*4882a593Smuzhiyun {
260*4882a593Smuzhiyun might_fault();
261*4882a593Smuzhiyun return __strncpy_from_user(dst, src, count);
262*4882a593Smuzhiyun }
263*4882a593Smuzhiyun
264*4882a593Smuzhiyun unsigned long __must_check __strnlen_user(const char __user *src, unsigned long count);
265*4882a593Smuzhiyun
strnlen_user(const char __user * src,unsigned long n)266*4882a593Smuzhiyun static inline unsigned long strnlen_user(const char __user *src, unsigned long n)
267*4882a593Smuzhiyun {
268*4882a593Smuzhiyun might_fault();
269*4882a593Smuzhiyun return __strnlen_user(src, n);
270*4882a593Smuzhiyun }
271*4882a593Smuzhiyun
272*4882a593Smuzhiyun /*
273*4882a593Smuzhiyun * Zero Userspace
274*4882a593Smuzhiyun */
275*4882a593Smuzhiyun unsigned long __must_check __clear_user(void __user *to, unsigned long size);
276*4882a593Smuzhiyun
clear_user(void __user * to,unsigned long n)277*4882a593Smuzhiyun static inline unsigned long __must_check clear_user(void __user *to, unsigned long n)
278*4882a593Smuzhiyun {
279*4882a593Smuzhiyun might_fault();
280*4882a593Smuzhiyun return __clear_user(to, n);
281*4882a593Smuzhiyun }
282*4882a593Smuzhiyun
283*4882a593Smuzhiyun int copy_to_user_real(void __user *dest, void *src, unsigned long count);
284*4882a593Smuzhiyun void *s390_kernel_write(void *dst, const void *src, size_t size);
285*4882a593Smuzhiyun
286*4882a593Smuzhiyun #define HAVE_GET_KERNEL_NOFAULT
287*4882a593Smuzhiyun
288*4882a593Smuzhiyun int __noreturn __put_kernel_bad(void);
289*4882a593Smuzhiyun
290*4882a593Smuzhiyun #define __put_kernel_asm(val, to, insn) \
291*4882a593Smuzhiyun ({ \
292*4882a593Smuzhiyun int __rc; \
293*4882a593Smuzhiyun \
294*4882a593Smuzhiyun asm volatile( \
295*4882a593Smuzhiyun "0: " insn " %2,%1\n" \
296*4882a593Smuzhiyun "1: xr %0,%0\n" \
297*4882a593Smuzhiyun "2:\n" \
298*4882a593Smuzhiyun ".pushsection .fixup, \"ax\"\n" \
299*4882a593Smuzhiyun "3: lhi %0,%3\n" \
300*4882a593Smuzhiyun " jg 2b\n" \
301*4882a593Smuzhiyun ".popsection\n" \
302*4882a593Smuzhiyun EX_TABLE(0b,3b) EX_TABLE(1b,3b) \
303*4882a593Smuzhiyun : "=d" (__rc), "+Q" (*(to)) \
304*4882a593Smuzhiyun : "d" (val), "K" (-EFAULT) \
305*4882a593Smuzhiyun : "cc"); \
306*4882a593Smuzhiyun __rc; \
307*4882a593Smuzhiyun })
308*4882a593Smuzhiyun
309*4882a593Smuzhiyun #define __put_kernel_nofault(dst, src, type, err_label) \
310*4882a593Smuzhiyun do { \
311*4882a593Smuzhiyun u64 __x = (u64)(*((type *)(src))); \
312*4882a593Smuzhiyun int __pk_err; \
313*4882a593Smuzhiyun \
314*4882a593Smuzhiyun switch (sizeof(type)) { \
315*4882a593Smuzhiyun case 1: \
316*4882a593Smuzhiyun __pk_err = __put_kernel_asm(__x, (type *)(dst), "stc"); \
317*4882a593Smuzhiyun break; \
318*4882a593Smuzhiyun case 2: \
319*4882a593Smuzhiyun __pk_err = __put_kernel_asm(__x, (type *)(dst), "sth"); \
320*4882a593Smuzhiyun break; \
321*4882a593Smuzhiyun case 4: \
322*4882a593Smuzhiyun __pk_err = __put_kernel_asm(__x, (type *)(dst), "st"); \
323*4882a593Smuzhiyun break; \
324*4882a593Smuzhiyun case 8: \
325*4882a593Smuzhiyun __pk_err = __put_kernel_asm(__x, (type *)(dst), "stg"); \
326*4882a593Smuzhiyun break; \
327*4882a593Smuzhiyun default: \
328*4882a593Smuzhiyun __pk_err = __put_kernel_bad(); \
329*4882a593Smuzhiyun break; \
330*4882a593Smuzhiyun } \
331*4882a593Smuzhiyun if (unlikely(__pk_err)) \
332*4882a593Smuzhiyun goto err_label; \
333*4882a593Smuzhiyun } while (0)
334*4882a593Smuzhiyun
335*4882a593Smuzhiyun int __noreturn __get_kernel_bad(void);
336*4882a593Smuzhiyun
337*4882a593Smuzhiyun #define __get_kernel_asm(val, from, insn) \
338*4882a593Smuzhiyun ({ \
339*4882a593Smuzhiyun int __rc; \
340*4882a593Smuzhiyun \
341*4882a593Smuzhiyun asm volatile( \
342*4882a593Smuzhiyun "0: " insn " %1,%2\n" \
343*4882a593Smuzhiyun "1: xr %0,%0\n" \
344*4882a593Smuzhiyun "2:\n" \
345*4882a593Smuzhiyun ".pushsection .fixup, \"ax\"\n" \
346*4882a593Smuzhiyun "3: lhi %0,%3\n" \
347*4882a593Smuzhiyun " jg 2b\n" \
348*4882a593Smuzhiyun ".popsection\n" \
349*4882a593Smuzhiyun EX_TABLE(0b,3b) EX_TABLE(1b,3b) \
350*4882a593Smuzhiyun : "=d" (__rc), "+d" (val) \
351*4882a593Smuzhiyun : "Q" (*(from)), "K" (-EFAULT) \
352*4882a593Smuzhiyun : "cc"); \
353*4882a593Smuzhiyun __rc; \
354*4882a593Smuzhiyun })
355*4882a593Smuzhiyun
356*4882a593Smuzhiyun #define __get_kernel_nofault(dst, src, type, err_label) \
357*4882a593Smuzhiyun do { \
358*4882a593Smuzhiyun int __gk_err; \
359*4882a593Smuzhiyun \
360*4882a593Smuzhiyun switch (sizeof(type)) { \
361*4882a593Smuzhiyun case 1: { \
362*4882a593Smuzhiyun u8 __x = 0; \
363*4882a593Smuzhiyun \
364*4882a593Smuzhiyun __gk_err = __get_kernel_asm(__x, (type *)(src), "ic"); \
365*4882a593Smuzhiyun *((type *)(dst)) = (type)__x; \
366*4882a593Smuzhiyun break; \
367*4882a593Smuzhiyun }; \
368*4882a593Smuzhiyun case 2: { \
369*4882a593Smuzhiyun u16 __x = 0; \
370*4882a593Smuzhiyun \
371*4882a593Smuzhiyun __gk_err = __get_kernel_asm(__x, (type *)(src), "lh"); \
372*4882a593Smuzhiyun *((type *)(dst)) = (type)__x; \
373*4882a593Smuzhiyun break; \
374*4882a593Smuzhiyun }; \
375*4882a593Smuzhiyun case 4: { \
376*4882a593Smuzhiyun u32 __x = 0; \
377*4882a593Smuzhiyun \
378*4882a593Smuzhiyun __gk_err = __get_kernel_asm(__x, (type *)(src), "l"); \
379*4882a593Smuzhiyun *((type *)(dst)) = (type)__x; \
380*4882a593Smuzhiyun break; \
381*4882a593Smuzhiyun }; \
382*4882a593Smuzhiyun case 8: { \
383*4882a593Smuzhiyun u64 __x = 0; \
384*4882a593Smuzhiyun \
385*4882a593Smuzhiyun __gk_err = __get_kernel_asm(__x, (type *)(src), "lg"); \
386*4882a593Smuzhiyun *((type *)(dst)) = (type)__x; \
387*4882a593Smuzhiyun break; \
388*4882a593Smuzhiyun }; \
389*4882a593Smuzhiyun default: \
390*4882a593Smuzhiyun __gk_err = __get_kernel_bad(); \
391*4882a593Smuzhiyun break; \
392*4882a593Smuzhiyun } \
393*4882a593Smuzhiyun if (unlikely(__gk_err)) \
394*4882a593Smuzhiyun goto err_label; \
395*4882a593Smuzhiyun } while (0)
396*4882a593Smuzhiyun
397*4882a593Smuzhiyun #endif /* __S390_UACCESS_H */
398