2 * include/asm-s390/uaccess.h
5 * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
6 * Author(s): Hartmut Penner (hpenner@de.ibm.com),
7 * Martin Schwidefsky (schwidefsky@de.ibm.com)
9 * Derived from "include/asm-i386/uaccess.h"
11 #ifndef __S390_UACCESS_H
12 #define __S390_UACCESS_H
15 * User space memory access functions
17 #include <linux/sched.h>
20 #define VERIFY_WRITE 1
24 * The fs value determines whether argument validity checking should be
25 * performed or not. If get_fs() == USER_DS, checking is performed, with
26 * get_fs() == KERNEL_DS, checking is bypassed.
28 * For historical reasons, these macros are grossly misnamed.
31 #define MAKE_MM_SEG(s) ((mm_segment_t) { (s) })
34 #define KERNEL_DS MAKE_MM_SEG(0)
35 #define USER_DS MAKE_MM_SEG(1)
37 #define get_ds() (KERNEL_DS)
38 #define get_fs() (current->addr_limit)
39 #define set_fs(x) ({asm volatile("sar 4,%0"::"a" ((x).ar4));\
40 current->addr_limit = (x);})
42 #define segment_eq(a,b) ((a).ar4 == (b).ar4)
45 #define __access_ok(addr,size) (1)
47 #define access_ok(type,addr,size) __access_ok(addr,size)
49 extern inline int verify_area(int type, const void * addr, unsigned long size)
51 return access_ok(type,addr,size)?0:-EFAULT;
55 * The exception table consists of pairs of addresses: the first is the
56 * address of an instruction that is allowed to fault, and the second is
57 * the address at which the program should continue. No registers are
58 * modified, so it is entirely up to the continuation code to figure out
61 * All the routines below use bits of fixup code that are out of line
62 * with the main instruction path. This means when everything is well,
63 * we don't even have to jump over them. Further, they do not intrude
64 * on our cache or tlb entries.
67 struct exception_table_entry
69 unsigned long insn, fixup;
72 /* Returns 0 if exception not found and fixup otherwise. */
73 extern unsigned long search_exception_table(unsigned long);
77 * These are the main single-value transfer routines. They automatically
78 * use the right size if we just have the right pointer type.
81 extern inline int __put_user_asm_8(__u64 x, void *ptr)
85 __asm__ __volatile__ ( " sr %1,%1\n"
90 ".section .fixup,\"ax\"\n"
94 ".section __ex_table,\"a\"\n"
98 : "=m" (*((__u64*) ptr)) , "=&d" (err)
99 : "d" (x), "K" (-EFAULT)
103 extern inline int __put_user_asm_4(__u32 x, void *ptr)
107 __asm__ __volatile__ ( " sr %1,%1\n"
112 ".section .fixup,\"ax\"\n"
116 ".section __ex_table,\"a\"\n"
120 : "=m" (*((__u32*) ptr)) , "=&d" (err)
121 : "d" (x), "K" (-EFAULT)
126 extern inline int __put_user_asm_2(__u16 x, void *ptr)
130 __asm__ __volatile__ ( " sr %1,%1\n"
135 ".section .fixup,\"ax\"\n"
139 ".section __ex_table,\"a\"\n"
143 : "=m" (*((__u16*) ptr)) , "=&d" (err)
144 : "d" (x), "K" (-EFAULT)
149 extern inline int __put_user_asm_1(__u8 x, void *ptr)
153 __asm__ __volatile__ ( " sr %1,%1\n"
158 ".section .fixup,\"ax\"\n"
162 ".section __ex_table,\"a\"\n"
166 : "=m" (*((__u8*) ptr)) , "=&d" (err)
167 : "d" (x), "K" (-EFAULT)
173 * (u?)(u64) ... autsch, but that the only way we can suppress the
174 * warnings when compiling binfmt_elf.c
176 #define __put_user(x, ptr) \
178 __typeof__(*(ptr)) *__pu_addr = (ptr); \
179 __typeof__(*(ptr)) __x = (x); \
181 switch (sizeof (*(__pu_addr))) { \
183 __pu_err = __put_user_asm_1((__u8)(__u64)(__x), \
187 __pu_err = __put_user_asm_2((__u16)(__u64)(__x),\
191 __pu_err = __put_user_asm_4((__u32)(__u64)(__x),\
195 __pu_err = __put_user_asm_8((__u64)(__x), \
199 __pu_err = __put_user_bad(); \
205 #define put_user(x, ptr) __put_user(x, ptr)
207 extern int __put_user_bad(void);
209 #define __get_user_asm_8(x, ptr, err) \
211 __asm__ __volatile__ ( " sr %1,%1\n" \
216 ".section .fixup,\"ax\"\n" \
220 ".section __ex_table,\"a\"\n" \
224 : "=d" (x) , "=&d" (err) \
225 : "m" (*(const __u64*)(ptr)),"K" (-EFAULT) \
228 #define __get_user_asm_4(x, ptr, err) \
230 __asm__ __volatile__ ( " sr %1,%1\n" \
235 ".section .fixup,\"ax\"\n" \
239 ".section __ex_table,\"a\"\n" \
243 : "=d" (x) , "=&d" (err) \
244 : "m" (*(const __u32*)(ptr)),"K" (-EFAULT) \
248 #define __get_user_asm_2(x, ptr, err) \
250 __asm__ __volatile__ ( " sr %1,%1\n" \
255 ".section .fixup,\"ax\"\n" \
259 ".section __ex_table,\"a\"\n" \
263 : "=d" (x) , "=&d" (err) \
264 : "m" (*(const __u16*)(ptr)),"K" (-EFAULT) \
268 #define __get_user_asm_1(x, ptr, err) \
270 __asm__ __volatile__ ( " sr %1,%1\n" \
276 ".section .fixup,\"ax\"\n" \
280 ".section __ex_table,\"a\"\n" \
284 : "=d" (x) , "=&d" (err) \
285 : "m" (*(const __u8*)(ptr)),"K" (-EFAULT) \
289 #define __get_user(x, ptr) \
291 __typeof__(ptr) __gu_addr = (ptr); \
292 __typeof__(*(ptr)) __x; \
294 switch (sizeof(*(ptr))) { \
296 __get_user_asm_1(__x,__gu_addr,__gu_err); \
299 __get_user_asm_2(__x,__gu_addr,__gu_err); \
302 __get_user_asm_4(__x,__gu_addr,__gu_err); \
305 __get_user_asm_8(__x,__gu_addr,__gu_err); \
309 __gu_err = __get_user_bad(); \
316 #define get_user(x, ptr) __get_user(x, ptr)
318 extern int __get_user_bad(void);
321 * access register are set up, that 4 points to secondary (user) , 2 to primary (kernel)
324 extern long __copy_to_user_asm(const void *from, long n, void *to);
326 #define __copy_to_user(to, from, n) \
328 __copy_to_user_asm(from, n, to); \
331 #define copy_to_user(to, from, n) \
334 __typeof__(n) __n = (n); \
335 if (__access_ok(to,__n)) { \
336 err = __copy_to_user_asm(from, __n, to); \
343 extern long __copy_from_user_asm(void *to, long n, const void *from);
345 #define __copy_from_user(to, from, n) \
347 __copy_from_user_asm(to, n, from); \
350 #define copy_from_user(to, from, n) \
353 __typeof__(n) __n = (n); \
354 if (__access_ok(from,__n)) { \
355 err = __copy_from_user_asm(to, __n, from); \
363 * Copy a null terminated string from userspace.
367 __strncpy_from_user(char *dst, const char *src, long count)
370 __asm__ __volatile__ ( " slgr %0,%0\n"
383 ".section .fixup,\"ax\"\n"
387 ".section __ex_table,\"a\"\n"
393 : "a" (dst), "d" (src), "d" (count),
395 : "cc", "2" ,"3", "4" );
400 strncpy_from_user(char *dst, const char *src, long count)
403 if (access_ok(VERIFY_READ, src, 1))
404 res = __strncpy_from_user(dst, src, count);
409 * Return the size of a string (including the ending 0)
413 static inline unsigned long
414 strnlen_user(const char * src, unsigned long n)
417 __asm__ __volatile__ (" algr %0,%1\n"
426 ".section .fixup,\"ax\"\n"
430 ".section __ex_table,\"a\"\n"
434 : "+&a" (n) : "d" (src)
437 __asm__ __volatile__ (" lgr 4,%1\n"
446 ".section .fixup,\"ax\"\n"
450 ".section __ex_table,\"a\"\n"
454 : "+&a" (n) : "d" (src)
459 #define strlen_user(str) strnlen_user(str, ~0UL)
465 extern long __clear_user_asm(void *to, long n);
467 #define __clear_user(to, n) \
469 __clear_user_asm(to, n); \
472 static inline unsigned long
473 clear_user(void *to, unsigned long n)
475 if (access_ok(VERIFY_WRITE, to, n))
476 n = __clear_user(to, n);
480 #endif /* _S390_UACCESS_H */