diff options
Diffstat (limited to 'include/asm-s390/uaccess.h')
-rw-r--r-- | include/asm-s390/uaccess.h | 262 |
1 files changed, 142 insertions, 120 deletions
diff --git a/include/asm-s390/uaccess.h b/include/asm-s390/uaccess.h index a19cfa29f..3bcf7bbed 100644 --- a/include/asm-s390/uaccess.h +++ b/include/asm-s390/uaccess.h @@ -84,15 +84,14 @@ extern inline int __put_user_asm_4(__u32 x, void *ptr) { int err; - __asm__ __volatile__ ( " iac 1\n" - " sr %1,%1\n" + __asm__ __volatile__ ( " sr %1,%1\n" " la 4,%0\n" " sacf 512\n" "0: st %2,0(4)\n" - " sacf 0(1)\n" + " sacf 0\n" "1:\n" ".section .fixup,\"ax\"\n" - "2: sacf 0(1)\n" + "2: sacf 0\n" " lhi %1,%h3\n" " bras 4,3f\n" " .long 1b\n" @@ -105,7 +104,7 @@ extern inline int __put_user_asm_4(__u32 x, void *ptr) ".previous" : "=m" (*((__u32*) ptr)) , "=&d" (err) : "d" (x), "K" (-EFAULT) - : "1", "4" ); + : "4" ); return err; } @@ -113,15 +112,14 @@ extern inline int __put_user_asm_2(__u16 x, void *ptr) { int err; - __asm__ __volatile__ ( " iac 1\n" - " sr %1,%1\n" + __asm__ __volatile__ ( " sr %1,%1\n" " la 4,%0\n" " sacf 512\n" "0: sth %2,0(4)\n" - " sacf 0(1)\n" + " sacf 0\n" "1:\n" ".section .fixup,\"ax\"\n" - "2: sacf 0(1)\n" + "2: sacf 0\n" " lhi %1,%h3\n" " bras 4,3f\n" " .long 1b\n" @@ -134,7 +132,7 @@ extern inline int __put_user_asm_2(__u16 x, void *ptr) ".previous" : "=m" (*((__u16*) ptr)) , "=&d" (err) : "d" (x), "K" (-EFAULT) - : "1", "4" ); + : "4" ); return err; } @@ -142,15 +140,14 @@ extern inline int __put_user_asm_1(__u8 x, void *ptr) { int err; - __asm__ __volatile__ ( " iac 1\n" - " sr %1,%1\n" + __asm__ __volatile__ ( " sr %1,%1\n" " la 4,%0\n" " sacf 512\n" "0: stc %2,0(4)\n" - " sacf 0(1)\n" + " sacf 0\n" "1:\n" ".section .fixup,\"ax\"\n" - "2: sacf 0(1)\n" + "2: sacf 0\n" " lhi %1,%h3\n" " bras 4,3f\n" " .long 1b\n" @@ -163,7 +160,7 @@ extern inline int __put_user_asm_1(__u8 x, void *ptr) ".previous" : "=m" (*((__u8*) ptr)) , "=&d" (err) : "d" (x), "K" (-EFAULT) - : "1", "4" ); + : "4" ); return err; } @@ -176,13 +173,13 @@ extern inline int __put_user_asm_1(__u8 x, void *ptr) int __pu_err; \ switch (sizeof (*(ptr))) { \ case 1: \ - __pu_err = __put_user_asm_1((__u8)(__u32)x,ptr);\ + __pu_err = __put_user_asm_1((__u8)(__u32)x,(ptr));\ break; \ case 2: \ - __pu_err = __put_user_asm_2((__u16)(__u32)x,ptr);\ + __pu_err = __put_user_asm_2((__u16)(__u32)x,(ptr));\ break; \ case 4: \ - __pu_err = __put_user_asm_4((__u32) x,ptr);\ + __pu_err = __put_user_asm_4((__u32) x,(ptr));\ break; \ default: \ __pu_err = __put_user_bad(); \ @@ -195,7 +192,7 @@ extern inline int __put_user_asm_1(__u8 x, void *ptr) ({ \ long __pu_err = -EFAULT; \ __typeof__(*(ptr)) *__pu_addr = (ptr); \ - __typeof__(x) __x = (x); \ + __typeof__(*(ptr)) __x = (x); \ if (__access_ok((long)__pu_addr,sizeof(*(ptr)))) { \ __pu_err = 0; \ __put_user((__x), (__pu_addr)); \ @@ -206,83 +203,80 @@ extern inline int __put_user_asm_1(__u8 x, void *ptr) extern int __put_user_bad(void); -#define __get_user_asm_4(x, ptr, err) \ -({ \ - __asm__ __volatile__ ( " iac 1\n" \ - " sr %1,%1\n" \ - " la 4,%2\n" \ - " sacf 512\n" \ - "0: l %0,0(4)\n" \ - " sacf 0(1)\n" \ - "1:\n" \ - ".section .fixup,\"ax\"\n" \ - "2: sacf 0(1)\n" \ - " lhi %1,%h3\n" \ - " bras 4,3f\n" \ - " .long 1b\n" \ - "3: l 4,0(4)\n" \ - " br 4\n" \ - ".previous\n" \ - ".section __ex_table,\"a\"\n" \ - " .align 4\n" \ - " .long 0b,2b\n" \ - ".previous" \ - : "=d" (x) , "=&d" (err) \ - : "m" (*(__u32*) ptr), "K" (-EFAULT) \ - : "1", "4" ); \ +#define __get_user_asm_4(x, ptr, err) \ +({ \ + __asm__ __volatile__ ( " sr %1,%1\n" \ + " la 4,%2\n" \ + " sacf 512\n" \ + "0: l %0,0(4)\n" \ + " sacf 0\n" \ + "1:\n" \ + ".section .fixup,\"ax\"\n" \ + "2: sacf 0\n" \ + " lhi %1,%h3\n" \ + " bras 4,3f\n" \ + " .long 1b\n" \ + "3: l 4,0(4)\n" \ + " br 4\n" \ + ".previous\n" \ + ".section __ex_table,\"a\"\n" \ + " .align 4\n" \ + " .long 0b,2b\n" \ + ".previous" \ + : "=d" (x) , "=&d" (err) \ + : "m" (*(const __u32*)(ptr)),"K" (-EFAULT) \ + : "4" ); \ }) -#define __get_user_asm_2(x, ptr, err) \ -({ \ - __asm__ __volatile__ ( " iac 1\n" \ - " sr %1,%1\n" \ - " la 4,%2\n" \ - " sacf 512\n" \ - "0: lh %0,0(4)\n" \ - " sacf 0(1)\n" \ - "1:\n" \ - ".section .fixup,\"ax\"\n" \ - "2: sacf 0(1)\n" \ - " lhi %1,%h3\n" \ - " bras 4,3f\n" \ - " .long 1b\n" \ - "3: l 4,0(4)\n" \ - " br 4\n" \ - ".previous\n" \ - ".section __ex_table,\"a\"\n" \ - " .align 4\n" \ - " .long 0b,2b\n" \ - ".previous" \ - : "=d" (x) , "=&d" (err) \ - : "m" (*(__u16*) ptr), "K" (-EFAULT) \ - : "1", "4" ); \ +#define __get_user_asm_2(x, ptr, err) \ +({ \ + __asm__ __volatile__ ( " sr %1,%1\n" \ + " la 4,%2\n" \ + " sacf 512\n" \ + "0: lh %0,0(4)\n" \ + " sacf 0\n" \ + "1:\n" \ + ".section .fixup,\"ax\"\n" \ + "2: sacf 0\n" \ + " lhi %1,%h3\n" \ + " bras 4,3f\n" \ + " .long 1b\n" \ + "3: l 4,0(4)\n" \ + " br 4\n" \ + ".previous\n" \ + ".section __ex_table,\"a\"\n" \ + " .align 4\n" \ + " .long 0b,2b\n" \ + ".previous" \ + : "=d" (x) , "=&d" (err) \ + : "m" (*(const __u16*)(ptr)),"K" (-EFAULT) \ + : "4" ); \ }) -#define __get_user_asm_1(x, ptr, err) \ -({ \ - __asm__ __volatile__ ( " iac 1\n" \ - " sr %1,%1\n" \ - " la 4,%2\n" \ - " sr %0,%0\n" \ - " sacf 512\n" \ - "0: ic %0,0(4)\n" \ - " sacf 0(1)\n" \ - "1:\n" \ - ".section .fixup,\"ax\"\n" \ - "2: sacf 0(1)\n" \ - " lhi %1,%h3\n" \ - " bras 4,3f\n" \ - " .long 1b\n" \ - "3: l 4,0(4)\n" \ - " br 4\n" \ - ".previous\n" \ - ".section __ex_table,\"a\"\n" \ - " .align 4\n" \ - " .long 0b,2b\n" \ - ".previous" \ - : "=d" (x) , "=&d" (err) \ - : "m" (*(__u8*) ptr), "K" (-EFAULT) \ - : "1", "4" ); \ +#define __get_user_asm_1(x, ptr, err) \ +({ \ + __asm__ __volatile__ ( " sr %1,%1\n" \ + " la 4,%2\n" \ + " sr %0,%0\n" \ + " sacf 512\n" \ + "0: ic %0,0(4)\n" \ + " sacf 0\n" \ + "1:\n" \ + ".section .fixup,\"ax\"\n" \ + "2: sacf 0\n" \ + " lhi %1,%h3\n" \ + " bras 4,3f\n" \ + " .long 1b\n" \ + "3: l 4,0(4)\n" \ + " br 4\n" \ + ".previous\n" \ + ".section __ex_table,\"a\"\n" \ + " .align 4\n" \ + " .long 0b,2b\n" \ + ".previous" \ + : "=d" (x) , "=&d" (err) \ + : "m" (*(const __u8*)(ptr)),"K" (-EFAULT) \ + : "4" ); \ }) #define __get_user(x, ptr) \ @@ -310,7 +304,7 @@ extern int __put_user_bad(void); ({ \ long __gu_err = -EFAULT; \ __typeof__(ptr) __gu_addr = (ptr); \ - __typeof__(x) __x; \ + __typeof__(*(ptr)) __x; \ if (__access_ok((long)__gu_addr,sizeof(*(ptr)))) { \ __gu_err = 0; \ __get_user((__x), (__gu_addr)); \ @@ -327,26 +321,28 @@ extern int __get_user_bad(void); * access register are set up, that 4 points to secondary (user) , 2 to primary (kernel) */ +asmlinkage void __copy_from_user_fixup(void /* special calling convention */); +asmlinkage void __copy_to_user_fixup(void /* special calling convention */); + extern inline unsigned long __copy_to_user_asm(void* to, const void* from, long n) { - __asm__ __volatile__ ( " iac 1\n" - " lr 2,%2\n" + __asm__ __volatile__ ( " lr 2,%2\n" " lr 4,%1\n" " lr 3,%0\n" " lr 5,3\n" " sacf 512\n" "0: mvcle 4,2,0\n" " jo 0b\n" - "1: sacf 0(1)\n" + " sacf 0\n" " lr %0,3\n" ".section __ex_table,\"a\"\n" " .align 4\n" - " .long 0b,1b\n" + " .long 0b,__copy_to_user_fixup\n" ".previous" : "+&d" (n) : "d" (to), "d" (from) - : "1", "2", "3", "4", "5" ); + : "2", "3", "4", "5" ); return n; } @@ -370,22 +366,21 @@ __copy_to_user_asm(void* to, const void* from, long n) extern inline unsigned long __copy_from_user_asm(void* to, const void* from, long n) { - __asm__ __volatile__ ( " iac 1\n" - " lr 2,%1\n" + __asm__ __volatile__ ( " lr 2,%1\n" " lr 4,%2\n" " lr 3,%0\n" " lr 5,3\n" " sacf 512\n" "0: mvcle 2,4,0\n" " jo 0b\n" - "1: sacf 0(1)\n" + " sacf 0\n" " lr %0,3\n" ".section __ex_table,\"a\"\n" " .align 4\n" - " .long 0b,1b\n" + " .long 0b,__copy_from_user_fixup\n" ".previous" : "+&d" (n) : "d" (to), "d" (from) - : "1", "2", "3", "4", "5" ); + : "2", "3", "4", "5" ); return n; } @@ -412,11 +407,10 @@ __copy_from_user_asm(void* to, const void* from, long n) */ static inline long -strncpy_from_user(char *dst, const char *src, long count) +__strncpy_from_user(char *dst, const char *src, long count) { int len; - __asm__ __volatile__ ( " iac 1\n" - " slr %0,%0\n" + __asm__ __volatile__ ( " slr %0,%0\n" " lr 2,%1\n" " lr 4,%2\n" " slr 3,3\n" @@ -428,7 +422,7 @@ strncpy_from_user(char *dst, const char *src, long count) " ahi %0,1\n" " clr %0,%3\n" " jl 0b\n" - "2: sacf 0(1)\n" + "2: sacf 0\n" ".section .fixup,\"ax\"\n" "3: lhi %0,%h4\n" " basr 3,0\n" @@ -444,10 +438,20 @@ strncpy_from_user(char *dst, const char *src, long count) : "=&a" (len) : "a" (dst), "d" (src), "d" (count), "K" (-EFAULT) - : "1", "2", "3", "4", "memory" ); + : "2", "3", "4", "memory" ); return len; } +static inline long +strncpy_from_user(char *dst, const char *src, long count) +{ + long res = -EFAULT; + if (access_ok(VERIFY_READ, src, 1)) + res = __strncpy_from_user(dst, src, count); + return res; +} + + /* * Return the size of a string (including the ending 0) * @@ -456,8 +460,7 @@ strncpy_from_user(char *dst, const char *src, long count) static inline unsigned long strnlen_user(const char * src, unsigned long n) { - __asm__ __volatile__ (" iac 1\n" - " alr %0,%1\n" + __asm__ __volatile__ (" alr %0,%1\n" " slr 0,0\n" " lr 4,%1\n" " sacf 512\n" @@ -465,10 +468,10 @@ strnlen_user(const char * src, unsigned long n) " jo 0b\n" " slr %0,%1\n" " ahi %0,1\n" - " sacf 0(1)\n" + " sacf 0\n" "1:\n" ".section .fixup,\"ax\"\n" - "2: sacf 0(1)\n" + "2: sacf 0\n" " slr %0,%0\n" " bras 4,3f\n" " .long 1b\n" @@ -480,7 +483,7 @@ strnlen_user(const char * src, unsigned long n) " .long 0b,2b\n" ".previous" : "+&a" (n) : "d" (src) - : "cc", "0", "1", "4" ); + : "cc", "0", "4" ); return n; } #define strlen_user(str) strnlen_user(str, ~0UL) @@ -490,26 +493,45 @@ strnlen_user(const char * src, unsigned long n) */ static inline unsigned long -clear_user(void *to, unsigned long n) +__clear_user(void *to, unsigned long n) { - __asm__ __volatile__ ( " iac 1\n" - " sacf 512\n" + __asm__ __volatile__ ( " sacf 512\n" " lr 4,%1\n" " lr 5,%0\n" " sr 2,2\n" " sr 3,3\n" "0: mvcle 4,2,0\n" " jo 0b\n" - "1: sacf 0(1)\n" - " lr %0,3\n" + " sacf 0\n" + "1: lr %0,3\n" + ".section .fixup,\"ax\"\n" + "2: lhi 5,-4096\n" + " n 5,0x90\n" + " sr 5,4\n" + " mvcle 4,2,0\n" + " sacf 0\n" + " basr 4,0\n" + " l 4,3f-.(4)\n" + " br 4\n" + "3: .long 1b\n" + ".previous\n" ".section __ex_table,\"a\"\n" " .align 4\n" - " .long 0b,1b\n" + " .long 0b,2b\n" ".previous" : "+&a" (n) : "a" (to) - : "cc", "1", "2", "3", "4", "5" ); + : "cc", "2", "3", "4", "5" ); + return n; +} + +static inline unsigned long +clear_user(void *to, unsigned long n) +{ + if (access_ok(VERIFY_WRITE, to, n)) + n = __clear_user(to, n); return n; } + #endif /* _S390_UACCESS_H */ |