diff options
author | Gerald Schaefer <geraldsc@de.ibm.com> | 2006-12-04 09:40:45 -0500 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2006-12-04 09:40:45 -0500 |
commit | 59f35d53fde3987d071ea1c9bf1c9ba29fcb69fe (patch) | |
tree | 50853c1bf3ad3af080707fb2e6b3722d3d86db9e /arch/s390/lib/uaccess_std.c | |
parent | d57de5a36791cb1b7285649c62f183b0d3505f7d (diff) |
[S390] Add dynamic size check for usercopy functions.
Use a wrapper for copy_to/from_user to chose the best usercopy method.
The mvcos instruction is better for sizes greater than 256 bytes, if
mvcos is not available a page table walk is better for sizes greater
than 1024 bytes. Also removed the redundant copy_to/from_user_std_small
functions.
Signed-off-by: Gerald Schaefer <geraldsc@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'arch/s390/lib/uaccess_std.c')
-rw-r--r-- | arch/s390/lib/uaccess_std.c | 67 |
1 files changed, 15 insertions, 52 deletions
diff --git a/arch/s390/lib/uaccess_std.c b/arch/s390/lib/uaccess_std.c index f44f0078b354..2d549ed2e113 100644 --- a/arch/s390/lib/uaccess_std.c +++ b/arch/s390/lib/uaccess_std.c | |||
@@ -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) |
@@ -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, |