diff options
Diffstat (limited to 'arch/s390/lib/uaccess_std.c')
-rw-r--r-- | arch/s390/lib/uaccess_std.c | 73 |
1 files changed, 18 insertions, 55 deletions
diff --git a/arch/s390/lib/uaccess_std.c b/arch/s390/lib/uaccess_std.c index f44f0078b354..bbaca66fa293 100644 --- a/arch/s390/lib/uaccess_std.c +++ b/arch/s390/lib/uaccess_std.c | |||
@@ -11,7 +11,7 @@ | |||
11 | 11 | ||
12 | #include <linux/errno.h> | 12 | #include <linux/errno.h> |
13 | #include <linux/mm.h> | 13 | #include <linux/mm.h> |
14 | #include <asm/uaccess.h> | 14 | #include <linux/uaccess.h> |
15 | #include <asm/futex.h> | 15 | #include <asm/futex.h> |
16 | 16 | ||
17 | #ifndef __s390x__ | 17 | #ifndef __s390x__ |
@@ -28,6 +28,9 @@ | |||
28 | #define SLR "slgr" | 28 | #define SLR "slgr" |
29 | #endif | 29 | #endif |
30 | 30 | ||
31 | extern size_t copy_from_user_pt(size_t n, const void __user *from, void *to); | ||
32 | extern size_t copy_to_user_pt(size_t n, void __user *to, const void *from); | ||
33 | |||
31 | size_t copy_from_user_std(size_t size, const void __user *ptr, void *x) | 34 | size_t copy_from_user_std(size_t size, const void __user *ptr, void *x) |
32 | { | 35 | { |
33 | unsigned long tmp1, tmp2; | 36 | unsigned long tmp1, tmp2; |
@@ -69,34 +72,11 @@ size_t copy_from_user_std(size_t size, const void __user *ptr, void *x) | |||
69 | return size; | 72 | return size; |
70 | } | 73 | } |
71 | 74 | ||
72 | size_t copy_from_user_std_small(size_t size, const void __user *ptr, void *x) | 75 | size_t copy_from_user_std_check(size_t size, const void __user *ptr, void *x) |
73 | { | 76 | { |
74 | unsigned long tmp1, tmp2; | 77 | if (size <= 1024) |
75 | 78 | return copy_from_user_std(size, ptr, x); | |
76 | tmp1 = 0UL; | 79 | return copy_from_user_pt(size, ptr, x); |
77 | asm volatile( | ||
78 | "0: mvcp 0(%0,%2),0(%1),%3\n" | ||
79 | " "SLR" %0,%0\n" | ||
80 | " j 5f\n" | ||
81 | "1: la %4,255(%1)\n" /* %4 = ptr + 255 */ | ||
82 | " "LHI" %3,-4096\n" | ||
83 | " nr %4,%3\n" /* %4 = (ptr + 255) & -4096 */ | ||
84 | " "SLR" %4,%1\n" | ||
85 | " "CLR" %0,%4\n" /* copy crosses next page boundary? */ | ||
86 | " jnh 5f\n" | ||
87 | "2: mvcp 0(%4,%2),0(%1),%3\n" | ||
88 | " "SLR" %0,%4\n" | ||
89 | " "ALR" %2,%4\n" | ||
90 | "3:"LHI" %4,-1\n" | ||
91 | " "ALR" %4,%0\n" /* copy remaining size, subtract 1 */ | ||
92 | " bras %3,4f\n" | ||
93 | " xc 0(1,%2),0(%2)\n" | ||
94 | "4: ex %4,0(%3)\n" | ||
95 | "5:\n" | ||
96 | EX_TABLE(0b,1b) EX_TABLE(2b,3b) | ||
97 | : "+a" (size), "+a" (ptr), "+a" (x), "+a" (tmp1), "=a" (tmp2) | ||
98 | : : "cc", "memory"); | ||
99 | return size; | ||
100 | } | 80 | } |
101 | 81 | ||
102 | size_t copy_to_user_std(size_t size, void __user *ptr, const void *x) | 82 | size_t copy_to_user_std(size_t size, void __user *ptr, const void *x) |
@@ -130,28 +110,11 @@ size_t copy_to_user_std(size_t size, void __user *ptr, const void *x) | |||
130 | return size; | 110 | return size; |
131 | } | 111 | } |
132 | 112 | ||
133 | size_t copy_to_user_std_small(size_t size, void __user *ptr, const void *x) | 113 | size_t copy_to_user_std_check(size_t size, void __user *ptr, const void *x) |
134 | { | 114 | { |
135 | unsigned long tmp1, tmp2; | 115 | if (size <= 1024) |
136 | 116 | return copy_to_user_std(size, ptr, x); | |
137 | tmp1 = 0UL; | 117 | return copy_to_user_pt(size, ptr, x); |
138 | asm volatile( | ||
139 | "0: mvcs 0(%0,%1),0(%2),%3\n" | ||
140 | " "SLR" %0,%0\n" | ||
141 | " j 3f\n" | ||
142 | "1: la %4,255(%1)\n" /* ptr + 255 */ | ||
143 | " "LHI" %3,-4096\n" | ||
144 | " nr %4,%3\n" /* (ptr + 255) & -4096UL */ | ||
145 | " "SLR" %4,%1\n" | ||
146 | " "CLR" %0,%4\n" /* copy crosses next page boundary? */ | ||
147 | " jnh 3f\n" | ||
148 | "2: mvcs 0(%4,%1),0(%2),%3\n" | ||
149 | " "SLR" %0,%4\n" | ||
150 | "3:\n" | ||
151 | EX_TABLE(0b,1b) EX_TABLE(2b,3b) | ||
152 | : "+a" (size), "+a" (ptr), "+a" (x), "+a" (tmp1), "=a" (tmp2) | ||
153 | : : "cc", "memory"); | ||
154 | return size; | ||
155 | } | 118 | } |
156 | 119 | ||
157 | size_t copy_in_user_std(size_t size, void __user *to, const void __user *from) | 120 | size_t copy_in_user_std(size_t size, void __user *to, const void __user *from) |
@@ -295,7 +258,7 @@ int futex_atomic_op(int op, int __user *uaddr, int oparg, int *old) | |||
295 | { | 258 | { |
296 | int oldval = 0, newval, ret; | 259 | int oldval = 0, newval, ret; |
297 | 260 | ||
298 | inc_preempt_count(); | 261 | pagefault_disable(); |
299 | 262 | ||
300 | switch (op) { | 263 | switch (op) { |
301 | case FUTEX_OP_SET: | 264 | case FUTEX_OP_SET: |
@@ -321,7 +284,7 @@ int futex_atomic_op(int op, int __user *uaddr, int oparg, int *old) | |||
321 | default: | 284 | default: |
322 | ret = -ENOSYS; | 285 | ret = -ENOSYS; |
323 | } | 286 | } |
324 | dec_preempt_count(); | 287 | pagefault_enable(); |
325 | *old = oldval; | 288 | *old = oldval; |
326 | return ret; | 289 | return ret; |
327 | } | 290 | } |
@@ -343,10 +306,10 @@ int futex_atomic_cmpxchg(int __user *uaddr, int oldval, int newval) | |||
343 | } | 306 | } |
344 | 307 | ||
345 | struct uaccess_ops uaccess_std = { | 308 | struct uaccess_ops uaccess_std = { |
346 | .copy_from_user = copy_from_user_std, | 309 | .copy_from_user = copy_from_user_std_check, |
347 | .copy_from_user_small = copy_from_user_std_small, | 310 | .copy_from_user_small = copy_from_user_std, |
348 | .copy_to_user = copy_to_user_std, | 311 | .copy_to_user = copy_to_user_std_check, |
349 | .copy_to_user_small = copy_to_user_std_small, | 312 | .copy_to_user_small = copy_to_user_std, |
350 | .copy_in_user = copy_in_user_std, | 313 | .copy_in_user = copy_in_user_std, |
351 | .clear_user = clear_user_std, | 314 | .clear_user = clear_user_std, |
352 | .strnlen_user = strnlen_user_std, | 315 | .strnlen_user = strnlen_user_std, |