aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/lib/uaccess_pt.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390/lib/uaccess_pt.c')
-rw-r--r--arch/s390/lib/uaccess_pt.c69
1 files changed, 28 insertions, 41 deletions
diff --git a/arch/s390/lib/uaccess_pt.c b/arch/s390/lib/uaccess_pt.c
index 61ebcc9ccb34..8d39760bae68 100644
--- a/arch/s390/lib/uaccess_pt.c
+++ b/arch/s390/lib/uaccess_pt.c
@@ -22,7 +22,7 @@
22#define SLR "slgr" 22#define SLR "slgr"
23#endif 23#endif
24 24
25static size_t strnlen_kernel(size_t count, const char __user *src) 25static unsigned long strnlen_kernel(const char __user *src, unsigned long count)
26{ 26{
27 register unsigned long reg0 asm("0") = 0UL; 27 register unsigned long reg0 asm("0") = 0UL;
28 unsigned long tmp1, tmp2; 28 unsigned long tmp1, tmp2;
@@ -42,8 +42,8 @@ static size_t strnlen_kernel(size_t count, const char __user *src)
42 return count; 42 return count;
43} 43}
44 44
45static size_t copy_in_kernel(size_t count, void __user *to, 45static unsigned long copy_in_kernel(void __user *to, const void __user *from,
46 const void __user *from) 46 unsigned long count)
47{ 47{
48 unsigned long tmp1; 48 unsigned long tmp1;
49 49
@@ -146,8 +146,8 @@ static unsigned long follow_table(struct mm_struct *mm,
146 146
147#endif /* CONFIG_64BIT */ 147#endif /* CONFIG_64BIT */
148 148
149static __always_inline size_t __user_copy_pt(unsigned long uaddr, void *kptr, 149static inline unsigned long __user_copy_pt(unsigned long uaddr, void *kptr,
150 size_t n, int write_user) 150 unsigned long n, int write_user)
151{ 151{
152 struct mm_struct *mm = current->mm; 152 struct mm_struct *mm = current->mm;
153 unsigned long offset, done, size, kaddr; 153 unsigned long offset, done, size, kaddr;
@@ -189,8 +189,7 @@ fault:
189 * Do DAT for user address by page table walk, return kernel address. 189 * Do DAT for user address by page table walk, return kernel address.
190 * This function needs to be called with current->mm->page_table_lock held. 190 * This function needs to be called with current->mm->page_table_lock held.
191 */ 191 */
192static __always_inline unsigned long __dat_user_addr(unsigned long uaddr, 192static inline unsigned long __dat_user_addr(unsigned long uaddr, int write)
193 int write)
194{ 193{
195 struct mm_struct *mm = current->mm; 194 struct mm_struct *mm = current->mm;
196 unsigned long kaddr; 195 unsigned long kaddr;
@@ -211,29 +210,29 @@ fault:
211 return 0; 210 return 0;
212} 211}
213 212
214static size_t copy_from_user_pt(size_t n, const void __user *from, void *to) 213unsigned long copy_from_user_pt(void *to, const void __user *from, unsigned long n)
215{ 214{
216 size_t rc; 215 unsigned long rc;
217 216
218 if (segment_eq(get_fs(), KERNEL_DS)) 217 if (segment_eq(get_fs(), KERNEL_DS))
219 return copy_in_kernel(n, (void __user *) to, from); 218 return copy_in_kernel((void __user *) to, from, n);
220 rc = __user_copy_pt((unsigned long) from, to, n, 0); 219 rc = __user_copy_pt((unsigned long) from, to, n, 0);
221 if (unlikely(rc)) 220 if (unlikely(rc))
222 memset(to + n - rc, 0, rc); 221 memset(to + n - rc, 0, rc);
223 return rc; 222 return rc;
224} 223}
225 224
226static size_t copy_to_user_pt(size_t n, void __user *to, const void *from) 225unsigned long copy_to_user_pt(void __user *to, const void *from, unsigned long n)
227{ 226{
228 if (segment_eq(get_fs(), KERNEL_DS)) 227 if (segment_eq(get_fs(), KERNEL_DS))
229 return copy_in_kernel(n, to, (void __user *) from); 228 return copy_in_kernel(to, (void __user *) from, n);
230 return __user_copy_pt((unsigned long) to, (void *) from, n, 1); 229 return __user_copy_pt((unsigned long) to, (void *) from, n, 1);
231} 230}
232 231
233static size_t clear_user_pt(size_t n, void __user *to) 232unsigned long clear_user_pt(void __user *to, unsigned long n)
234{ 233{
235 void *zpage = (void *) empty_zero_page; 234 void *zpage = (void *) empty_zero_page;
236 long done, size, ret; 235 unsigned long done, size, ret;
237 236
238 done = 0; 237 done = 0;
239 do { 238 do {
@@ -242,7 +241,7 @@ static size_t clear_user_pt(size_t n, void __user *to)
242 else 241 else
243 size = n - done; 242 size = n - done;
244 if (segment_eq(get_fs(), KERNEL_DS)) 243 if (segment_eq(get_fs(), KERNEL_DS))
245 ret = copy_in_kernel(n, to, (void __user *) zpage); 244 ret = copy_in_kernel(to, (void __user *) zpage, n);
246 else 245 else
247 ret = __user_copy_pt((unsigned long) to, zpage, size, 1); 246 ret = __user_copy_pt((unsigned long) to, zpage, size, 1);
248 done += size; 247 done += size;
@@ -253,17 +252,17 @@ static size_t clear_user_pt(size_t n, void __user *to)
253 return 0; 252 return 0;
254} 253}
255 254
256static size_t strnlen_user_pt(size_t count, const char __user *src) 255unsigned long strnlen_user_pt(const char __user *src, unsigned long count)
257{ 256{
258 unsigned long uaddr = (unsigned long) src; 257 unsigned long uaddr = (unsigned long) src;
259 struct mm_struct *mm = current->mm; 258 struct mm_struct *mm = current->mm;
260 unsigned long offset, done, len, kaddr; 259 unsigned long offset, done, len, kaddr;
261 size_t len_str; 260 unsigned long len_str;
262 261
263 if (unlikely(!count)) 262 if (unlikely(!count))
264 return 0; 263 return 0;
265 if (segment_eq(get_fs(), KERNEL_DS)) 264 if (segment_eq(get_fs(), KERNEL_DS))
266 return strnlen_kernel(count, src); 265 return strnlen_kernel(src, count);
267 if (!mm) 266 if (!mm)
268 return 0; 267 return 0;
269 done = 0; 268 done = 0;
@@ -289,19 +288,18 @@ fault:
289 goto retry; 288 goto retry;
290} 289}
291 290
292static size_t strncpy_from_user_pt(size_t count, const char __user *src, 291long strncpy_from_user_pt(char *dst, const char __user *src, long count)
293 char *dst)
294{ 292{
295 size_t done, len, offset, len_str; 293 unsigned long done, len, offset, len_str;
296 294
297 if (unlikely(!count)) 295 if (unlikely(count <= 0))
298 return 0; 296 return 0;
299 done = 0; 297 done = 0;
300 do { 298 do {
301 offset = (size_t)src & ~PAGE_MASK; 299 offset = (unsigned long)src & ~PAGE_MASK;
302 len = min(count - done, PAGE_SIZE - offset); 300 len = min(count - done, PAGE_SIZE - offset);
303 if (segment_eq(get_fs(), KERNEL_DS)) { 301 if (segment_eq(get_fs(), KERNEL_DS)) {
304 if (copy_in_kernel(len, (void __user *) dst, src)) 302 if (copy_in_kernel((void __user *) dst, src, len))
305 return -EFAULT; 303 return -EFAULT;
306 } else { 304 } else {
307 if (__user_copy_pt((unsigned long) src, dst, len, 0)) 305 if (__user_copy_pt((unsigned long) src, dst, len, 0))
@@ -315,8 +313,8 @@ static size_t strncpy_from_user_pt(size_t count, const char __user *src,
315 return done; 313 return done;
316} 314}
317 315
318static size_t copy_in_user_pt(size_t n, void __user *to, 316unsigned long copy_in_user_pt(void __user *to, const void __user *from,
319 const void __user *from) 317 unsigned long n)
320{ 318{
321 struct mm_struct *mm = current->mm; 319 struct mm_struct *mm = current->mm;
322 unsigned long offset_max, uaddr, done, size, error_code; 320 unsigned long offset_max, uaddr, done, size, error_code;
@@ -326,7 +324,7 @@ static size_t copy_in_user_pt(size_t n, void __user *to,
326 int write_user; 324 int write_user;
327 325
328 if (segment_eq(get_fs(), KERNEL_DS)) 326 if (segment_eq(get_fs(), KERNEL_DS))
329 return copy_in_kernel(n, to, from); 327 return copy_in_kernel(to, from, n);
330 if (!mm) 328 if (!mm)
331 return n; 329 return n;
332 done = 0; 330 done = 0;
@@ -411,7 +409,7 @@ static int __futex_atomic_op_pt(int op, u32 __user *uaddr, int oparg, int *old)
411 return ret; 409 return ret;
412} 410}
413 411
414int futex_atomic_op_pt(int op, u32 __user *uaddr, int oparg, int *old) 412int __futex_atomic_op_inuser(int op, u32 __user *uaddr, int oparg, int *old)
415{ 413{
416 int ret; 414 int ret;
417 415
@@ -449,8 +447,8 @@ static int __futex_atomic_cmpxchg_pt(u32 *uval, u32 __user *uaddr,
449 return ret; 447 return ret;
450} 448}
451 449
452int futex_atomic_cmpxchg_pt(u32 *uval, u32 __user *uaddr, 450int futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
453 u32 oldval, u32 newval) 451 u32 oldval, u32 newval)
454{ 452{
455 int ret; 453 int ret;
456 454
@@ -471,14 +469,3 @@ int futex_atomic_cmpxchg_pt(u32 *uval, u32 __user *uaddr,
471 put_page(virt_to_page(uaddr)); 469 put_page(virt_to_page(uaddr));
472 return ret; 470 return ret;
473} 471}
474
475struct uaccess_ops uaccess_pt = {
476 .copy_from_user = copy_from_user_pt,
477 .copy_to_user = copy_to_user_pt,
478 .copy_in_user = copy_in_user_pt,
479 .clear_user = clear_user_pt,
480 .strnlen_user = strnlen_user_pt,
481 .strncpy_from_user = strncpy_from_user_pt,
482 .futex_atomic_op = futex_atomic_op_pt,
483 .futex_atomic_cmpxchg = futex_atomic_cmpxchg_pt,
484};