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