xref: /openbmc/linux/arch/s390/include/asm/uaccess.h (revision f8e17c17)
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 segment_eq(a,b) (((a) & 2) == ((b) & 2))
36 
37 void set_fs(mm_segment_t fs);
38 
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 #ifdef CONFIG_HAVE_MARCH_Z10_FEATURES
64 
65 #define __put_get_user_asm(to, from, size, spec)		\
66 ({								\
67 	register unsigned long __reg0 asm("0") = spec;		\
68 	int __rc;						\
69 								\
70 	asm volatile(						\
71 		"0:	mvcos	%1,%3,%2\n"			\
72 		"1:	xr	%0,%0\n"			\
73 		"2:\n"						\
74 		".pushsection .fixup, \"ax\"\n"			\
75 		"3:	lhi	%0,%5\n"			\
76 		"	jg	2b\n"				\
77 		".popsection\n"					\
78 		EX_TABLE(0b,3b) EX_TABLE(1b,3b)			\
79 		: "=d" (__rc), "+Q" (*(to))			\
80 		: "d" (size), "Q" (*(from)),			\
81 		  "d" (__reg0), "K" (-EFAULT)			\
82 		: "cc");					\
83 	__rc;							\
84 })
85 
86 static __always_inline int __put_user_fn(void *x, void __user *ptr, unsigned long size)
87 {
88 	unsigned long spec = 0x010000UL;
89 	int rc;
90 
91 	switch (size) {
92 	case 1:
93 		rc = __put_get_user_asm((unsigned char __user *)ptr,
94 					(unsigned char *)x,
95 					size, spec);
96 		break;
97 	case 2:
98 		rc = __put_get_user_asm((unsigned short __user *)ptr,
99 					(unsigned short *)x,
100 					size, spec);
101 		break;
102 	case 4:
103 		rc = __put_get_user_asm((unsigned int __user *)ptr,
104 					(unsigned int *)x,
105 					size, spec);
106 		break;
107 	case 8:
108 		rc = __put_get_user_asm((unsigned long __user *)ptr,
109 					(unsigned long *)x,
110 					size, spec);
111 		break;
112 	}
113 	return rc;
114 }
115 
116 static __always_inline int __get_user_fn(void *x, const void __user *ptr, unsigned long size)
117 {
118 	unsigned long spec = 0x01UL;
119 	int rc;
120 
121 	switch (size) {
122 	case 1:
123 		rc = __put_get_user_asm((unsigned char *)x,
124 					(unsigned char __user *)ptr,
125 					size, spec);
126 		break;
127 	case 2:
128 		rc = __put_get_user_asm((unsigned short *)x,
129 					(unsigned short __user *)ptr,
130 					size, spec);
131 		break;
132 	case 4:
133 		rc = __put_get_user_asm((unsigned int *)x,
134 					(unsigned int __user *)ptr,
135 					size, spec);
136 		break;
137 	case 8:
138 		rc = __put_get_user_asm((unsigned long *)x,
139 					(unsigned long __user *)ptr,
140 					size, spec);
141 		break;
142 	}
143 	return rc;
144 }
145 
146 #else /* CONFIG_HAVE_MARCH_Z10_FEATURES */
147 
148 static inline int __put_user_fn(void *x, void __user *ptr, unsigned long size)
149 {
150 	size = raw_copy_to_user(ptr, x, size);
151 	return size ? -EFAULT : 0;
152 }
153 
154 static inline int __get_user_fn(void *x, const void __user *ptr, unsigned long size)
155 {
156 	size = raw_copy_from_user(x, ptr, size);
157 	return size ? -EFAULT : 0;
158 }
159 
160 #endif /* CONFIG_HAVE_MARCH_Z10_FEATURES */
161 
162 /*
163  * These are the main single-value transfer routines.  They automatically
164  * use the right size if we just have the right pointer type.
165  */
166 #define __put_user(x, ptr) \
167 ({								\
168 	__typeof__(*(ptr)) __x = (x);				\
169 	int __pu_err = -EFAULT;					\
170         __chk_user_ptr(ptr);                                    \
171 	switch (sizeof (*(ptr))) {				\
172 	case 1:							\
173 	case 2:							\
174 	case 4:							\
175 	case 8:							\
176 		__pu_err = __put_user_fn(&__x, ptr,		\
177 					 sizeof(*(ptr)));	\
178 		break;						\
179 	default:						\
180 		__put_user_bad();				\
181 		break;						\
182 	 }							\
183 	__builtin_expect(__pu_err, 0);				\
184 })
185 
186 #define put_user(x, ptr)					\
187 ({								\
188 	might_fault();						\
189 	__put_user(x, ptr);					\
190 })
191 
192 
193 int __put_user_bad(void) __attribute__((noreturn));
194 
195 #define __get_user(x, ptr)					\
196 ({								\
197 	int __gu_err = -EFAULT;					\
198 	__chk_user_ptr(ptr);					\
199 	switch (sizeof(*(ptr))) {				\
200 	case 1: {						\
201 		unsigned char __x = 0;				\
202 		__gu_err = __get_user_fn(&__x, ptr,		\
203 					 sizeof(*(ptr)));	\
204 		(x) = *(__force __typeof__(*(ptr)) *) &__x;	\
205 		break;						\
206 	};							\
207 	case 2: {						\
208 		unsigned short __x = 0;				\
209 		__gu_err = __get_user_fn(&__x, ptr,		\
210 					 sizeof(*(ptr)));	\
211 		(x) = *(__force __typeof__(*(ptr)) *) &__x;	\
212 		break;						\
213 	};							\
214 	case 4: {						\
215 		unsigned int __x = 0;				\
216 		__gu_err = __get_user_fn(&__x, ptr,		\
217 					 sizeof(*(ptr)));	\
218 		(x) = *(__force __typeof__(*(ptr)) *) &__x;	\
219 		break;						\
220 	};							\
221 	case 8: {						\
222 		unsigned long long __x = 0;			\
223 		__gu_err = __get_user_fn(&__x, ptr,		\
224 					 sizeof(*(ptr)));	\
225 		(x) = *(__force __typeof__(*(ptr)) *) &__x;	\
226 		break;						\
227 	};							\
228 	default:						\
229 		__get_user_bad();				\
230 		break;						\
231 	}							\
232 	__builtin_expect(__gu_err, 0);				\
233 })
234 
235 #define get_user(x, ptr)					\
236 ({								\
237 	might_fault();						\
238 	__get_user(x, ptr);					\
239 })
240 
241 int __get_user_bad(void) __attribute__((noreturn));
242 
243 unsigned long __must_check
244 raw_copy_in_user(void __user *to, const void __user *from, unsigned long n);
245 
246 /*
247  * Copy a null terminated string from userspace.
248  */
249 
250 long __strncpy_from_user(char *dst, const char __user *src, long count);
251 
252 static inline long __must_check
253 strncpy_from_user(char *dst, const char __user *src, long count)
254 {
255 	might_fault();
256 	return __strncpy_from_user(dst, src, count);
257 }
258 
259 unsigned long __must_check __strnlen_user(const char __user *src, unsigned long count);
260 
261 static inline unsigned long strnlen_user(const char __user *src, unsigned long n)
262 {
263 	might_fault();
264 	return __strnlen_user(src, n);
265 }
266 
267 /*
268  * Zero Userspace
269  */
270 unsigned long __must_check __clear_user(void __user *to, unsigned long size);
271 
272 static inline unsigned long __must_check clear_user(void __user *to, unsigned long n)
273 {
274 	might_fault();
275 	return __clear_user(to, n);
276 }
277 
278 int copy_to_user_real(void __user *dest, void *src, unsigned long count);
279 void s390_kernel_write(void *dst, const void *src, size_t size);
280 
281 #endif /* __S390_UACCESS_H */
282