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