1185f3d38SThomas Gleixner /* 2185f3d38SThomas Gleixner * User address space access functions. 3185f3d38SThomas Gleixner * 4185f3d38SThomas Gleixner * Copyright 1997 Andi Kleen <ak@muc.de> 5185f3d38SThomas Gleixner * Copyright 1997 Linus Torvalds 6185f3d38SThomas Gleixner * Copyright 2002 Andi Kleen <ak@suse.de> 7185f3d38SThomas Gleixner */ 8185f3d38SThomas Gleixner #include <linux/module.h> 9185f3d38SThomas Gleixner #include <asm/uaccess.h> 10185f3d38SThomas Gleixner 11185f3d38SThomas Gleixner /* 12185f3d38SThomas Gleixner * Zero Userspace 13185f3d38SThomas Gleixner */ 14185f3d38SThomas Gleixner 15185f3d38SThomas Gleixner unsigned long __clear_user(void __user *addr, unsigned long size) 16185f3d38SThomas Gleixner { 17185f3d38SThomas Gleixner long __d0; 183ee1afa3SNick Piggin might_fault(); 19185f3d38SThomas Gleixner /* no memory constraint because it doesn't change any memory gcc knows 20185f3d38SThomas Gleixner about */ 21*63bcff2aSH. Peter Anvin stac(); 22185f3d38SThomas Gleixner asm volatile( 23185f3d38SThomas Gleixner " testq %[size8],%[size8]\n" 24185f3d38SThomas Gleixner " jz 4f\n" 25185f3d38SThomas Gleixner "0: movq %[zero],(%[dst])\n" 26185f3d38SThomas Gleixner " addq %[eight],%[dst]\n" 27185f3d38SThomas Gleixner " decl %%ecx ; jnz 0b\n" 28185f3d38SThomas Gleixner "4: movq %[size1],%%rcx\n" 29185f3d38SThomas Gleixner " testl %%ecx,%%ecx\n" 30185f3d38SThomas Gleixner " jz 2f\n" 31185f3d38SThomas Gleixner "1: movb %b[zero],(%[dst])\n" 32185f3d38SThomas Gleixner " incq %[dst]\n" 33185f3d38SThomas Gleixner " decl %%ecx ; jnz 1b\n" 34185f3d38SThomas Gleixner "2:\n" 35185f3d38SThomas Gleixner ".section .fixup,\"ax\"\n" 36185f3d38SThomas Gleixner "3: lea 0(%[size1],%[size8],8),%[size8]\n" 37185f3d38SThomas Gleixner " jmp 2b\n" 38185f3d38SThomas Gleixner ".previous\n" 398da804f2SH. Peter Anvin _ASM_EXTABLE(0b,3b) 408da804f2SH. Peter Anvin _ASM_EXTABLE(1b,2b) 41e0a96129SAndi Kleen : [size8] "=&c"(size), [dst] "=&D" (__d0) 42185f3d38SThomas Gleixner : [size1] "r"(size & 7), "[size8]" (size / 8), "[dst]"(addr), 43185f3d38SThomas Gleixner [zero] "r" (0UL), [eight] "r" (8UL)); 44*63bcff2aSH. Peter Anvin clac(); 45185f3d38SThomas Gleixner return size; 46185f3d38SThomas Gleixner } 47185f3d38SThomas Gleixner EXPORT_SYMBOL(__clear_user); 48185f3d38SThomas Gleixner 49185f3d38SThomas Gleixner unsigned long clear_user(void __user *to, unsigned long n) 50185f3d38SThomas Gleixner { 51185f3d38SThomas Gleixner if (access_ok(VERIFY_WRITE, to, n)) 52185f3d38SThomas Gleixner return __clear_user(to, n); 53185f3d38SThomas Gleixner return n; 54185f3d38SThomas Gleixner } 55185f3d38SThomas Gleixner EXPORT_SYMBOL(clear_user); 56185f3d38SThomas Gleixner 57185f3d38SThomas Gleixner unsigned long copy_in_user(void __user *to, const void __user *from, unsigned len) 58185f3d38SThomas Gleixner { 59185f3d38SThomas Gleixner if (access_ok(VERIFY_WRITE, to, len) && access_ok(VERIFY_READ, from, len)) { 60185f3d38SThomas Gleixner return copy_user_generic((__force void *)to, (__force void *)from, len); 61185f3d38SThomas Gleixner } 62185f3d38SThomas Gleixner return len; 63185f3d38SThomas Gleixner } 64185f3d38SThomas Gleixner EXPORT_SYMBOL(copy_in_user); 65185f3d38SThomas Gleixner 661129585aSVitaly Mayatskikh /* 671129585aSVitaly Mayatskikh * Try to copy last bytes and clear the rest if needed. 681129585aSVitaly Mayatskikh * Since protection fault in copy_from/to_user is not a normal situation, 691129585aSVitaly Mayatskikh * it is not necessary to optimize tail handling. 701129585aSVitaly Mayatskikh */ 711129585aSVitaly Mayatskikh unsigned long 721129585aSVitaly Mayatskikh copy_user_handle_tail(char *to, char *from, unsigned len, unsigned zerorest) 731129585aSVitaly Mayatskikh { 741129585aSVitaly Mayatskikh char c; 751129585aSVitaly Mayatskikh unsigned zero_len; 761129585aSVitaly Mayatskikh 771129585aSVitaly Mayatskikh for (; len; --len) { 781129585aSVitaly Mayatskikh if (__get_user_nocheck(c, from++, sizeof(char))) 791129585aSVitaly Mayatskikh break; 801129585aSVitaly Mayatskikh if (__put_user_nocheck(c, to++, sizeof(char))) 811129585aSVitaly Mayatskikh break; 821129585aSVitaly Mayatskikh } 831129585aSVitaly Mayatskikh 841129585aSVitaly Mayatskikh for (c = 0, zero_len = len; zerorest && zero_len; --zero_len) 851129585aSVitaly Mayatskikh if (__put_user_nocheck(c, to++, sizeof(char))) 861129585aSVitaly Mayatskikh break; 87*63bcff2aSH. Peter Anvin clac(); 881129585aSVitaly Mayatskikh return len; 891129585aSVitaly Mayatskikh } 90