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