summaryrefslogtreecommitdiffstats
path: root/include/asm-s390/uaccess.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/asm-s390/uaccess.h')
-rw-r--r--include/asm-s390/uaccess.h262
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 */