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