1 /*
2 * include/asm-s390/uaccess.h
3 *
4 * S390 version
5 * Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
6 * Author(s): Hartmut Penner (hp@de.ibm.com),
7 * Martin Schwidefsky (schwidefsky@de.ibm.com)
8 *
9 * Derived from "include/asm-i386/uaccess.h"
10 */
11 #ifndef __S390_UACCESS_H
12 #define __S390_UACCESS_H
13
14 /*
15 * User space memory access functions
16 */
17 #include <linux/sched.h>
18 #if 0
19 #include <asm/segment.h>
20 #endif
21 #define VERIFY_READ 0
22 #define VERIFY_WRITE 1
23
24
25 /*
26 * The fs value determines whether argument validity checking should be
27 * performed or not. If get_fs() == USER_DS, checking is performed, with
28 * get_fs() == KERNEL_DS, checking is bypassed.
29 *
30 * For historical reasons, these macros are grossly misnamed.
31 */
32
33 #define MAKE_MM_SEG(s,a) ((mm_segment_t) { (s),(a) })
34
35
36 #define KERNEL_DS MAKE_MM_SEG(0x7FFFFFFF,0)
37 #define USER_DS MAKE_MM_SEG(PAGE_OFFSET,1)
38
39 #define get_ds() (KERNEL_DS)
40 #define get_fs() (current->thread.fs)
41 #define set_fs(x) ({asm volatile("sar 4,%0"::"a" (x.acc4)); \
42 current->thread.fs = (x);})
43
44 #define segment_eq(a,b) ((a).acc4 == (b).acc4)
45
46
47 #define __access_ok(addr,size) ((((long) addr + size)&0x7FFFFFFFL) < current->addr_limit.seg)
48
49 #define access_ok(type,addr,size) __access_ok(addr,size)
50
51 extern inline int verify_area(int type, const void * addr, unsigned long size)
52 {
53 return access_ok(type,addr,size)?0:-EFAULT;
54 }
55
56 /*
57 * The exception table consists of pairs of addresses: the first is the
58 * address of an instruction that is allowed to fault, and the second is
59 * the address at which the program should continue. No registers are
60 * modified, so it is entirely up to the continuation code to figure out
61 * what to do.
62 *
63 * All the routines below use bits of fixup code that are out of line
64 * with the main instruction path. This means when everything is well,
65 * we don't even have to jump over them. Further, they do not intrude
66 * on our cache or tlb entries.
67 */
68
69 struct exception_table_entry
70 {
71 unsigned long insn, fixup;
72 };
73
74 /* Returns 0 if exception not found and fixup otherwise. */
75 extern unsigned long search_exception_table(unsigned long);
76
77
78 /*
79 * These are the main single-value transfer routines. They automatically
80 * use the right size if we just have the right pointer type.
81 */
82
83 extern inline int __put_user_asm_4(__u32 x, void *ptr)
84 {
85 int err;
86
87 __asm__ __volatile__ ( " iac 1\n"
88 " sr %1,%1\n"
89 " la 4,%0\n"
90 " sacf 512\n"
91 "0: st %2,0(4)\n"
92 " sacf 0(1)\n"
93 "1:\n"
94 ".section .fixup,\"ax\"\n"
95 "2: sacf 0(1)\n"
96 " lhi %1,%h3\n"
97 " bras 4,3f\n"
98 " .long 1b\n"
99 "3: l 4,0(4)\n"
100 " br 4\n"
101 ".previous\n"
102 ".section __ex_table,\"a\"\n"
103 " .align 4\n"
104 " .long 0b,2b\n"
105 ".previous"
106 : "=m" (*((__u32*) ptr)) , "=&d" (err)
107 : "d" (x), "K" (-EFAULT)
108 : "1", "4" );
109 return err;
110 }
111
112 extern inline int __put_user_asm_2(__u16 x, void *ptr)
113 {
114 int err;
115
116 __asm__ __volatile__ ( " iac 1\n"
117 " sr %1,%1\n"
118 " la 4,%0\n"
119 " sacf 512\n"
120 "0: sth %2,0(4)\n"
121 " sacf 0(1)\n"
122 "1:\n"
123 ".section .fixup,\"ax\"\n"
124 "2: sacf 0(1)\n"
125 " lhi %1,%h3\n"
126 " bras 4,3f\n"
127 " .long 1b\n"
128 "3: l 4,0(4)\n"
129 " br 4\n"
130 ".previous\n"
131 ".section __ex_table,\"a\"\n"
132 " .align 4\n"
133 " .long 0b,2b\n"
134 ".previous"
135 : "=m" (*((__u16*) ptr)) , "=&d" (err)
136 : "d" (x), "K" (-EFAULT)
137 : "1", "4" );
138 return err;
139 }
140
141 extern inline int __put_user_asm_1(__u8 x, void *ptr)
142 {
143 int err;
144
145 __asm__ __volatile__ ( " iac 1\n"
146 " sr %1,%1\n"
147 " la 4,%0\n"
148 " sacf 512\n"
149 "0: stc %2,0(4)\n"
150 " sacf 0(1)\n"
151 "1:\n"
152 ".section .fixup,\"ax\"\n"
153 "2: sacf 0(1)\n"
154 " lhi %1,%h3\n"
155 " bras 4,3f\n"
156 " .long 1b\n"
157 "3: l 4,0(4)\n"
158 " br 4\n"
159 ".previous\n"
160 ".section __ex_table,\"a\"\n"
161 " .align 4\n"
162 " .long 0b,2b\n"
163 ".previous"
164 : "=m" (*((__u8*) ptr)) , "=&d" (err)
165 : "d" (x), "K" (-EFAULT)
166 : "1", "4" );
167 return err;
168 }
169
170 /*
171 * (u8)(u32) ... autsch, but that the only way we can suppress the
172 * warnings when compiling binfmt_elf.c
173 */
174 #define __put_user(x, ptr) \
175 ({ \
176 int __pu_err; \
177 switch (sizeof (*(ptr))) { \
178 case 1: \
179 __pu_err = __put_user_asm_1((__u8)(__u32)x,ptr);\
180 break; \
181 case 2: \
182 __pu_err = __put_user_asm_2((__u16)(__u32)x,ptr);\
183 break; \
184 case 4: \
185 __pu_err = __put_user_asm_4((__u32) x,ptr);\
186 break; \
187 default: \
188 __pu_err = __put_user_bad(); \
189 break; \
190 } \
191 __pu_err; \
192 })
193
194 #define put_user(x, ptr) \
195 ({ \
196 long __pu_err = -EFAULT; \
197 __typeof__(*(ptr)) *__pu_addr = (ptr); \
198 __typeof__(x) __x = (x); \
199 if (__access_ok((long)__pu_addr,sizeof(*(ptr)))) { \
200 __pu_err = 0; \
201 __put_user((__x), (__pu_addr)); \
202 } \
203 __pu_err; \
204 })
205
206 extern int __put_user_bad(void);
207
208
209 #define __get_user_asm_4(x, ptr, err) \
210 ({ \
211 __asm__ __volatile__ ( " iac 1\n" \
212 " sr %1,%1\n" \
213 " la 4,%2\n" \
214 " sacf 512\n" \
215 "0: l %0,0(4)\n" \
216 " sacf 0(1)\n" \
217 "1:\n" \
218 ".section .fixup,\"ax\"\n" \
219 "2: sacf 0(1)\n" \
220 " lhi %1,%h3\n" \
221 " bras 4,3f\n" \
222 " .long 1b\n" \
223 "3: l 4,0(4)\n" \
224 " br 4\n" \
225 ".previous\n" \
226 ".section __ex_table,\"a\"\n" \
227 " .align 4\n" \
228 " .long 0b,2b\n" \
229 ".previous" \
230 : "=d" (x) , "=&d" (err) \
231 : "m" (*(__u32*) ptr), "K" (-EFAULT) \
232 : "1", "4" ); \
233 })
234
235 #define __get_user_asm_2(x, ptr, err) \
236 ({ \
237 __asm__ __volatile__ ( " iac 1\n" \
238 " sr %1,%1\n" \
239 " la 4,%2\n" \
240 " sacf 512\n" \
241 "0: lh %0,0(4)\n" \
242 " sacf 0(1)\n" \
243 "1:\n" \
244 ".section .fixup,\"ax\"\n" \
245 "2: sacf 0(1)\n" \
246 " lhi %1,%h3\n" \
247 " bras 4,3f\n" \
248 " .long 1b\n" \
249 "3: l 4,0(4)\n" \
250 " br 4\n" \
251 ".previous\n" \
252 ".section __ex_table,\"a\"\n" \
253 " .align 4\n" \
254 " .long 0b,2b\n" \
255 ".previous" \
256 : "=d" (x) , "=&d" (err) \
257 : "m" (*(__u16*) ptr), "K" (-EFAULT) \
258 : "1", "4" ); \
259 })
260
261 #define __get_user_asm_1(x, ptr, err) \
262 ({ \
263 __asm__ __volatile__ ( " iac 1\n" \
264 " sr %1,%1\n" \
265 " la 4,%2\n" \
266 " sr %0,%0\n" \
267 " sacf 512\n" \
268 "0: ic %0,0(4)\n" \
269 " sacf 0(1)\n" \
270 "1:\n" \
271 ".section .fixup,\"ax\"\n" \
272 "2: sacf 0(1)\n" \
273 " lhi %1,%h3\n" \
274 " bras 4,3f\n" \
275 " .long 1b\n" \
276 "3: l 4,0(4)\n" \
277 " br 4\n" \
278 ".previous\n" \
279 ".section __ex_table,\"a\"\n" \
280 " .align 4\n" \
281 " .long 0b,2b\n" \
282 ".previous" \
283 : "=d" (x) , "=&d" (err) \
284 : "m" (*(__u8*) ptr), "K" (-EFAULT) \
285 : "1", "4" ); \
286 })
287
288 #define __get_user(x, ptr) \
289 ({ \
290 int __gu_err; \
291 switch (sizeof(*(ptr))) { \
292 case 1: \
293 __get_user_asm_1(x,ptr,__gu_err); \
294 break; \
295 case 2: \
296 __get_user_asm_2(x,ptr,__gu_err); \
297 break; \
298 case 4: \
299 __get_user_asm_4(x,ptr,__gu_err); \
300 break; \
301 default: \
302 (x) = 0; \
303 __gu_err = __get_user_bad(); \
304 break; \
305 } \
306 __gu_err; \
307 })
308
309 #define get_user(x, ptr) \
310 ({ \
311 long __gu_err = -EFAULT; \
312 __typeof__(ptr) __gu_addr = (ptr); \
313 __typeof__(x) __x; \
314 if (__access_ok((long)__gu_addr,sizeof(*(ptr)))) { \
315 __gu_err = 0; \
316 __get_user((__x), (__gu_addr)); \
317 (x) = __x; \
318 } \
319 else \
320 (x) = 0; \
321 __gu_err; \
322 })
323
324 extern int __get_user_bad(void);
325
326 /*
327 * access register are set up, that 4 points to secondary (user) , 2 to primary (kernel)
328 */
329
330 extern inline unsigned long
331 __copy_to_user_asm(void* to, const void* from, long n)
332 {
333
334 __asm__ __volatile__ ( " iac 1\n"
335 " lr 2,%2\n"
336 " lr 4,%1\n"
337 " lr 3,%0\n"
338 " lr 5,3\n"
339 " sacf 512\n"
340 "0: mvcle 4,2,0\n"
341 " jo 0b\n"
342 "1: sacf 0(1)\n"
343 " lr %0,3\n"
344 ".section __ex_table,\"a\"\n"
345 " .align 4\n"
346 " .long 0b,1b\n"
347 ".previous"
348 : "+&d" (n) : "d" (to), "d" (from)
349 : "1", "2", "3", "4", "5" );
350 return n;
351 }
352
353 #define __copy_to_user(to, from, n) \
354 ({ \
355 __copy_to_user_asm(to,from,n); \
356 })
357
358 #define copy_to_user(to, from, n) \
359 ({ \
360 long err = 0; \
361 __typeof__(n) __n = (n); \
362 if (__access_ok(to,__n)) { \
363 err = __copy_to_user_asm(to,from,__n); \
364 } \
365 else \
366 err = __n; \
367 err; \
368 })
369
370 extern inline unsigned long
371 __copy_from_user_asm(void* to, const void* from, long n)
372 {
373 __asm__ __volatile__ ( " iac 1\n"
374 " lr 2,%1\n"
375 " lr 4,%2\n"
376 " lr 3,%0\n"
377 " lr 5,3\n"
378 " sacf 512\n"
379 "0: mvcle 2,4,0\n"
380 " jo 0b\n"
381 "1: sacf 0(1)\n"
382 " lr %0,3\n"
383 ".section __ex_table,\"a\"\n"
384 " .align 4\n"
385 " .long 0b,1b\n"
386 ".previous"
387 : "+&d" (n) : "d" (to), "d" (from)
388 : "1", "2", "3", "4", "5" );
389 return n;
390 }
391
392
393 #define __copy_from_user(to, from, n) \
394 ({ \
395 __copy_from_user_asm(to,from,n); \
396 })
397
398 #define copy_from_user(to, from, n) \
399 ({ \
400 long err = 0; \
401 __typeof__(n) __n = (n); \
402 if (__access_ok(from,__n)) { \
403 err = __copy_from_user_asm(to,from,__n); \
404 } \
405 else \
406 err = __n; \
407 err; \
408 })
409
410 /*
411 * Copy a null terminated string from userspace.
412 */
413
414 static inline long
415 strncpy_from_user(char *dst, const char *src, long count)
416 {
417 int len;
418 __asm__ __volatile__ ( " iac 1\n"
419 " slr %0,%0\n"
420 " lr 2,%1\n"
421 " lr 4,%2\n"
422 " slr 3,3\n"
423 " sacf 512\n"
424 "0: ic 3,0(%0,4)\n"
425 "1: stc 3,0(%0,2)\n"
426 " ltr 3,3\n"
427 " jz 2f\n"
428 " ahi %0,1\n"
429 " clr %0,%3\n"
430 " jl 0b\n"
431 "2: sacf 0(1)\n"
432 ".section .fixup,\"ax\"\n"
433 "3: lhi %0,%h4\n"
434 " basr 3,0\n"
435 " l 3,4f-.(3)\n"
436 " br 3\n"
437 "4: .long 2b\n"
438 ".previous\n"
439 ".section __ex_table,\"a\"\n"
440 " .align 4\n"
441 " .long 0b,3b\n"
442 " .long 1b,3b\n"
443 ".previous"
444 : "=&a" (len)
445 : "a" (dst), "d" (src), "d" (count),
446 "K" (-EFAULT)
447 : "1", "2", "3", "4", "memory" );
448 return len;
449 }
450
451 /*
452 * Return the size of a string (including the ending 0)
453 *
454 * Return 0 for error
455 */
456 static inline unsigned long
457 strnlen_user(const char * src, unsigned long n)
458 {
459 __asm__ __volatile__ (" iac 1\n"
460 " alr %0,%1\n"
461 " slr 0,0\n"
462 " lr 4,%1\n"
463 " sacf 512\n"
464 "0: srst %0,4\n"
465 " jo 0b\n"
466 " slr %0,%1\n"
467 " ahi %0,1\n"
468 " sacf 0(1)\n"
469 "1:\n"
470 ".section .fixup,\"ax\"\n"
471 "2: sacf 0(1)\n"
472 " slr %0,%0\n"
473 " bras 4,3f\n"
474 " .long 1b\n"
475 "3: l 4,0(4)\n"
476 " br 4\n"
477 ".previous\n"
478 ".section __ex_table,\"a\"\n"
479 " .align 4\n"
480 " .long 0b,2b\n"
481 ".previous"
482 : "+&a" (n) : "d" (src)
483 : "cc", "", "1", "4" );
484 return n;
485 }
486 #define strlen_user(str) strnlen_user(str, ~0UL)
487
488 /*
489 * Zero Userspace
490 */
491
492 static inline unsigned long
493 clear_user(void *to, unsigned long n)
494 {
495 __asm__ __volatile__ ( " iac 1\n"
496 " sacf 512\n"
497 " lr 4,%1\n"
498 " lr 5,%0\n"
499 " sr 2,2\n"
500 " sr 3,3\n"
501 "0: mvcle 4,2,0\n"
502 " jo 0b\n"
503 "1: sacf 0(1)\n"
504 " lr %0,3\n"
505 ".section __ex_table,\"a\"\n"
506 " .align 4\n"
507 " .long 0b,1b\n"
508 ".previous"
509 : "+&a" (n)
510 : "a" (to)
511 : "cc", "1", "2", "3", "4", "5" );
512 return n;
513 }
514
515 #endif /* _S390_UACCESS_H */
516