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