debuggers.hg
changeset 3725:7db5b671b347
bitkeeper revision 1.1159.212.106 (42068c6bV88PUeuTyW0W65OVudMAlQ)
Added user-memory accessing functionality for x86_64.
Signed-off-by: keir.fraser@cl.cam.ac.uk
Added user-memory accessing functionality for x86_64.
Signed-off-by: keir.fraser@cl.cam.ac.uk
author | kaf24@viper.(none) |
---|---|
date | Sun Feb 06 21:30:19 2005 +0000 (2005-02-06) |
parents | 253e8e10e986 |
children | 88957a238191 177865f3143e b8cbcd601e0e |
files | xen/arch/x86/boot/x86_64.S xen/arch/x86/x86_32/usercopy.c xen/arch/x86/x86_64/usercopy.c xen/common/dom_mem_ops.c xen/include/asm-x86/x86_32/uaccess.h xen/include/asm-x86/x86_64/uaccess.h |
line diff
1.1 --- a/xen/arch/x86/boot/x86_64.S Sun Feb 06 18:49:34 2005 +0000 1.2 +++ b/xen/arch/x86/boot/x86_64.S Sun Feb 06 21:30:19 2005 +0000 1.3 @@ -248,12 +248,3 @@ ENTRY(cpu0_stack) # Initial stack is 1.4 .org 0x6000 1.5 ENTRY(stext) 1.6 ENTRY(_stext) 1.7 - 1.8 -.globl copy_from_user, copy_to_user, copy_user_generic 1.9 -copy_from_user: 1.10 -copy_to_user: 1.11 -copy_user_generic: 1.12 -.globl __get_user_1, __get_user_4, __get_user_8 1.13 -__get_user_1: 1.14 -__get_user_4: 1.15 -__get_user_8:
2.1 --- a/xen/arch/x86/x86_32/usercopy.c Sun Feb 06 18:49:34 2005 +0000 2.2 +++ b/xen/arch/x86/x86_32/usercopy.c Sun Feb 06 21:30:19 2005 +0000 2.3 @@ -9,8 +9,6 @@ 2.4 #include <xen/mm.h> 2.5 #include <asm/uaccess.h> 2.6 2.7 -#define might_sleep() ((void)0) 2.8 - 2.9 static inline int __movsl_is_ok(unsigned long a1, unsigned long a2, unsigned long n) 2.10 { 2.11 #ifdef CONFIG_X86_INTEL_USERCOPY 2.12 @@ -22,93 +20,6 @@ static inline int __movsl_is_ok(unsigned 2.13 #define movsl_is_ok(a1,a2,n) \ 2.14 __movsl_is_ok((unsigned long)(a1),(unsigned long)(a2),(n)) 2.15 2.16 -/* 2.17 - * Copy a null terminated string from userspace. 2.18 - */ 2.19 - 2.20 -#define __do_strncpy_from_user(dst,src,count,res) \ 2.21 -do { \ 2.22 - int __d0, __d1, __d2; \ 2.23 - __asm__ __volatile__( \ 2.24 - " testl %1,%1\n" \ 2.25 - " jz 2f\n" \ 2.26 - "0: lodsb\n" \ 2.27 - " stosb\n" \ 2.28 - " testb %%al,%%al\n" \ 2.29 - " jz 1f\n" \ 2.30 - " decl %1\n" \ 2.31 - " jnz 0b\n" \ 2.32 - "1: subl %1,%0\n" \ 2.33 - "2:\n" \ 2.34 - ".section .fixup,\"ax\"\n" \ 2.35 - "3: movl %5,%0\n" \ 2.36 - " jmp 2b\n" \ 2.37 - ".previous\n" \ 2.38 - ".section __ex_table,\"a\"\n" \ 2.39 - " .align 4\n" \ 2.40 - " .long 0b,3b\n" \ 2.41 - ".previous" \ 2.42 - : "=d"(res), "=c"(count), "=&a" (__d0), "=&S" (__d1), \ 2.43 - "=&D" (__d2) \ 2.44 - : "i"(-EFAULT), "0"(count), "1"(count), "3"(src), "4"(dst) \ 2.45 - : "memory"); \ 2.46 -} while (0) 2.47 - 2.48 -/** 2.49 - * __strncpy_from_user: - Copy a NUL terminated string from userspace, with less checking. 2.50 - * @dst: Destination address, in kernel space. This buffer must be at 2.51 - * least @count bytes long. 2.52 - * @src: Source address, in user space. 2.53 - * @count: Maximum number of bytes to copy, including the trailing NUL. 2.54 - * 2.55 - * Copies a NUL-terminated string from userspace to kernel space. 2.56 - * Caller must check the specified block with access_ok() before calling 2.57 - * this function. 2.58 - * 2.59 - * On success, returns the length of the string (not including the trailing 2.60 - * NUL). 2.61 - * 2.62 - * If access to userspace fails, returns -EFAULT (some data may have been 2.63 - * copied). 2.64 - * 2.65 - * If @count is smaller than the length of the string, copies @count bytes 2.66 - * and returns @count. 2.67 - */ 2.68 -long 2.69 -__strncpy_from_user(char *dst, const char __user *src, long count) 2.70 -{ 2.71 - long res; 2.72 - __do_strncpy_from_user(dst, src, count, res); 2.73 - return res; 2.74 -} 2.75 - 2.76 -/** 2.77 - * strncpy_from_user: - Copy a NUL terminated string from userspace. 2.78 - * @dst: Destination address, in kernel space. This buffer must be at 2.79 - * least @count bytes long. 2.80 - * @src: Source address, in user space. 2.81 - * @count: Maximum number of bytes to copy, including the trailing NUL. 2.82 - * 2.83 - * Copies a NUL-terminated string from userspace to kernel space. 2.84 - * 2.85 - * On success, returns the length of the string (not including the trailing 2.86 - * NUL). 2.87 - * 2.88 - * If access to userspace fails, returns -EFAULT (some data may have been 2.89 - * copied). 2.90 - * 2.91 - * If @count is smaller than the length of the string, copies @count bytes 2.92 - * and returns @count. 2.93 - */ 2.94 -long 2.95 -strncpy_from_user(char *dst, const char __user *src, long count) 2.96 -{ 2.97 - long res = -EFAULT; 2.98 - if (access_ok(VERIFY_READ, src, 1)) 2.99 - __do_strncpy_from_user(dst, src, count, res); 2.100 - return res; 2.101 -} 2.102 - 2.103 2.104 /* 2.105 * Zero Userspace 2.106 @@ -148,7 +59,6 @@ do { \ 2.107 unsigned long 2.108 clear_user(void __user *to, unsigned long n) 2.109 { 2.110 - might_sleep(); 2.111 if (access_ok(VERIFY_WRITE, to, n)) 2.112 __do_clear_user(to, n); 2.113 return n; 2.114 @@ -172,49 +82,6 @@ unsigned long 2.115 return n; 2.116 } 2.117 2.118 -/** 2.119 - * strlen_user: - Get the size of a string in user space. 2.120 - * @s: The string to measure. 2.121 - * @n: The maximum valid length 2.122 - * 2.123 - * Get the size of a NUL-terminated string in user space. 2.124 - * 2.125 - * Returns the size of the string INCLUDING the terminating NUL. 2.126 - * On exception, returns 0. 2.127 - * If the string is too long, returns a value greater than @n. 2.128 - */ 2.129 -long strnlen_user(const char __user *s, long n) 2.130 -{ 2.131 - unsigned long mask = -__addr_ok(s); 2.132 - unsigned long res, tmp; 2.133 - 2.134 - might_sleep(); 2.135 - 2.136 - __asm__ __volatile__( 2.137 - " testl %0, %0\n" 2.138 - " jz 3f\n" 2.139 - " andl %0,%%ecx\n" 2.140 - "0: repne; scasb\n" 2.141 - " setne %%al\n" 2.142 - " subl %%ecx,%0\n" 2.143 - " addl %0,%%eax\n" 2.144 - "1:\n" 2.145 - ".section .fixup,\"ax\"\n" 2.146 - "2: xorl %%eax,%%eax\n" 2.147 - " jmp 1b\n" 2.148 - "3: movb $1,%%al\n" 2.149 - " jmp 1b\n" 2.150 - ".previous\n" 2.151 - ".section __ex_table,\"a\"\n" 2.152 - " .align 4\n" 2.153 - " .long 0b,2b\n" 2.154 - ".previous" 2.155 - :"=r" (n), "=D" (s), "=a" (res), "=c" (tmp) 2.156 - :"0" (n), "1" (s), "2" (0), "3" (mask) 2.157 - :"cc"); 2.158 - return res & mask; 2.159 -} 2.160 - 2.161 #ifdef CONFIG_X86_INTEL_USERCOPY 2.162 static unsigned long 2.163 __copy_user_intel(void __user *to, const void *from, unsigned long size) 2.164 @@ -543,12 +410,10 @@ unsigned long 2.165 unsigned long 2.166 copy_to_user(void __user *to, const void *from, unsigned long n) 2.167 { 2.168 - might_sleep(); 2.169 if (access_ok(VERIFY_WRITE, to, n)) 2.170 n = __copy_to_user(to, from, n); 2.171 return n; 2.172 } 2.173 -EXPORT_SYMBOL(copy_to_user); 2.174 2.175 /** 2.176 * copy_from_user: - Copy a block of data from user space. 2.177 @@ -569,11 +434,9 @@ EXPORT_SYMBOL(copy_to_user); 2.178 unsigned long 2.179 copy_from_user(void *to, const void __user *from, unsigned long n) 2.180 { 2.181 - might_sleep(); 2.182 if (access_ok(VERIFY_READ, from, n)) 2.183 n = __copy_from_user(to, from, n); 2.184 else 2.185 memset(to, 0, n); 2.186 return n; 2.187 } 2.188 -EXPORT_SYMBOL(copy_from_user);
3.1 --- a/xen/arch/x86/x86_64/usercopy.c Sun Feb 06 18:49:34 2005 +0000 3.2 +++ b/xen/arch/x86/x86_64/usercopy.c Sun Feb 06 21:30:19 2005 +0000 3.3 @@ -8,55 +8,6 @@ 3.4 #include <asm/uaccess.h> 3.5 3.6 /* 3.7 - * Copy a null terminated string from userspace. 3.8 - */ 3.9 - 3.10 -#define __do_strncpy_from_user(dst,src,count,res) \ 3.11 -do { \ 3.12 - long __d0, __d1, __d2; \ 3.13 - __asm__ __volatile__( \ 3.14 - " testq %1,%1\n" \ 3.15 - " jz 2f\n" \ 3.16 - "0: lodsb\n" \ 3.17 - " stosb\n" \ 3.18 - " testb %%al,%%al\n" \ 3.19 - " jz 1f\n" \ 3.20 - " decq %1\n" \ 3.21 - " jnz 0b\n" \ 3.22 - "1: subq %1,%0\n" \ 3.23 - "2:\n" \ 3.24 - ".section .fixup,\"ax\"\n" \ 3.25 - "3: movq %5,%0\n" \ 3.26 - " jmp 2b\n" \ 3.27 - ".previous\n" \ 3.28 - ".section __ex_table,\"a\"\n" \ 3.29 - " .align 8\n" \ 3.30 - " .quad 0b,3b\n" \ 3.31 - ".previous" \ 3.32 - : "=r"(res), "=c"(count), "=&a" (__d0), "=&S" (__d1), \ 3.33 - "=&D" (__d2) \ 3.34 - : "i"(-EFAULT), "0"(count), "1"(count), "3"(src), "4"(dst) \ 3.35 - : "memory"); \ 3.36 -} while (0) 3.37 - 3.38 -long 3.39 -__strncpy_from_user(char *dst, const char *src, long count) 3.40 -{ 3.41 - long res; 3.42 - __do_strncpy_from_user(dst, src, count, res); 3.43 - return res; 3.44 -} 3.45 - 3.46 -long 3.47 -strncpy_from_user(char *dst, const char *src, long count) 3.48 -{ 3.49 - long res = -EFAULT; 3.50 - if (access_ok(VERIFY_READ, src, 1)) 3.51 - __do_strncpy_from_user(dst, src, count, res); 3.52 - return res; 3.53 -} 3.54 - 3.55 -/* 3.56 * Zero Userspace 3.57 */ 3.58 3.59 @@ -93,6 +44,86 @@ unsigned long __clear_user(void *addr, u 3.60 return size; 3.61 } 3.62 3.63 +unsigned long __copy_to_user_ll(void __user *to, const void *from, unsigned n) 3.64 +{ 3.65 + unsigned long __d0, __d1, __d2, __n = n; 3.66 + __asm__ __volatile__( 3.67 + " cmpq $15,%0\n" 3.68 + " jbe 1f\n" 3.69 + " mov %1,%0\n" 3.70 + " neg %0\n" 3.71 + " and $7,%0\n" 3.72 + " sub %0,%3\n" 3.73 + "4: rep; movsb\n" /* make 'to' address aligned */ 3.74 + " mov %3,%0\n" 3.75 + " shr $3,%0\n" 3.76 + " and $7,%3\n" 3.77 + " .align 2,0x90\n" 3.78 + "0: rep; movsq\n" /* as many quadwords as possible... */ 3.79 + " mov %3,%0\n" 3.80 + "1: rep; movsb\n" /* ...remainder copied as bytes */ 3.81 + "2:\n" 3.82 + ".section .fixup,\"ax\"\n" 3.83 + "5: add %3,%0\n" 3.84 + " jmp 2b\n" 3.85 + "3: lea 0(%3,%0,8),%0\n" 3.86 + " jmp 2b\n" 3.87 + ".previous\n" 3.88 + ".section __ex_table,\"a\"\n" 3.89 + " .align 8\n" 3.90 + " .quad 4b,5b\n" 3.91 + " .quad 0b,3b\n" 3.92 + " .quad 1b,2b\n" 3.93 + ".previous" 3.94 + : "=&c"(__n), "=&D" (__d0), "=&S" (__d1), "=r"(__d2) 3.95 + : "3"(__n), "0"(__n), "1"(to), "2"(from) 3.96 + : "memory"); 3.97 + return (unsigned)__n; 3.98 +} 3.99 + 3.100 +unsigned long 3.101 +__copy_from_user_ll(void *to, const void __user *from, unsigned n) 3.102 +{ 3.103 + unsigned long __d0, __d1, __d2, __n = n; 3.104 + __asm__ __volatile__( 3.105 + " cmp $15,%0\n" 3.106 + " jbe 1f\n" 3.107 + " mov %1,%0\n" 3.108 + " neg %0\n" 3.109 + " and $7,%0\n" 3.110 + " sub %0,%3\n" 3.111 + "4: rep; movsb\n" /* make 'to' address aligned */ 3.112 + " mov %3,%0\n" 3.113 + " shr $3,%0\n" 3.114 + " and $7,%3\n" 3.115 + " .align 2,0x90\n" 3.116 + "0: rep; movsq\n" /* as many quadwords as possible... */ 3.117 + " mov %3,%0\n" 3.118 + "1: rep; movsb\n" /* ...remainder copied as bytes */ 3.119 + "2:\n" 3.120 + ".section .fixup,\"ax\"\n" 3.121 + "5: add %3,%0\n" 3.122 + " jmp 6f\n" 3.123 + "3: lea 0(%3,%0,8),%0\n" 3.124 + "6: push %0\n" 3.125 + " push %%rax\n" 3.126 + " xor %%rax,%%rax\n" 3.127 + " rep; stosb\n" 3.128 + " pop %%rax\n" 3.129 + " pop %0\n" 3.130 + " jmp 2b\n" 3.131 + ".previous\n" 3.132 + ".section __ex_table,\"a\"\n" 3.133 + " .align 8\n" 3.134 + " .quad 4b,5b\n" 3.135 + " .quad 0b,3b\n" 3.136 + " .quad 1b,6b\n" 3.137 + ".previous" 3.138 + : "=&c"(__n), "=&D" (__d0), "=&S" (__d1), "=r"(__d2) 3.139 + : "3"(__n), "0"(__n), "1"(to), "2"(from) 3.140 + : "memory"); 3.141 + return (unsigned)__n; 3.142 +} 3.143 3.144 unsigned long clear_user(void *to, unsigned long n) 3.145 { 3.146 @@ -101,36 +132,49 @@ unsigned long clear_user(void *to, unsig 3.147 return n; 3.148 } 3.149 3.150 -/* 3.151 - * Return the size of a string (including the ending 0) 3.152 +/** 3.153 + * copy_to_user: - Copy a block of data into user space. 3.154 + * @to: Destination address, in user space. 3.155 + * @from: Source address, in kernel space. 3.156 + * @n: Number of bytes to copy. 3.157 + * 3.158 + * Context: User context only. This function may sleep. 3.159 * 3.160 - * Return 0 on exception, a value greater than N if too long 3.161 + * Copy data from kernel space to user space. 3.162 + * 3.163 + * Returns number of bytes that could not be copied. 3.164 + * On success, this will be zero. 3.165 */ 3.166 - 3.167 -long strnlen_user(const char *s, long n) 3.168 +unsigned long 3.169 +copy_to_user(void __user *to, const void *from, unsigned n) 3.170 { 3.171 - unsigned long res = 0; 3.172 - char c; 3.173 - 3.174 - if (!access_ok(VERIFY_READ, s, n)) 3.175 - return 0; 3.176 - 3.177 - while (1) { 3.178 - if (get_user(c, s)) 3.179 - return 0; 3.180 - if (!c) 3.181 - return res+1; 3.182 - if (res>n) 3.183 - return n+1; 3.184 - res++; 3.185 - s++; 3.186 - } 3.187 + if (access_ok(VERIFY_WRITE, to, n)) 3.188 + n = __copy_to_user(to, from, n); 3.189 + return n; 3.190 } 3.191 3.192 -unsigned long copy_in_user(void *to, const void *from, unsigned len) 3.193 +/** 3.194 + * copy_from_user: - Copy a block of data from user space. 3.195 + * @to: Destination address, in kernel space. 3.196 + * @from: Source address, in user space. 3.197 + * @n: Number of bytes to copy. 3.198 + * 3.199 + * Context: User context only. This function may sleep. 3.200 + * 3.201 + * Copy data from user space to kernel space. 3.202 + * 3.203 + * Returns number of bytes that could not be copied. 3.204 + * On success, this will be zero. 3.205 + * 3.206 + * If some data could not be copied, this function will pad the copied 3.207 + * data to the requested size using zero bytes. 3.208 + */ 3.209 +unsigned long 3.210 +copy_from_user(void *to, const void __user *from, unsigned n) 3.211 { 3.212 - if (access_ok(VERIFY_WRITE, to, len) && access_ok(VERIFY_READ, from, len)) { 3.213 - return copy_user_generic(to, from, len); 3.214 - } 3.215 - return len; 3.216 + if (access_ok(VERIFY_READ, from, n)) 3.217 + n = __copy_from_user(to, from, n); 3.218 + else 3.219 + memset(to, 0, n); 3.220 + return n; 3.221 }
4.1 --- a/xen/common/dom_mem_ops.c Sun Feb 06 18:49:34 2005 +0000 4.2 +++ b/xen/common/dom_mem_ops.c Sun Feb 06 21:30:19 2005 +0000 4.3 @@ -35,7 +35,7 @@ static long 4.4 alloc_dom_mem(struct domain *d, 4.5 unsigned long *extent_list, 4.6 unsigned long start_extent, 4.7 - unsigned long nr_extents, 4.8 + unsigned int nr_extents, 4.9 unsigned int extent_order) 4.10 { 4.11 struct pfn_info *page; 4.12 @@ -73,7 +73,7 @@ static long 4.13 free_dom_mem(struct domain *d, 4.14 unsigned long *extent_list, 4.15 unsigned long start_extent, 4.16 - unsigned long nr_extents, 4.17 + unsigned int nr_extents, 4.18 unsigned int extent_order) 4.19 { 4.20 struct pfn_info *page; 4.21 @@ -134,7 +134,7 @@ do_dom_mem_op(unsigned long op, 4.22 op &= (1 << START_EXTENT_SHIFT) - 1; 4.23 4.24 if ( unlikely(start_extent > nr_extents) || 4.25 - unlikely(nr_extents > (~0UL >> START_EXTENT_SHIFT)) ) 4.26 + unlikely(nr_extents > ~0U) ) /* can pack into a uint? */ 4.27 return -EINVAL; 4.28 4.29 if ( likely(domid == DOMID_SELF) ) 4.30 @@ -150,11 +150,13 @@ do_dom_mem_op(unsigned long op, 4.31 { 4.32 case MEMOP_increase_reservation: 4.33 rc = alloc_dom_mem( 4.34 - d, extent_list, start_extent, nr_extents, extent_order); 4.35 + d, extent_list, start_extent, 4.36 + (unsigned int)nr_extents, extent_order); 4.37 break; 4.38 case MEMOP_decrease_reservation: 4.39 rc = free_dom_mem( 4.40 - d, extent_list, start_extent, nr_extents, extent_order); 4.41 + d, extent_list, start_extent, 4.42 + (unsigned int)nr_extents, extent_order); 4.43 break; 4.44 default: 4.45 rc = -ENOSYS;
5.1 --- a/xen/include/asm-x86/x86_32/uaccess.h Sun Feb 06 18:49:34 2005 +0000 5.2 +++ b/xen/include/asm-x86/x86_32/uaccess.h Sun Feb 06 21:30:19 2005 +0000 5.3 @@ -10,9 +10,7 @@ 5.4 #include <xen/string.h> 5.5 #include <xen/sched.h> 5.6 5.7 -/* No user-pointer checking. */ 5.8 #define __user 5.9 -#define __chk_user_ptr(_p) ((void)0) 5.10 5.11 #define VERIFY_READ 0 5.12 #define VERIFY_WRITE 1 5.13 @@ -22,7 +20,7 @@ 5.14 */ 5.15 #ifdef CONFIG_X86_INTEL_USERCOPY 5.16 extern struct movsl_mask { 5.17 - int mask; 5.18 + int mask; 5.19 } __cacheline_aligned movsl_mask; 5.20 #endif 5.21 5.22 @@ -34,41 +32,22 @@ extern struct movsl_mask { 5.23 * 5.24 * This is equivalent to the following test: 5.25 * (u33)addr + (u33)size >= (u33)HYPERVISOR_VIRT_START 5.26 - * 5.27 - * This needs 33-bit arithmetic. We have a carry... 5.28 */ 5.29 -#define __range_ok(addr,size) ({ \ 5.30 +#define __range_not_ok(addr,size) ({ \ 5.31 unsigned long flag,sum; \ 5.32 - __chk_user_ptr(addr); \ 5.33 asm("addl %3,%1 ; sbbl %0,%0; cmpl %1,%4; sbbl $0,%0" \ 5.34 :"=&r" (flag), "=r" (sum) \ 5.35 :"1" (addr),"g" ((int)(size)),"r" (HYPERVISOR_VIRT_START)); \ 5.36 flag; }) 5.37 5.38 -/** 5.39 - * access_ok: - Checks if a user space pointer is valid 5.40 - * @type: Type of access: %VERIFY_READ or %VERIFY_WRITE. Note that 5.41 - * %VERIFY_WRITE is a superset of %VERIFY_READ - if it is safe 5.42 - * to write to a block, it is always safe to read from it. 5.43 - * @addr: User space pointer to start of block to check 5.44 - * @size: Size of block to check 5.45 - * 5.46 - * Context: User context only. This function may sleep. 5.47 - * 5.48 - * Checks if a pointer to a block of memory in user space is valid. 5.49 - * 5.50 - * Returns true (nonzero) if the memory block may be valid, false (zero) 5.51 - * if it is definitely invalid. 5.52 - * 5.53 - * Note that, depending on architecture, this function probably just 5.54 - * checks that the pointer is in the user space range - after calling 5.55 - * this function, memory access functions may still return -EFAULT. 5.56 - */ 5.57 -#define access_ok(type,addr,size) (likely(__range_ok(addr,size) == 0)) 5.58 +#define access_ok(type,addr,size) (likely(__range_not_ok(addr,size) == 0)) 5.59 5.60 #define array_access_ok(type,addr,count,size) \ 5.61 (likely(count < (~0UL/size)) && access_ok(type,addr,count*size)) 5.62 5.63 +extern long __get_user_bad(void); 5.64 +extern void __put_user_bad(void); 5.65 + 5.66 /** 5.67 * get_user: - Get a simple variable from user space. 5.68 * @x: Variable to store result. 5.69 @@ -89,8 +68,6 @@ extern struct movsl_mask { 5.70 #define get_user(x,ptr) \ 5.71 __get_user_check((x),(ptr),sizeof(*(ptr))) 5.72 5.73 -extern void __put_user_bad(void); 5.74 - 5.75 /** 5.76 * put_user: - Write a simple value into user space. 5.77 * @x: Value to copy to user space. 5.78 @@ -195,7 +172,6 @@ extern void __put_user_bad(void); 5.79 #define __put_user_size(x,ptr,size,retval,errret) \ 5.80 do { \ 5.81 retval = 0; \ 5.82 - __chk_user_ptr(ptr); \ 5.83 switch (size) { \ 5.84 case 1: __put_user_asm(x,ptr,retval,"b","b","iq",errret);break; \ 5.85 case 2: __put_user_asm(x,ptr,retval,"w","w","ir",errret);break; \ 5.86 @@ -259,12 +235,9 @@ struct __large_struct { unsigned long bu 5.87 __gu_err; \ 5.88 }) 5.89 5.90 -extern long __get_user_bad(void); 5.91 - 5.92 #define __get_user_size(x,ptr,size,retval,errret) \ 5.93 do { \ 5.94 retval = 0; \ 5.95 - __chk_user_ptr(ptr); \ 5.96 switch (size) { \ 5.97 case 1: __get_user_asm(x,ptr,retval,"b","b","=q",errret);break; \ 5.98 case 2: __get_user_asm(x,ptr,retval,"w","w","=r",errret);break; \ 5.99 @@ -317,22 +290,22 @@ unsigned long __copy_from_user_ll(void * 5.100 static always_inline unsigned long 5.101 __copy_to_user(void __user *to, const void *from, unsigned long n) 5.102 { 5.103 - if (__builtin_constant_p(n)) { 5.104 - unsigned long ret; 5.105 + if (__builtin_constant_p(n)) { 5.106 + unsigned long ret; 5.107 5.108 - switch (n) { 5.109 - case 1: 5.110 - __put_user_size(*(u8 *)from, (u8 __user *)to, 1, ret, 1); 5.111 - return ret; 5.112 - case 2: 5.113 - __put_user_size(*(u16 *)from, (u16 __user *)to, 2, ret, 2); 5.114 - return ret; 5.115 - case 4: 5.116 - __put_user_size(*(u32 *)from, (u32 __user *)to, 4, ret, 4); 5.117 - return ret; 5.118 - } 5.119 - } 5.120 - return __copy_to_user_ll(to, from, n); 5.121 + switch (n) { 5.122 + case 1: 5.123 + __put_user_size(*(u8 *)from, (u8 __user *)to, 1, ret, 1); 5.124 + return ret; 5.125 + case 2: 5.126 + __put_user_size(*(u16 *)from, (u16 __user *)to, 2, ret, 2); 5.127 + return ret; 5.128 + case 4: 5.129 + __put_user_size(*(u32 *)from, (u32 __user *)to, 4, ret, 4); 5.130 + return ret; 5.131 + } 5.132 + } 5.133 + return __copy_to_user_ll(to, from, n); 5.134 } 5.135 5.136 /** 5.137 @@ -355,47 +328,28 @@ static always_inline unsigned long 5.138 static always_inline unsigned long 5.139 __copy_from_user(void *to, const void __user *from, unsigned long n) 5.140 { 5.141 - if (__builtin_constant_p(n)) { 5.142 - unsigned long ret; 5.143 + if (__builtin_constant_p(n)) { 5.144 + unsigned long ret; 5.145 5.146 - switch (n) { 5.147 - case 1: 5.148 - __get_user_size(*(u8 *)to, from, 1, ret, 1); 5.149 - return ret; 5.150 - case 2: 5.151 - __get_user_size(*(u16 *)to, from, 2, ret, 2); 5.152 - return ret; 5.153 - case 4: 5.154 - __get_user_size(*(u32 *)to, from, 4, ret, 4); 5.155 - return ret; 5.156 - } 5.157 - } 5.158 - return __copy_from_user_ll(to, from, n); 5.159 + switch (n) { 5.160 + case 1: 5.161 + __get_user_size(*(u8 *)to, from, 1, ret, 1); 5.162 + return ret; 5.163 + case 2: 5.164 + __get_user_size(*(u16 *)to, from, 2, ret, 2); 5.165 + return ret; 5.166 + case 4: 5.167 + __get_user_size(*(u32 *)to, from, 4, ret, 4); 5.168 + return ret; 5.169 + } 5.170 + } 5.171 + return __copy_from_user_ll(to, from, n); 5.172 } 5.173 5.174 unsigned long copy_to_user(void __user *to, const void *from, unsigned long n); 5.175 unsigned long copy_from_user(void *to, 5.176 - const void __user *from, unsigned long n); 5.177 -long strncpy_from_user(char *dst, const char __user *src, long count); 5.178 -long __strncpy_from_user(char *dst, const char __user *src, long count); 5.179 + const void __user *from, unsigned long n); 5.180 5.181 -/** 5.182 - * strlen_user: - Get the size of a string in user space. 5.183 - * @str: The string to measure. 5.184 - * 5.185 - * Context: User context only. This function may sleep. 5.186 - * 5.187 - * Get the size of a NUL-terminated string in user space. 5.188 - * 5.189 - * Returns the size of the string INCLUDING the terminating NUL. 5.190 - * On exception, returns 0. 5.191 - * 5.192 - * If there is a limit on the length of a valid string, you may wish to 5.193 - * consider using strnlen_user() instead. 5.194 - */ 5.195 -#define strlen_user(str) strnlen_user(str, ~0UL >> 1) 5.196 - 5.197 -long strnlen_user(const char __user *str, long n); 5.198 unsigned long clear_user(void __user *mem, unsigned long len); 5.199 unsigned long __clear_user(void __user *mem, unsigned long len); 5.200
6.1 --- a/xen/include/asm-x86/x86_64/uaccess.h Sun Feb 06 18:49:34 2005 +0000 6.2 +++ b/xen/include/asm-x86/x86_64/uaccess.h Sun Feb 06 21:30:19 2005 +0000 6.3 @@ -11,10 +11,7 @@ 6.4 #include <xen/prefetch.h> 6.5 #include <asm/page.h> 6.6 6.7 -/* No user-pointer checking. */ 6.8 #define __user 6.9 -#define __force 6.10 -#define __chk_user_ptr(_p) ((void)0) 6.11 6.12 #define VERIFY_READ 0 6.13 #define VERIFY_WRITE 1 6.14 @@ -22,122 +19,149 @@ 6.15 #define __addr_ok(addr) ((unsigned long)(addr) < HYPERVISOR_VIRT_START) 6.16 6.17 /* 6.18 - * Uhhuh, this needs 65-bit arithmetic. We have a carry.. 6.19 + * Test whether a block of memory is a valid user space address. 6.20 + * Returns 0 if the range is valid, nonzero otherwise. 6.21 + * 6.22 + * This is equivalent to the following test: 6.23 + * ((u65)addr >= (u65)HYPERVISOR_VIRT_END) ? 6.24 + * (((u65)addr + (u65)size) >= ((u65)1 << 64)) : 6.25 + * (((u65)addr + (u65)size) >= ((u65)HYPERVISOR_VIRT_START)) 6.26 */ 6.27 #define __range_not_ok(addr,size) ({ \ 6.28 - unsigned long flag,sum; \ 6.29 - __chk_user_ptr(addr); \ 6.30 - asm("# range_ok\n\r" \ 6.31 - "addq %3,%1 ; sbbq %0,%0 ; cmpq %1,%4 ; sbbq $0,%0" \ 6.32 - :"=&r" (flag), "=r" (sum) \ 6.33 - :"1" (addr),"g" ((long)(size)),"r" (HYPERVISOR_VIRT_START)); \ 6.34 - flag; }) 6.35 + unsigned long flag,sum; \ 6.36 + if ((unsigned long)addr >= HYPERVISOR_VIRT_END) \ 6.37 + asm("addq %3,%1 ; sbbq %0,%0" \ 6.38 + :"=&r" (flag), "=r" (sum) \ 6.39 + :"1" (addr),"g" ((long)(size))); \ 6.40 + else \ 6.41 + asm("addq %3,%1 ; sbbq %0,%0 ; cmpq %1,%4 ; sbbq $0,%0" \ 6.42 + :"=&r" (flag), "=r" (sum) \ 6.43 + :"1" (addr),"g" ((long)(size)),"r" (HYPERVISOR_VIRT_START)); \ 6.44 + flag; }) 6.45 6.46 #define access_ok(type, addr, size) (__range_not_ok(addr,size) == 0) 6.47 6.48 #define array_access_ok(type,addr,count,size) \ 6.49 (likely(sizeof(count) <= 4) /* disallow 64-bit counts */ && \ 6.50 - access_ok(type,addr,count*size)) 6.51 - 6.52 -extern inline int verify_area(int type, const void __user * addr, unsigned long size) 6.53 -{ 6.54 - return access_ok(type,addr,size) ? 0 : -EFAULT; 6.55 -} 6.56 - 6.57 -/* 6.58 - * These are the main single-value transfer routines. They automatically 6.59 - * use the right size if we just have the right pointer type. 6.60 - * 6.61 - * This gets kind of ugly. We want to return _two_ values in "get_user()" 6.62 - * and yet we don't want to do any pointers, because that is too much 6.63 - * of a performance impact. Thus we have a few rather ugly macros here, 6.64 - * and hide all the ugliness from the user. 6.65 - * 6.66 - * The "__xxx" versions of the user access functions are versions that 6.67 - * do not verify the address space, that must have been done previously 6.68 - * with a separate "access_ok()" call (this is used when we do multiple 6.69 - * accesses to the same area of user memory). 6.70 - */ 6.71 - 6.72 -extern void __get_user_1(void); 6.73 -extern void __get_user_2(void); 6.74 -extern void __get_user_4(void); 6.75 -extern void __get_user_8(void); 6.76 + access_ok(type,addr,(unsigned long)count*(unsigned long)size)) 6.77 6.78 -#define __get_user_x(size,ret,x,ptr) \ 6.79 - __asm__ __volatile__("call __get_user_" #size \ 6.80 - :"=a" (ret),"=d" (x) \ 6.81 - :"0" (ptr) \ 6.82 - :"rbx") 6.83 - 6.84 -/* Careful: we have to cast the result to the type of the pointer for sign reasons */ 6.85 -#define get_user(x,ptr) \ 6.86 -({ long __val_gu; \ 6.87 - int __ret_gu; \ 6.88 - __chk_user_ptr(ptr); \ 6.89 - switch(sizeof (*(ptr))) { \ 6.90 - case 1: __get_user_x(1,__ret_gu,__val_gu,ptr); break; \ 6.91 - case 2: __get_user_x(2,__ret_gu,__val_gu,ptr); break; \ 6.92 - case 4: __get_user_x(4,__ret_gu,__val_gu,ptr); break; \ 6.93 - case 8: __get_user_x(8,__ret_gu,__val_gu,ptr); break; \ 6.94 - default: __get_user_bad(); break; \ 6.95 - } \ 6.96 - (x) = (__typeof__(*(ptr)))__val_gu; \ 6.97 - __ret_gu; \ 6.98 -}) 6.99 - 6.100 -extern void __put_user_1(void); 6.101 -extern void __put_user_2(void); 6.102 -extern void __put_user_4(void); 6.103 -extern void __put_user_8(void); 6.104 - 6.105 +extern long __get_user_bad(void); 6.106 extern void __put_user_bad(void); 6.107 6.108 -#define __put_user_x(size,ret,x,ptr) \ 6.109 - __asm__ __volatile__("call __put_user_" #size \ 6.110 - :"=a" (ret) \ 6.111 - :"0" (ptr),"d" (x) \ 6.112 - :"rbx") 6.113 +/** 6.114 + * get_user: - Get a simple variable from user space. 6.115 + * @x: Variable to store result. 6.116 + * @ptr: Source address, in user space. 6.117 + * 6.118 + * Context: User context only. This function may sleep. 6.119 + * 6.120 + * This macro copies a single simple variable from user space to kernel 6.121 + * space. It supports simple types like char and int, but not larger 6.122 + * data types like structures or arrays. 6.123 + * 6.124 + * @ptr must have pointer-to-simple-variable type, and the result of 6.125 + * dereferencing @ptr must be assignable to @x without a cast. 6.126 + * 6.127 + * Returns zero on success, or -EFAULT on error. 6.128 + * On error, the variable @x is set to zero. 6.129 + */ 6.130 +#define get_user(x,ptr) \ 6.131 + __get_user_check((x),(ptr),sizeof(*(ptr))) 6.132 6.133 +/** 6.134 + * put_user: - Write a simple value into user space. 6.135 + * @x: Value to copy to user space. 6.136 + * @ptr: Destination address, in user space. 6.137 + * 6.138 + * Context: User context only. This function may sleep. 6.139 + * 6.140 + * This macro copies a single simple value from kernel space to user 6.141 + * space. It supports simple types like char and int, but not larger 6.142 + * data types like structures or arrays. 6.143 + * 6.144 + * @ptr must have pointer-to-simple-variable type, and @x must be assignable 6.145 + * to the result of dereferencing @ptr. 6.146 + * 6.147 + * Returns zero on success, or -EFAULT on error. 6.148 + */ 6.149 #define put_user(x,ptr) \ 6.150 __put_user_check((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr))) 6.151 6.152 + 6.153 +/** 6.154 + * __get_user: - Get a simple variable from user space, with less checking. 6.155 + * @x: Variable to store result. 6.156 + * @ptr: Source address, in user space. 6.157 + * 6.158 + * Context: User context only. This function may sleep. 6.159 + * 6.160 + * This macro copies a single simple variable from user space to kernel 6.161 + * space. It supports simple types like char and int, but not larger 6.162 + * data types like structures or arrays. 6.163 + * 6.164 + * @ptr must have pointer-to-simple-variable type, and the result of 6.165 + * dereferencing @ptr must be assignable to @x without a cast. 6.166 + * 6.167 + * Caller must check the pointer with access_ok() before calling this 6.168 + * function. 6.169 + * 6.170 + * Returns zero on success, or -EFAULT on error. 6.171 + * On error, the variable @x is set to zero. 6.172 + */ 6.173 #define __get_user(x,ptr) \ 6.174 __get_user_nocheck((x),(ptr),sizeof(*(ptr))) 6.175 + 6.176 + 6.177 +/** 6.178 + * __put_user: - Write a simple value into user space, with less checking. 6.179 + * @x: Value to copy to user space. 6.180 + * @ptr: Destination address, in user space. 6.181 + * 6.182 + * Context: User context only. This function may sleep. 6.183 + * 6.184 + * This macro copies a single simple value from kernel space to user 6.185 + * space. It supports simple types like char and int, but not larger 6.186 + * data types like structures or arrays. 6.187 + * 6.188 + * @ptr must have pointer-to-simple-variable type, and @x must be assignable 6.189 + * to the result of dereferencing @ptr. 6.190 + * 6.191 + * Caller must check the pointer with access_ok() before calling this 6.192 + * function. 6.193 + * 6.194 + * Returns zero on success, or -EFAULT on error. 6.195 + */ 6.196 #define __put_user(x,ptr) \ 6.197 __put_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr))) 6.198 6.199 -#define __put_user_nocheck(x,ptr,size) \ 6.200 -({ \ 6.201 - int __pu_err; \ 6.202 - __put_user_size((x),(ptr),(size),__pu_err); \ 6.203 - __pu_err; \ 6.204 +#define __put_user_nocheck(x,ptr,size) \ 6.205 +({ \ 6.206 + long __pu_err; \ 6.207 + __put_user_size((x),(ptr),(size),__pu_err,-EFAULT); \ 6.208 + __pu_err; \ 6.209 }) 6.210 6.211 +#define __put_user_check(x,ptr,size) \ 6.212 +({ \ 6.213 + long __pu_err = -EFAULT; \ 6.214 + __typeof__(*(ptr)) __user *__pu_addr = (ptr); \ 6.215 + if (__addr_ok(__pu_addr)) \ 6.216 + __put_user_size((x),__pu_addr,(size),__pu_err,-EFAULT); \ 6.217 + __pu_err; \ 6.218 +}) 6.219 6.220 -#define __put_user_check(x,ptr,size) \ 6.221 -({ \ 6.222 - int __pu_err = -EFAULT; \ 6.223 - __typeof__(*(ptr)) __user *__pu_addr = (ptr); \ 6.224 - if (likely(access_ok(VERIFY_WRITE,__pu_addr,size))) \ 6.225 - __put_user_size((x),__pu_addr,(size),__pu_err); \ 6.226 - __pu_err; \ 6.227 -}) 6.228 - 6.229 -#define __put_user_size(x,ptr,size,retval) \ 6.230 +#define __put_user_size(x,ptr,size,retval,errret) \ 6.231 do { \ 6.232 retval = 0; \ 6.233 - __chk_user_ptr(ptr); \ 6.234 switch (size) { \ 6.235 - case 1: __put_user_asm(x,ptr,retval,"b","b","iq",-EFAULT); break;\ 6.236 - case 2: __put_user_asm(x,ptr,retval,"w","w","ir",-EFAULT); break;\ 6.237 - case 4: __put_user_asm(x,ptr,retval,"l","k","ir",-EFAULT); break;\ 6.238 - case 8: __put_user_asm(x,ptr,retval,"q","","ir",-EFAULT); break;\ 6.239 - default: __put_user_bad(); \ 6.240 + case 1: __put_user_asm(x,ptr,retval,"b","b","iq",errret);break; \ 6.241 + case 2: __put_user_asm(x,ptr,retval,"w","w","ir",errret);break; \ 6.242 + case 4: __put_user_asm(x,ptr,retval,"l","k","ir",errret);break; \ 6.243 + case 8: __put_user_asm(x,ptr,retval,"q","","ir",errret);break; \ 6.244 + default: __put_user_bad(); \ 6.245 } \ 6.246 } while (0) 6.247 6.248 -/* FIXME: this hack is definitely wrong -AK */ 6.249 struct __large_struct { unsigned long buf[100]; }; 6.250 #define __m(x) (*(struct __large_struct *)(x)) 6.251 6.252 @@ -146,178 +170,139 @@ struct __large_struct { unsigned long bu 6.253 * we do not write to any memory gcc knows about, so there are no 6.254 * aliasing issues. 6.255 */ 6.256 -#define __put_user_asm(x, addr, err, itype, rtype, ltype, errno) \ 6.257 - __asm__ __volatile__( \ 6.258 - "1: mov"itype" %"rtype"1,%2\n" \ 6.259 - "2:\n" \ 6.260 - ".section .fixup,\"ax\"\n" \ 6.261 - "3: mov %3,%0\n" \ 6.262 - " jmp 2b\n" \ 6.263 - ".previous\n" \ 6.264 - ".section __ex_table,\"a\"\n" \ 6.265 - " .align 8\n" \ 6.266 - " .quad 1b,3b\n" \ 6.267 - ".previous" \ 6.268 - : "=r"(err) \ 6.269 - : ltype (x), "m"(__m(addr)), "i"(errno), "0"(err)) 6.270 - 6.271 +#define __put_user_asm(x, addr, err, itype, rtype, ltype, errret) \ 6.272 + __asm__ __volatile__( \ 6.273 + "1: mov"itype" %"rtype"1,%2\n" \ 6.274 + "2:\n" \ 6.275 + ".section .fixup,\"ax\"\n" \ 6.276 + "3: mov %3,%0\n" \ 6.277 + " jmp 2b\n" \ 6.278 + ".previous\n" \ 6.279 + ".section __ex_table,\"a\"\n" \ 6.280 + " .align 8\n" \ 6.281 + " .quad 1b,3b\n" \ 6.282 + ".previous" \ 6.283 + : "=r"(err) \ 6.284 + : ltype (x), "m"(__m(addr)), "i"(errret), "0"(err)) 6.285 6.286 #define __get_user_nocheck(x,ptr,size) \ 6.287 ({ \ 6.288 - int __gu_err; \ 6.289 - long __gu_val; \ 6.290 - __get_user_size(__gu_val,(ptr),(size),__gu_err); \ 6.291 + long __gu_err, __gu_val; \ 6.292 + __get_user_size(__gu_val,(ptr),(size),__gu_err,-EFAULT);\ 6.293 (x) = (__typeof__(*(ptr)))__gu_val; \ 6.294 __gu_err; \ 6.295 }) 6.296 6.297 -extern int __get_user_bad(void); 6.298 +#define __get_user_check(x,ptr,size) \ 6.299 +({ \ 6.300 + long __gu_err, __gu_val; \ 6.301 + __typeof__(*(ptr)) __user *__gu_addr = (ptr); \ 6.302 + __get_user_size(__gu_val,__gu_addr,(size),__gu_err,-EFAULT); \ 6.303 + (x) = (__typeof__(*(ptr)))__gu_val; \ 6.304 + if (!__addr_ok(__gu_addr)) __gu_err = -EFAULT; \ 6.305 + __gu_err; \ 6.306 +}) 6.307 6.308 -#define __get_user_size(x,ptr,size,retval) \ 6.309 +#define __get_user_size(x,ptr,size,retval,errret) \ 6.310 do { \ 6.311 retval = 0; \ 6.312 - __chk_user_ptr(ptr); \ 6.313 switch (size) { \ 6.314 - case 1: __get_user_asm(x,ptr,retval,"b","b","=q",-EFAULT); break;\ 6.315 - case 2: __get_user_asm(x,ptr,retval,"w","w","=r",-EFAULT); break;\ 6.316 - case 4: __get_user_asm(x,ptr,retval,"l","k","=r",-EFAULT); break;\ 6.317 - case 8: __get_user_asm(x,ptr,retval,"q","","=r",-EFAULT); break;\ 6.318 - default: (x) = __get_user_bad(); \ 6.319 + case 1: __get_user_asm(x,ptr,retval,"b","b","=q",errret);break; \ 6.320 + case 2: __get_user_asm(x,ptr,retval,"w","w","=r",errret);break; \ 6.321 + case 4: __get_user_asm(x,ptr,retval,"l","k","=r",errret);break; \ 6.322 + case 8: __get_user_asm(x,ptr,retval,"q","","=r",errret); break; \ 6.323 + default: (x) = __get_user_bad(); \ 6.324 } \ 6.325 } while (0) 6.326 6.327 -#define __get_user_asm(x, addr, err, itype, rtype, ltype, errno) \ 6.328 - __asm__ __volatile__( \ 6.329 - "1: mov"itype" %2,%"rtype"1\n" \ 6.330 - "2:\n" \ 6.331 - ".section .fixup,\"ax\"\n" \ 6.332 - "3: mov %3,%0\n" \ 6.333 - " xor"itype" %"rtype"1,%"rtype"1\n" \ 6.334 - " jmp 2b\n" \ 6.335 - ".previous\n" \ 6.336 - ".section __ex_table,\"a\"\n" \ 6.337 - " .align 8\n" \ 6.338 - " .quad 1b,3b\n" \ 6.339 - ".previous" \ 6.340 - : "=r"(err), ltype (x) \ 6.341 - : "m"(__m(addr)), "i"(errno), "0"(err)) 6.342 +#define __get_user_asm(x, addr, err, itype, rtype, ltype, errret) \ 6.343 + __asm__ __volatile__( \ 6.344 + "1: mov"itype" %2,%"rtype"1\n" \ 6.345 + "2:\n" \ 6.346 + ".section .fixup,\"ax\"\n" \ 6.347 + "3: mov %3,%0\n" \ 6.348 + " xor"itype" %"rtype"1,%"rtype"1\n" \ 6.349 + " jmp 2b\n" \ 6.350 + ".previous\n" \ 6.351 + ".section __ex_table,\"a\"\n" \ 6.352 + " .align 8\n" \ 6.353 + " .quad 1b,3b\n" \ 6.354 + ".previous" \ 6.355 + : "=r"(err), ltype (x) \ 6.356 + : "m"(__m(addr)), "i"(errret), "0"(err)) 6.357 + 6.358 6.359 /* 6.360 * Copy To/From Userspace 6.361 */ 6.362 6.363 /* Handles exceptions in both to and from, but doesn't do access_ok */ 6.364 -extern unsigned long copy_user_generic(void *to, const void *from, unsigned len); 6.365 +unsigned long __copy_to_user_ll(void __user *to, const void *from, unsigned n); 6.366 +unsigned long __copy_from_user_ll(void *to, const void __user *from, unsigned n); 6.367 6.368 -extern unsigned long copy_to_user(void __user *to, const void *from, unsigned len); 6.369 -extern unsigned long copy_from_user(void *to, const void __user *from, unsigned len); 6.370 -extern unsigned long copy_in_user(void __user *to, const void __user *from, unsigned len); 6.371 +unsigned long copy_to_user(void __user *to, const void *from, unsigned len); 6.372 +unsigned long copy_from_user(void *to, const void __user *from, unsigned len); 6.373 6.374 static always_inline int __copy_from_user(void *dst, const void __user *src, unsigned size) 6.375 { 6.376 - int ret = 0; 6.377 - if (!__builtin_constant_p(size)) 6.378 - return copy_user_generic(dst,(__force void *)src,size); 6.379 - switch (size) { 6.380 - case 1:__get_user_asm(*(u8*)dst,(u8 __user *)src,ret,"b","b","=q",1); 6.381 - return ret; 6.382 - case 2:__get_user_asm(*(u16*)dst,(u16 __user *)src,ret,"w","w","=r",2); 6.383 - return ret; 6.384 - case 4:__get_user_asm(*(u32*)dst,(u32 __user *)src,ret,"l","k","=r",4); 6.385 - return ret; 6.386 - case 8:__get_user_asm(*(u64*)dst,(u64 __user *)src,ret,"q","","=r",8); 6.387 - return ret; 6.388 - case 10: 6.389 - __get_user_asm(*(u64*)dst,(u64 __user *)src,ret,"q","","=r",16); 6.390 - if (unlikely(ret)) return ret; 6.391 - __get_user_asm(*(u16*)(8+(char*)dst),(u16 __user *)(8+(char __user *)src),ret,"w","w","=r",2); 6.392 - return ret; 6.393 - case 16: 6.394 - __get_user_asm(*(u64*)dst,(u64 __user *)src,ret,"q","","=r",16); 6.395 - if (unlikely(ret)) return ret; 6.396 - __get_user_asm(*(u64*)(8+(char*)dst),(u64 __user *)(8+(char __user *)src),ret,"q","","=r",8); 6.397 - return ret; 6.398 - default: 6.399 - return copy_user_generic(dst,(__force void *)src,size); 6.400 - } 6.401 + int ret = 0; 6.402 + if (!__builtin_constant_p(size)) 6.403 + return __copy_from_user_ll(dst,(void *)src,size); 6.404 + switch (size) { 6.405 + case 1:__get_user_asm(*(u8*)dst,(u8 __user *)src,ret,"b","b","=q",1); 6.406 + return ret; 6.407 + case 2:__get_user_asm(*(u16*)dst,(u16 __user *)src,ret,"w","w","=r",2); 6.408 + return ret; 6.409 + case 4:__get_user_asm(*(u32*)dst,(u32 __user *)src,ret,"l","k","=r",4); 6.410 + return ret; 6.411 + case 8:__get_user_asm(*(u64*)dst,(u64 __user *)src,ret,"q","","=r",8); 6.412 + return ret; 6.413 + case 10: 6.414 + __get_user_asm(*(u64*)dst,(u64 __user *)src,ret,"q","","=r",16); 6.415 + if (unlikely(ret)) return ret; 6.416 + __get_user_asm(*(u16*)(8+(char*)dst),(u16 __user *)(8+(char __user *)src),ret,"w","w","=r",2); 6.417 + return ret; 6.418 + case 16: 6.419 + __get_user_asm(*(u64*)dst,(u64 __user *)src,ret,"q","","=r",16); 6.420 + if (unlikely(ret)) return ret; 6.421 + __get_user_asm(*(u64*)(8+(char*)dst),(u64 __user *)(8+(char __user *)src),ret,"q","","=r",8); 6.422 + return ret; 6.423 + default: 6.424 + return __copy_from_user_ll(dst,(void *)src,size); 6.425 + } 6.426 } 6.427 6.428 static always_inline int __copy_to_user(void __user *dst, const void *src, unsigned size) 6.429 { 6.430 - int ret = 0; 6.431 - if (!__builtin_constant_p(size)) 6.432 - return copy_user_generic((__force void *)dst,src,size); 6.433 - switch (size) { 6.434 - case 1:__put_user_asm(*(u8*)src,(u8 __user *)dst,ret,"b","b","iq",1); 6.435 - return ret; 6.436 - case 2:__put_user_asm(*(u16*)src,(u16 __user *)dst,ret,"w","w","ir",2); 6.437 - return ret; 6.438 - case 4:__put_user_asm(*(u32*)src,(u32 __user *)dst,ret,"l","k","ir",4); 6.439 - return ret; 6.440 - case 8:__put_user_asm(*(u64*)src,(u64 __user *)dst,ret,"q","","ir",8); 6.441 - return ret; 6.442 - case 10: 6.443 - __put_user_asm(*(u64*)src,(u64 __user *)dst,ret,"q","","ir",10); 6.444 - if (unlikely(ret)) return ret; 6.445 - asm("":::"memory"); 6.446 - __put_user_asm(4[(u16*)src],4+(u16 __user *)dst,ret,"w","w","ir",2); 6.447 - return ret; 6.448 - case 16: 6.449 - __put_user_asm(*(u64*)src,(u64 __user *)dst,ret,"q","","ir",16); 6.450 - if (unlikely(ret)) return ret; 6.451 - asm("":::"memory"); 6.452 - __put_user_asm(1[(u64*)src],1+(u64 __user *)dst,ret,"q","","ir",8); 6.453 - return ret; 6.454 - default: 6.455 - return copy_user_generic((__force void *)dst,src,size); 6.456 - } 6.457 + int ret = 0; 6.458 + if (!__builtin_constant_p(size)) 6.459 + return __copy_to_user_ll((void *)dst,src,size); 6.460 + switch (size) { 6.461 + case 1:__put_user_asm(*(u8*)src,(u8 __user *)dst,ret,"b","b","iq",1); 6.462 + return ret; 6.463 + case 2:__put_user_asm(*(u16*)src,(u16 __user *)dst,ret,"w","w","ir",2); 6.464 + return ret; 6.465 + case 4:__put_user_asm(*(u32*)src,(u32 __user *)dst,ret,"l","k","ir",4); 6.466 + return ret; 6.467 + case 8:__put_user_asm(*(u64*)src,(u64 __user *)dst,ret,"q","","ir",8); 6.468 + return ret; 6.469 + case 10: 6.470 + __put_user_asm(*(u64*)src,(u64 __user *)dst,ret,"q","","ir",10); 6.471 + if (unlikely(ret)) return ret; 6.472 + asm("":::"memory"); 6.473 + __put_user_asm(4[(u16*)src],4+(u16 __user *)dst,ret,"w","w","ir",2); 6.474 + return ret; 6.475 + case 16: 6.476 + __put_user_asm(*(u64*)src,(u64 __user *)dst,ret,"q","","ir",16); 6.477 + if (unlikely(ret)) return ret; 6.478 + asm("":::"memory"); 6.479 + __put_user_asm(1[(u64*)src],1+(u64 __user *)dst,ret,"q","","ir",8); 6.480 + return ret; 6.481 + default: 6.482 + return __copy_to_user_ll((void *)dst,src,size); 6.483 + } 6.484 } 6.485 6.486 - 6.487 -static always_inline int __copy_in_user(void __user *dst, const void __user *src, unsigned size) 6.488 -{ 6.489 - int ret = 0; 6.490 - if (!__builtin_constant_p(size)) 6.491 - return copy_user_generic((__force void *)dst,(__force void *)src,size); 6.492 - switch (size) { 6.493 - case 1: { 6.494 - u8 tmp; 6.495 - __get_user_asm(tmp,(u8 __user *)src,ret,"b","b","=q",1); 6.496 - if (likely(!ret)) 6.497 - __put_user_asm(tmp,(u8 __user *)dst,ret,"b","b","iq",1); 6.498 - return ret; 6.499 - } 6.500 - case 2: { 6.501 - u16 tmp; 6.502 - __get_user_asm(tmp,(u16 __user *)src,ret,"w","w","=r",2); 6.503 - if (likely(!ret)) 6.504 - __put_user_asm(tmp,(u16 __user *)dst,ret,"w","w","ir",2); 6.505 - return ret; 6.506 - } 6.507 - 6.508 - case 4: { 6.509 - u32 tmp; 6.510 - __get_user_asm(tmp,(u32 __user *)src,ret,"l","k","=r",4); 6.511 - if (likely(!ret)) 6.512 - __put_user_asm(tmp,(u32 __user *)dst,ret,"l","k","ir",4); 6.513 - return ret; 6.514 - } 6.515 - case 8: { 6.516 - u64 tmp; 6.517 - __get_user_asm(tmp,(u64 __user *)src,ret,"q","","=r",8); 6.518 - if (likely(!ret)) 6.519 - __put_user_asm(tmp,(u64 __user *)dst,ret,"q","","ir",8); 6.520 - return ret; 6.521 - } 6.522 - default: 6.523 - return copy_user_generic((__force void *)dst,(__force void *)src,size); 6.524 - } 6.525 -} 6.526 - 6.527 -long strncpy_from_user(char *dst, const char __user *src, long count); 6.528 -long __strncpy_from_user(char *dst, const char __user *src, long count); 6.529 -long strnlen_user(const char __user *str, long n); 6.530 -long strlen_user(const char __user *str); 6.531 unsigned long clear_user(void __user *mem, unsigned long len); 6.532 unsigned long __clear_user(void __user *mem, unsigned long len); 6.533