xref: /openbmc/linux/arch/s390/include/asm/uaccess.h (revision d2c43ff1)
1 /*
2  *  S390 version
3  *    Copyright IBM Corp. 1999, 2000
4  *    Author(s): Hartmut Penner (hp@de.ibm.com),
5  *               Martin Schwidefsky (schwidefsky@de.ibm.com)
6  *
7  *  Derived from "include/asm-i386/uaccess.h"
8  */
9 #ifndef __S390_UACCESS_H
10 #define __S390_UACCESS_H
11 
12 /*
13  * User space memory access functions
14  */
15 #include <asm/processor.h>
16 #include <asm/ctl_reg.h>
17 #include <asm/extable.h>
18 
19 
20 /*
21  * The fs value determines whether argument validity checking should be
22  * performed or not.  If get_fs() == USER_DS, checking is performed, with
23  * get_fs() == KERNEL_DS, checking is bypassed.
24  *
25  * For historical reasons, these macros are grossly misnamed.
26  */
27 
28 #define MAKE_MM_SEG(a)  ((mm_segment_t) { (a) })
29 
30 
31 #define KERNEL_DS       MAKE_MM_SEG(0)
32 #define USER_DS         MAKE_MM_SEG(1)
33 
34 #define get_ds()        (KERNEL_DS)
35 #define get_fs()        (current->thread.mm_segment)
36 #define segment_eq(a,b) ((a).ar4 == (b).ar4)
37 
38 static inline void set_fs(mm_segment_t fs)
39 {
40 	current->thread.mm_segment = fs;
41 	if (uaccess_kernel()) {
42 		set_cpu_flag(CIF_ASCE_SECONDARY);
43 		__ctl_load(S390_lowcore.kernel_asce, 7, 7);
44 	} else {
45 		clear_cpu_flag(CIF_ASCE_SECONDARY);
46 		__ctl_load(S390_lowcore.user_asce, 7, 7);
47 	}
48 }
49 
50 static inline int __range_ok(unsigned long addr, unsigned long size)
51 {
52 	return 1;
53 }
54 
55 #define __access_ok(addr, size)				\
56 ({							\
57 	__chk_user_ptr(addr);				\
58 	__range_ok((unsigned long)(addr), (size));	\
59 })
60 
61 #define access_ok(type, addr, size) __access_ok(addr, size)
62 
63 unsigned long __must_check
64 raw_copy_from_user(void *to, const void __user *from, unsigned long n);
65 
66 unsigned long __must_check
67 raw_copy_to_user(void __user *to, const void *from, unsigned long n);
68 
69 #define INLINE_COPY_FROM_USER
70 #define INLINE_COPY_TO_USER
71 
72 #ifdef CONFIG_HAVE_MARCH_Z10_FEATURES
73 
74 #define __put_get_user_asm(to, from, size, spec)		\
75 ({								\
76 	register unsigned long __reg0 asm("0") = spec;		\
77 	int __rc;						\
78 								\
79 	asm volatile(						\
80 		"0:	mvcos	%1,%3,%2\n"			\
81 		"1:	xr	%0,%0\n"			\
82 		"2:\n"						\
83 		".pushsection .fixup, \"ax\"\n"			\
84 		"3:	lhi	%0,%5\n"			\
85 		"	jg	2b\n"				\
86 		".popsection\n"					\
87 		EX_TABLE(0b,3b) EX_TABLE(1b,3b)			\
88 		: "=d" (__rc), "+Q" (*(to))			\
89 		: "d" (size), "Q" (*(from)),			\
90 		  "d" (__reg0), "K" (-EFAULT)			\
91 		: "cc");					\
92 	__rc;							\
93 })
94 
95 static inline int __put_user_fn(void *x, void __user *ptr, unsigned long size)
96 {
97 	unsigned long spec = 0x810000UL;
98 	int rc;
99 
100 	switch (size) {
101 	case 1:
102 		rc = __put_get_user_asm((unsigned char __user *)ptr,
103 					(unsigned char *)x,
104 					size, spec);
105 		break;
106 	case 2:
107 		rc = __put_get_user_asm((unsigned short __user *)ptr,
108 					(unsigned short *)x,
109 					size, spec);
110 		break;
111 	case 4:
112 		rc = __put_get_user_asm((unsigned int __user *)ptr,
113 					(unsigned int *)x,
114 					size, spec);
115 		break;
116 	case 8:
117 		rc = __put_get_user_asm((unsigned long __user *)ptr,
118 					(unsigned long *)x,
119 					size, spec);
120 		break;
121 	}
122 	return rc;
123 }
124 
125 static inline int __get_user_fn(void *x, const void __user *ptr, unsigned long size)
126 {
127 	unsigned long spec = 0x81UL;
128 	int rc;
129 
130 	switch (size) {
131 	case 1:
132 		rc = __put_get_user_asm((unsigned char *)x,
133 					(unsigned char __user *)ptr,
134 					size, spec);
135 		break;
136 	case 2:
137 		rc = __put_get_user_asm((unsigned short *)x,
138 					(unsigned short __user *)ptr,
139 					size, spec);
140 		break;
141 	case 4:
142 		rc = __put_get_user_asm((unsigned int *)x,
143 					(unsigned int __user *)ptr,
144 					size, spec);
145 		break;
146 	case 8:
147 		rc = __put_get_user_asm((unsigned long *)x,
148 					(unsigned long __user *)ptr,
149 					size, spec);
150 		break;
151 	}
152 	return rc;
153 }
154 
155 #else /* CONFIG_HAVE_MARCH_Z10_FEATURES */
156 
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 
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 int __put_user_bad(void) __attribute__((noreturn));
203 
204 #define __get_user(x, ptr)					\
205 ({								\
206 	int __gu_err = -EFAULT;					\
207 	__chk_user_ptr(ptr);					\
208 	switch (sizeof(*(ptr))) {				\
209 	case 1: {						\
210 		unsigned char __x = 0;				\
211 		__gu_err = __get_user_fn(&__x, ptr,		\
212 					 sizeof(*(ptr)));	\
213 		(x) = *(__force __typeof__(*(ptr)) *) &__x;	\
214 		break;						\
215 	};							\
216 	case 2: {						\
217 		unsigned short __x = 0;				\
218 		__gu_err = __get_user_fn(&__x, ptr,		\
219 					 sizeof(*(ptr)));	\
220 		(x) = *(__force __typeof__(*(ptr)) *) &__x;	\
221 		break;						\
222 	};							\
223 	case 4: {						\
224 		unsigned int __x = 0;				\
225 		__gu_err = __get_user_fn(&__x, ptr,		\
226 					 sizeof(*(ptr)));	\
227 		(x) = *(__force __typeof__(*(ptr)) *) &__x;	\
228 		break;						\
229 	};							\
230 	case 8: {						\
231 		unsigned long long __x = 0;			\
232 		__gu_err = __get_user_fn(&__x, ptr,		\
233 					 sizeof(*(ptr)));	\
234 		(x) = *(__force __typeof__(*(ptr)) *) &__x;	\
235 		break;						\
236 	};							\
237 	default:						\
238 		__get_user_bad();				\
239 		break;						\
240 	}							\
241 	__builtin_expect(__gu_err, 0);				\
242 })
243 
244 #define get_user(x, ptr)					\
245 ({								\
246 	might_fault();						\
247 	__get_user(x, ptr);					\
248 })
249 
250 int __get_user_bad(void) __attribute__((noreturn));
251 
252 unsigned long __must_check
253 raw_copy_in_user(void __user *to, const void __user *from, unsigned long n);
254 
255 /*
256  * Copy a null terminated string from userspace.
257  */
258 
259 long __strncpy_from_user(char *dst, const char __user *src, long count);
260 
261 static inline long __must_check
262 strncpy_from_user(char *dst, const char __user *src, long count)
263 {
264 	might_fault();
265 	return __strncpy_from_user(dst, src, count);
266 }
267 
268 unsigned long __must_check __strnlen_user(const char __user *src, unsigned long count);
269 
270 static inline unsigned long strnlen_user(const char __user *src, unsigned long n)
271 {
272 	might_fault();
273 	return __strnlen_user(src, n);
274 }
275 
276 /*
277  * Zero Userspace
278  */
279 unsigned long __must_check __clear_user(void __user *to, unsigned long size);
280 
281 static inline unsigned long __must_check clear_user(void __user *to, unsigned long n)
282 {
283 	might_fault();
284 	return __clear_user(to, n);
285 }
286 
287 int copy_to_user_real(void __user *dest, void *src, unsigned long count);
288 void s390_kernel_write(void *dst, const void *src, size_t size);
289 
290 #endif /* __S390_UACCESS_H */
291