diff options
Diffstat (limited to 'arch/s390/lib/uaccess_std.c')
-rw-r--r-- | arch/s390/lib/uaccess_std.c | 48 |
1 files changed, 18 insertions, 30 deletions
diff --git a/arch/s390/lib/uaccess_std.c b/arch/s390/lib/uaccess_std.c index 6fbd06338270..4a75d475b06a 100644 --- a/arch/s390/lib/uaccess_std.c +++ b/arch/s390/lib/uaccess_std.c | |||
@@ -188,6 +188,8 @@ size_t strnlen_user_std(size_t size, const char __user *src) | |||
188 | register unsigned long reg0 asm("0") = 0UL; | 188 | register unsigned long reg0 asm("0") = 0UL; |
189 | unsigned long tmp1, tmp2; | 189 | unsigned long tmp1, tmp2; |
190 | 190 | ||
191 | if (unlikely(!size)) | ||
192 | return 0; | ||
191 | asm volatile( | 193 | asm volatile( |
192 | " la %2,0(%1)\n" | 194 | " la %2,0(%1)\n" |
193 | " la %3,0(%0,%1)\n" | 195 | " la %3,0(%0,%1)\n" |
@@ -204,38 +206,24 @@ size_t strnlen_user_std(size_t size, const char __user *src) | |||
204 | return size; | 206 | return size; |
205 | } | 207 | } |
206 | 208 | ||
207 | size_t strncpy_from_user_std(size_t size, const char __user *src, char *dst) | 209 | size_t strncpy_from_user_std(size_t count, const char __user *src, char *dst) |
208 | { | 210 | { |
209 | register unsigned long reg0 asm("0") = 0UL; | 211 | size_t done, len, offset, len_str; |
210 | unsigned long tmp1, tmp2; | ||
211 | 212 | ||
212 | asm volatile( | 213 | if (unlikely(!count)) |
213 | " la %3,0(%1)\n" | 214 | return 0; |
214 | " la %4,0(%0,%1)\n" | 215 | done = 0; |
215 | " sacf 256\n" | 216 | do { |
216 | "0: srst %4,%3\n" | 217 | offset = (size_t)src & ~PAGE_MASK; |
217 | " jo 0b\n" | 218 | len = min(count - done, PAGE_SIZE - offset); |
218 | " sacf 0\n" | 219 | if (copy_from_user_std(len, src, dst)) |
219 | " la %0,0(%4)\n" | 220 | return -EFAULT; |
220 | " jh 1f\n" /* found \0 in string ? */ | 221 | len_str = strnlen(dst, len); |
221 | " "AHI" %4,1\n" /* include \0 in copy */ | 222 | done += len_str; |
222 | "1:"SLR" %0,%1\n" /* %0 = return length (without \0) */ | 223 | src += len_str; |
223 | " "SLR" %4,%1\n" /* %4 = copy length (including \0) */ | 224 | dst += len_str; |
224 | "2: mvcp 0(%4,%2),0(%1),%5\n" | 225 | } while ((len_str == len) && (done < count)); |
225 | " jz 9f\n" | 226 | return done; |
226 | "3:"AHI" %4,-256\n" | ||
227 | " la %1,256(%1)\n" | ||
228 | " la %2,256(%2)\n" | ||
229 | "4: mvcp 0(%4,%2),0(%1),%5\n" | ||
230 | " jnz 3b\n" | ||
231 | " j 9f\n" | ||
232 | "7: sacf 0\n" | ||
233 | "8:"LHI" %0,%6\n" | ||
234 | "9:\n" | ||
235 | EX_TABLE(0b,7b) EX_TABLE(2b,8b) EX_TABLE(4b,8b) | ||
236 | : "+a" (size), "+a" (src), "+d" (dst), "=a" (tmp1), "=a" (tmp2) | ||
237 | : "d" (reg0), "K" (-EFAULT) : "cc", "memory"); | ||
238 | return size; | ||
239 | } | 227 | } |
240 | 228 | ||
241 | #define __futex_atomic_op(insn, ret, oldval, newval, uaddr, oparg) \ | 229 | #define __futex_atomic_op(insn, ret, oldval, newval, uaddr, oparg) \ |