debuggers.hg
annotate xen/arch/x86/x86_32/usercopy.c @ 3674:fb875591fd72
bitkeeper revision 1.1159.223.63 (42028527-fv-d9BM0_LRp8UKGP19gQ)
Fix NMI deferral.
Signed-off-by: keir.fraser@cl.cam.ac.uk
Fix NMI deferral.
Signed-off-by: keir.fraser@cl.cam.ac.uk
author | kaf24@scramble.cl.cam.ac.uk |
---|---|
date | Thu Feb 03 20:10:15 2005 +0000 (2005-02-03) |
parents | c326283ef029 |
children | 7db5b671b347 88957a238191 |
rev | line source |
---|---|
kaf24@1710 | 1 /* |
kaf24@1710 | 2 * User address space access functions. |
kaf24@1710 | 3 * The non inlined parts of asm-i386/uaccess.h are here. |
kaf24@1710 | 4 * |
kaf24@1710 | 5 * Copyright 1997 Andi Kleen <ak@muc.de> |
kaf24@1710 | 6 * Copyright 1997 Linus Torvalds |
kaf24@1710 | 7 */ |
kaf24@1710 | 8 #include <xen/config.h> |
kaf24@2375 | 9 #include <xen/mm.h> |
kaf24@1710 | 10 #include <asm/uaccess.h> |
kaf24@1710 | 11 |
kaf24@2375 | 12 #define might_sleep() ((void)0) |
kaf24@1710 | 13 |
kaf24@2375 | 14 static inline int __movsl_is_ok(unsigned long a1, unsigned long a2, unsigned long n) |
kaf24@1710 | 15 { |
kaf24@2375 | 16 #ifdef CONFIG_X86_INTEL_USERCOPY |
kaf24@2375 | 17 if (n >= 64 && ((a1 ^ a2) & movsl_mask.mask)) |
kaf24@2375 | 18 return 0; |
kaf24@2375 | 19 #endif |
kaf24@2375 | 20 return 1; |
kaf24@1710 | 21 } |
kaf24@2375 | 22 #define movsl_is_ok(a1,a2,n) \ |
kaf24@2375 | 23 __movsl_is_ok((unsigned long)(a1),(unsigned long)(a2),(n)) |
kaf24@1710 | 24 |
kaf24@1710 | 25 /* |
kaf24@1710 | 26 * Copy a null terminated string from userspace. |
kaf24@1710 | 27 */ |
kaf24@1710 | 28 |
kaf24@1710 | 29 #define __do_strncpy_from_user(dst,src,count,res) \ |
kaf24@1710 | 30 do { \ |
kaf24@1710 | 31 int __d0, __d1, __d2; \ |
kaf24@1710 | 32 __asm__ __volatile__( \ |
kaf24@1710 | 33 " testl %1,%1\n" \ |
kaf24@1710 | 34 " jz 2f\n" \ |
kaf24@1710 | 35 "0: lodsb\n" \ |
kaf24@1710 | 36 " stosb\n" \ |
kaf24@1710 | 37 " testb %%al,%%al\n" \ |
kaf24@1710 | 38 " jz 1f\n" \ |
kaf24@1710 | 39 " decl %1\n" \ |
kaf24@1710 | 40 " jnz 0b\n" \ |
kaf24@1710 | 41 "1: subl %1,%0\n" \ |
kaf24@1710 | 42 "2:\n" \ |
kaf24@1710 | 43 ".section .fixup,\"ax\"\n" \ |
kaf24@1710 | 44 "3: movl %5,%0\n" \ |
kaf24@1710 | 45 " jmp 2b\n" \ |
kaf24@1710 | 46 ".previous\n" \ |
kaf24@1710 | 47 ".section __ex_table,\"a\"\n" \ |
kaf24@1710 | 48 " .align 4\n" \ |
kaf24@1710 | 49 " .long 0b,3b\n" \ |
kaf24@1710 | 50 ".previous" \ |
kaf24@1710 | 51 : "=d"(res), "=c"(count), "=&a" (__d0), "=&S" (__d1), \ |
kaf24@1710 | 52 "=&D" (__d2) \ |
kaf24@1710 | 53 : "i"(-EFAULT), "0"(count), "1"(count), "3"(src), "4"(dst) \ |
kaf24@1710 | 54 : "memory"); \ |
kaf24@1710 | 55 } while (0) |
kaf24@1710 | 56 |
kaf24@2375 | 57 /** |
kaf24@2375 | 58 * __strncpy_from_user: - Copy a NUL terminated string from userspace, with less checking. |
kaf24@2375 | 59 * @dst: Destination address, in kernel space. This buffer must be at |
kaf24@2375 | 60 * least @count bytes long. |
kaf24@2375 | 61 * @src: Source address, in user space. |
kaf24@2375 | 62 * @count: Maximum number of bytes to copy, including the trailing NUL. |
kaf24@2375 | 63 * |
kaf24@2375 | 64 * Copies a NUL-terminated string from userspace to kernel space. |
kaf24@2375 | 65 * Caller must check the specified block with access_ok() before calling |
kaf24@2375 | 66 * this function. |
kaf24@2375 | 67 * |
kaf24@2375 | 68 * On success, returns the length of the string (not including the trailing |
kaf24@2375 | 69 * NUL). |
kaf24@2375 | 70 * |
kaf24@2375 | 71 * If access to userspace fails, returns -EFAULT (some data may have been |
kaf24@2375 | 72 * copied). |
kaf24@2375 | 73 * |
kaf24@2375 | 74 * If @count is smaller than the length of the string, copies @count bytes |
kaf24@2375 | 75 * and returns @count. |
kaf24@2375 | 76 */ |
kaf24@1710 | 77 long |
kaf24@2375 | 78 __strncpy_from_user(char *dst, const char __user *src, long count) |
kaf24@1710 | 79 { |
kaf24@1710 | 80 long res; |
kaf24@1710 | 81 __do_strncpy_from_user(dst, src, count, res); |
kaf24@1710 | 82 return res; |
kaf24@1710 | 83 } |
kaf24@1710 | 84 |
kaf24@2375 | 85 /** |
kaf24@2375 | 86 * strncpy_from_user: - Copy a NUL terminated string from userspace. |
kaf24@2375 | 87 * @dst: Destination address, in kernel space. This buffer must be at |
kaf24@2375 | 88 * least @count bytes long. |
kaf24@2375 | 89 * @src: Source address, in user space. |
kaf24@2375 | 90 * @count: Maximum number of bytes to copy, including the trailing NUL. |
kaf24@2375 | 91 * |
kaf24@2375 | 92 * Copies a NUL-terminated string from userspace to kernel space. |
kaf24@2375 | 93 * |
kaf24@2375 | 94 * On success, returns the length of the string (not including the trailing |
kaf24@2375 | 95 * NUL). |
kaf24@2375 | 96 * |
kaf24@2375 | 97 * If access to userspace fails, returns -EFAULT (some data may have been |
kaf24@2375 | 98 * copied). |
kaf24@2375 | 99 * |
kaf24@2375 | 100 * If @count is smaller than the length of the string, copies @count bytes |
kaf24@2375 | 101 * and returns @count. |
kaf24@2375 | 102 */ |
kaf24@1710 | 103 long |
kaf24@2375 | 104 strncpy_from_user(char *dst, const char __user *src, long count) |
kaf24@1710 | 105 { |
kaf24@1710 | 106 long res = -EFAULT; |
kaf24@1710 | 107 if (access_ok(VERIFY_READ, src, 1)) |
kaf24@1710 | 108 __do_strncpy_from_user(dst, src, count, res); |
kaf24@1710 | 109 return res; |
kaf24@1710 | 110 } |
kaf24@1710 | 111 |
kaf24@1710 | 112 |
kaf24@1710 | 113 /* |
kaf24@1710 | 114 * Zero Userspace |
kaf24@1710 | 115 */ |
kaf24@1710 | 116 |
kaf24@1710 | 117 #define __do_clear_user(addr,size) \ |
kaf24@1710 | 118 do { \ |
kaf24@1710 | 119 int __d0; \ |
kaf24@1710 | 120 __asm__ __volatile__( \ |
kaf24@1710 | 121 "0: rep; stosl\n" \ |
kaf24@1710 | 122 " movl %2,%0\n" \ |
kaf24@1710 | 123 "1: rep; stosb\n" \ |
kaf24@1710 | 124 "2:\n" \ |
kaf24@1710 | 125 ".section .fixup,\"ax\"\n" \ |
kaf24@1710 | 126 "3: lea 0(%2,%0,4),%0\n" \ |
kaf24@1710 | 127 " jmp 2b\n" \ |
kaf24@1710 | 128 ".previous\n" \ |
kaf24@1710 | 129 ".section __ex_table,\"a\"\n" \ |
kaf24@1710 | 130 " .align 4\n" \ |
kaf24@1710 | 131 " .long 0b,3b\n" \ |
kaf24@1710 | 132 " .long 1b,2b\n" \ |
kaf24@1710 | 133 ".previous" \ |
kaf24@1710 | 134 : "=&c"(size), "=&D" (__d0) \ |
kaf24@1710 | 135 : "r"(size & 3), "0"(size / 4), "1"(addr), "a"(0)); \ |
kaf24@1710 | 136 } while (0) |
kaf24@1710 | 137 |
kaf24@2375 | 138 /** |
kaf24@2375 | 139 * clear_user: - Zero a block of memory in user space. |
kaf24@2375 | 140 * @to: Destination address, in user space. |
kaf24@2375 | 141 * @n: Number of bytes to zero. |
kaf24@2375 | 142 * |
kaf24@2375 | 143 * Zero a block of memory in user space. |
kaf24@2375 | 144 * |
kaf24@2375 | 145 * Returns number of bytes that could not be cleared. |
kaf24@2375 | 146 * On success, this will be zero. |
kaf24@2375 | 147 */ |
kaf24@1710 | 148 unsigned long |
kaf24@2375 | 149 clear_user(void __user *to, unsigned long n) |
kaf24@1710 | 150 { |
kaf24@2375 | 151 might_sleep(); |
kaf24@1710 | 152 if (access_ok(VERIFY_WRITE, to, n)) |
kaf24@1710 | 153 __do_clear_user(to, n); |
kaf24@1710 | 154 return n; |
kaf24@1710 | 155 } |
kaf24@1710 | 156 |
kaf24@2375 | 157 /** |
kaf24@2375 | 158 * __clear_user: - Zero a block of memory in user space, with less checking. |
kaf24@2375 | 159 * @to: Destination address, in user space. |
kaf24@2375 | 160 * @n: Number of bytes to zero. |
kaf24@2375 | 161 * |
kaf24@2375 | 162 * Zero a block of memory in user space. Caller must check |
kaf24@2375 | 163 * the specified block with access_ok() before calling this function. |
kaf24@2375 | 164 * |
kaf24@2375 | 165 * Returns number of bytes that could not be cleared. |
kaf24@2375 | 166 * On success, this will be zero. |
kaf24@2375 | 167 */ |
kaf24@1710 | 168 unsigned long |
kaf24@2375 | 169 __clear_user(void __user *to, unsigned long n) |
kaf24@1710 | 170 { |
kaf24@1710 | 171 __do_clear_user(to, n); |
kaf24@1710 | 172 return n; |
kaf24@1710 | 173 } |
kaf24@1710 | 174 |
kaf24@2375 | 175 /** |
kaf24@2375 | 176 * strlen_user: - Get the size of a string in user space. |
kaf24@2375 | 177 * @s: The string to measure. |
kaf24@2375 | 178 * @n: The maximum valid length |
kaf24@1710 | 179 * |
kaf24@2375 | 180 * Get the size of a NUL-terminated string in user space. |
kaf24@2375 | 181 * |
kaf24@2375 | 182 * Returns the size of the string INCLUDING the terminating NUL. |
kaf24@2375 | 183 * On exception, returns 0. |
kaf24@2375 | 184 * If the string is too long, returns a value greater than @n. |
kaf24@1710 | 185 */ |
kaf24@2375 | 186 long strnlen_user(const char __user *s, long n) |
kaf24@1710 | 187 { |
kaf24@1710 | 188 unsigned long mask = -__addr_ok(s); |
kaf24@1710 | 189 unsigned long res, tmp; |
kaf24@1710 | 190 |
kaf24@2375 | 191 might_sleep(); |
kaf24@2375 | 192 |
kaf24@1710 | 193 __asm__ __volatile__( |
kaf24@1710 | 194 " testl %0, %0\n" |
kaf24@1710 | 195 " jz 3f\n" |
kaf24@1710 | 196 " andl %0,%%ecx\n" |
kaf24@1710 | 197 "0: repne; scasb\n" |
kaf24@1710 | 198 " setne %%al\n" |
kaf24@1710 | 199 " subl %%ecx,%0\n" |
kaf24@1710 | 200 " addl %0,%%eax\n" |
kaf24@1710 | 201 "1:\n" |
kaf24@1710 | 202 ".section .fixup,\"ax\"\n" |
kaf24@1710 | 203 "2: xorl %%eax,%%eax\n" |
kaf24@1710 | 204 " jmp 1b\n" |
kaf24@1710 | 205 "3: movb $1,%%al\n" |
kaf24@1710 | 206 " jmp 1b\n" |
kaf24@1710 | 207 ".previous\n" |
kaf24@1710 | 208 ".section __ex_table,\"a\"\n" |
kaf24@1710 | 209 " .align 4\n" |
kaf24@1710 | 210 " .long 0b,2b\n" |
kaf24@1710 | 211 ".previous" |
kaf24@1710 | 212 :"=r" (n), "=D" (s), "=a" (res), "=c" (tmp) |
kaf24@1710 | 213 :"0" (n), "1" (s), "2" (0), "3" (mask) |
kaf24@1710 | 214 :"cc"); |
kaf24@1710 | 215 return res & mask; |
kaf24@1710 | 216 } |
kaf24@2375 | 217 |
kaf24@2375 | 218 #ifdef CONFIG_X86_INTEL_USERCOPY |
kaf24@2375 | 219 static unsigned long |
kaf24@2375 | 220 __copy_user_intel(void __user *to, const void *from, unsigned long size) |
kaf24@2375 | 221 { |
kaf24@2375 | 222 int d0, d1; |
kaf24@2375 | 223 __asm__ __volatile__( |
kaf24@2375 | 224 " .align 2,0x90\n" |
kaf24@2375 | 225 "1: movl 32(%4), %%eax\n" |
kaf24@2375 | 226 " cmpl $67, %0\n" |
kaf24@2375 | 227 " jbe 3f\n" |
kaf24@2375 | 228 "2: movl 64(%4), %%eax\n" |
kaf24@2375 | 229 " .align 2,0x90\n" |
kaf24@2375 | 230 "3: movl 0(%4), %%eax\n" |
kaf24@2375 | 231 "4: movl 4(%4), %%edx\n" |
kaf24@2375 | 232 "5: movl %%eax, 0(%3)\n" |
kaf24@2375 | 233 "6: movl %%edx, 4(%3)\n" |
kaf24@2375 | 234 "7: movl 8(%4), %%eax\n" |
kaf24@2375 | 235 "8: movl 12(%4),%%edx\n" |
kaf24@2375 | 236 "9: movl %%eax, 8(%3)\n" |
kaf24@2375 | 237 "10: movl %%edx, 12(%3)\n" |
kaf24@2375 | 238 "11: movl 16(%4), %%eax\n" |
kaf24@2375 | 239 "12: movl 20(%4), %%edx\n" |
kaf24@2375 | 240 "13: movl %%eax, 16(%3)\n" |
kaf24@2375 | 241 "14: movl %%edx, 20(%3)\n" |
kaf24@2375 | 242 "15: movl 24(%4), %%eax\n" |
kaf24@2375 | 243 "16: movl 28(%4), %%edx\n" |
kaf24@2375 | 244 "17: movl %%eax, 24(%3)\n" |
kaf24@2375 | 245 "18: movl %%edx, 28(%3)\n" |
kaf24@2375 | 246 "19: movl 32(%4), %%eax\n" |
kaf24@2375 | 247 "20: movl 36(%4), %%edx\n" |
kaf24@2375 | 248 "21: movl %%eax, 32(%3)\n" |
kaf24@2375 | 249 "22: movl %%edx, 36(%3)\n" |
kaf24@2375 | 250 "23: movl 40(%4), %%eax\n" |
kaf24@2375 | 251 "24: movl 44(%4), %%edx\n" |
kaf24@2375 | 252 "25: movl %%eax, 40(%3)\n" |
kaf24@2375 | 253 "26: movl %%edx, 44(%3)\n" |
kaf24@2375 | 254 "27: movl 48(%4), %%eax\n" |
kaf24@2375 | 255 "28: movl 52(%4), %%edx\n" |
kaf24@2375 | 256 "29: movl %%eax, 48(%3)\n" |
kaf24@2375 | 257 "30: movl %%edx, 52(%3)\n" |
kaf24@2375 | 258 "31: movl 56(%4), %%eax\n" |
kaf24@2375 | 259 "32: movl 60(%4), %%edx\n" |
kaf24@2375 | 260 "33: movl %%eax, 56(%3)\n" |
kaf24@2375 | 261 "34: movl %%edx, 60(%3)\n" |
kaf24@2375 | 262 " addl $-64, %0\n" |
kaf24@2375 | 263 " addl $64, %4\n" |
kaf24@2375 | 264 " addl $64, %3\n" |
kaf24@2375 | 265 " cmpl $63, %0\n" |
kaf24@2375 | 266 " ja 1b\n" |
kaf24@2375 | 267 "35: movl %0, %%eax\n" |
kaf24@2375 | 268 " shrl $2, %0\n" |
kaf24@2375 | 269 " andl $3, %%eax\n" |
kaf24@2375 | 270 " cld\n" |
kaf24@2375 | 271 "99: rep; movsl\n" |
kaf24@2375 | 272 "36: movl %%eax, %0\n" |
kaf24@2375 | 273 "37: rep; movsb\n" |
kaf24@2375 | 274 "100:\n" |
kaf24@2375 | 275 ".section .fixup,\"ax\"\n" |
kaf24@2375 | 276 "101: lea 0(%%eax,%0,4),%0\n" |
kaf24@2375 | 277 " jmp 100b\n" |
kaf24@2375 | 278 ".previous\n" |
kaf24@2375 | 279 ".section __ex_table,\"a\"\n" |
kaf24@2375 | 280 " .align 4\n" |
kaf24@2375 | 281 " .long 1b,100b\n" |
kaf24@2375 | 282 " .long 2b,100b\n" |
kaf24@2375 | 283 " .long 3b,100b\n" |
kaf24@2375 | 284 " .long 4b,100b\n" |
kaf24@2375 | 285 " .long 5b,100b\n" |
kaf24@2375 | 286 " .long 6b,100b\n" |
kaf24@2375 | 287 " .long 7b,100b\n" |
kaf24@2375 | 288 " .long 8b,100b\n" |
kaf24@2375 | 289 " .long 9b,100b\n" |
kaf24@2375 | 290 " .long 10b,100b\n" |
kaf24@2375 | 291 " .long 11b,100b\n" |
kaf24@2375 | 292 " .long 12b,100b\n" |
kaf24@2375 | 293 " .long 13b,100b\n" |
kaf24@2375 | 294 " .long 14b,100b\n" |
kaf24@2375 | 295 " .long 15b,100b\n" |
kaf24@2375 | 296 " .long 16b,100b\n" |
kaf24@2375 | 297 " .long 17b,100b\n" |
kaf24@2375 | 298 " .long 18b,100b\n" |
kaf24@2375 | 299 " .long 19b,100b\n" |
kaf24@2375 | 300 " .long 20b,100b\n" |
kaf24@2375 | 301 " .long 21b,100b\n" |
kaf24@2375 | 302 " .long 22b,100b\n" |
kaf24@2375 | 303 " .long 23b,100b\n" |
kaf24@2375 | 304 " .long 24b,100b\n" |
kaf24@2375 | 305 " .long 25b,100b\n" |
kaf24@2375 | 306 " .long 26b,100b\n" |
kaf24@2375 | 307 " .long 27b,100b\n" |
kaf24@2375 | 308 " .long 28b,100b\n" |
kaf24@2375 | 309 " .long 29b,100b\n" |
kaf24@2375 | 310 " .long 30b,100b\n" |
kaf24@2375 | 311 " .long 31b,100b\n" |
kaf24@2375 | 312 " .long 32b,100b\n" |
kaf24@2375 | 313 " .long 33b,100b\n" |
kaf24@2375 | 314 " .long 34b,100b\n" |
kaf24@2375 | 315 " .long 35b,100b\n" |
kaf24@2375 | 316 " .long 36b,100b\n" |
kaf24@2375 | 317 " .long 37b,100b\n" |
kaf24@2375 | 318 " .long 99b,101b\n" |
kaf24@2375 | 319 ".previous" |
kaf24@2375 | 320 : "=&c"(size), "=&D" (d0), "=&S" (d1) |
kaf24@2375 | 321 : "1"(to), "2"(from), "0"(size) |
kaf24@2375 | 322 : "eax", "edx", "memory"); |
kaf24@2375 | 323 return size; |
kaf24@2375 | 324 } |
kaf24@2375 | 325 |
kaf24@2375 | 326 static unsigned long |
kaf24@2375 | 327 __copy_user_zeroing_intel(void *to, const void __user *from, unsigned long size) |
kaf24@2375 | 328 { |
kaf24@2375 | 329 int d0, d1; |
kaf24@2375 | 330 __asm__ __volatile__( |
kaf24@2375 | 331 " .align 2,0x90\n" |
kaf24@2375 | 332 "0: movl 32(%4), %%eax\n" |
kaf24@2375 | 333 " cmpl $67, %0\n" |
kaf24@2375 | 334 " jbe 2f\n" |
kaf24@2375 | 335 "1: movl 64(%4), %%eax\n" |
kaf24@2375 | 336 " .align 2,0x90\n" |
kaf24@2375 | 337 "2: movl 0(%4), %%eax\n" |
kaf24@2375 | 338 "21: movl 4(%4), %%edx\n" |
kaf24@2375 | 339 " movl %%eax, 0(%3)\n" |
kaf24@2375 | 340 " movl %%edx, 4(%3)\n" |
kaf24@2375 | 341 "3: movl 8(%4), %%eax\n" |
kaf24@2375 | 342 "31: movl 12(%4),%%edx\n" |
kaf24@2375 | 343 " movl %%eax, 8(%3)\n" |
kaf24@2375 | 344 " movl %%edx, 12(%3)\n" |
kaf24@2375 | 345 "4: movl 16(%4), %%eax\n" |
kaf24@2375 | 346 "41: movl 20(%4), %%edx\n" |
kaf24@2375 | 347 " movl %%eax, 16(%3)\n" |
kaf24@2375 | 348 " movl %%edx, 20(%3)\n" |
kaf24@2375 | 349 "10: movl 24(%4), %%eax\n" |
kaf24@2375 | 350 "51: movl 28(%4), %%edx\n" |
kaf24@2375 | 351 " movl %%eax, 24(%3)\n" |
kaf24@2375 | 352 " movl %%edx, 28(%3)\n" |
kaf24@2375 | 353 "11: movl 32(%4), %%eax\n" |
kaf24@2375 | 354 "61: movl 36(%4), %%edx\n" |
kaf24@2375 | 355 " movl %%eax, 32(%3)\n" |
kaf24@2375 | 356 " movl %%edx, 36(%3)\n" |
kaf24@2375 | 357 "12: movl 40(%4), %%eax\n" |
kaf24@2375 | 358 "71: movl 44(%4), %%edx\n" |
kaf24@2375 | 359 " movl %%eax, 40(%3)\n" |
kaf24@2375 | 360 " movl %%edx, 44(%3)\n" |
kaf24@2375 | 361 "13: movl 48(%4), %%eax\n" |
kaf24@2375 | 362 "81: movl 52(%4), %%edx\n" |
kaf24@2375 | 363 " movl %%eax, 48(%3)\n" |
kaf24@2375 | 364 " movl %%edx, 52(%3)\n" |
kaf24@2375 | 365 "14: movl 56(%4), %%eax\n" |
kaf24@2375 | 366 "91: movl 60(%4), %%edx\n" |
kaf24@2375 | 367 " movl %%eax, 56(%3)\n" |
kaf24@2375 | 368 " movl %%edx, 60(%3)\n" |
kaf24@2375 | 369 " addl $-64, %0\n" |
kaf24@2375 | 370 " addl $64, %4\n" |
kaf24@2375 | 371 " addl $64, %3\n" |
kaf24@2375 | 372 " cmpl $63, %0\n" |
kaf24@2375 | 373 " ja 0b\n" |
kaf24@2375 | 374 "5: movl %0, %%eax\n" |
kaf24@2375 | 375 " shrl $2, %0\n" |
kaf24@2375 | 376 " andl $3, %%eax\n" |
kaf24@2375 | 377 " cld\n" |
kaf24@2375 | 378 "6: rep; movsl\n" |
kaf24@2375 | 379 " movl %%eax,%0\n" |
kaf24@2375 | 380 "7: rep; movsb\n" |
kaf24@2375 | 381 "8:\n" |
kaf24@2375 | 382 ".section .fixup,\"ax\"\n" |
kaf24@2375 | 383 "9: lea 0(%%eax,%0,4),%0\n" |
kaf24@2375 | 384 "16: pushl %0\n" |
kaf24@2375 | 385 " pushl %%eax\n" |
kaf24@2375 | 386 " xorl %%eax,%%eax\n" |
kaf24@2375 | 387 " rep; stosb\n" |
kaf24@2375 | 388 " popl %%eax\n" |
kaf24@2375 | 389 " popl %0\n" |
kaf24@2375 | 390 " jmp 8b\n" |
kaf24@2375 | 391 ".previous\n" |
kaf24@2375 | 392 ".section __ex_table,\"a\"\n" |
kaf24@2375 | 393 " .align 4\n" |
kaf24@2375 | 394 " .long 0b,16b\n" |
kaf24@2375 | 395 " .long 1b,16b\n" |
kaf24@2375 | 396 " .long 2b,16b\n" |
kaf24@2375 | 397 " .long 21b,16b\n" |
kaf24@2375 | 398 " .long 3b,16b\n" |
kaf24@2375 | 399 " .long 31b,16b\n" |
kaf24@2375 | 400 " .long 4b,16b\n" |
kaf24@2375 | 401 " .long 41b,16b\n" |
kaf24@2375 | 402 " .long 10b,16b\n" |
kaf24@2375 | 403 " .long 51b,16b\n" |
kaf24@2375 | 404 " .long 11b,16b\n" |
kaf24@2375 | 405 " .long 61b,16b\n" |
kaf24@2375 | 406 " .long 12b,16b\n" |
kaf24@2375 | 407 " .long 71b,16b\n" |
kaf24@2375 | 408 " .long 13b,16b\n" |
kaf24@2375 | 409 " .long 81b,16b\n" |
kaf24@2375 | 410 " .long 14b,16b\n" |
kaf24@2375 | 411 " .long 91b,16b\n" |
kaf24@2375 | 412 " .long 6b,9b\n" |
kaf24@2375 | 413 " .long 7b,16b\n" |
kaf24@2375 | 414 ".previous" |
kaf24@2375 | 415 : "=&c"(size), "=&D" (d0), "=&S" (d1) |
kaf24@2375 | 416 : "1"(to), "2"(from), "0"(size) |
kaf24@2375 | 417 : "eax", "edx", "memory"); |
kaf24@2375 | 418 return size; |
kaf24@2375 | 419 } |
kaf24@2375 | 420 #else |
kaf24@2375 | 421 /* |
kaf24@2375 | 422 * Leave these declared but undefined. They should not be any references to |
kaf24@2375 | 423 * them |
kaf24@2375 | 424 */ |
kaf24@2375 | 425 unsigned long |
kaf24@2375 | 426 __copy_user_zeroing_intel(void *to, const void __user *from, unsigned long size); |
kaf24@2375 | 427 unsigned long |
kaf24@2375 | 428 __copy_user_intel(void __user *to, const void *from, unsigned long size); |
kaf24@2375 | 429 #endif /* CONFIG_X86_INTEL_USERCOPY */ |
kaf24@2375 | 430 |
kaf24@2375 | 431 /* Generic arbitrary sized copy. */ |
kaf24@2375 | 432 #define __copy_user(to,from,size) \ |
kaf24@2375 | 433 do { \ |
kaf24@2375 | 434 int __d0, __d1, __d2; \ |
kaf24@2375 | 435 __asm__ __volatile__( \ |
kaf24@2375 | 436 " cmp $7,%0\n" \ |
kaf24@2375 | 437 " jbe 1f\n" \ |
kaf24@2375 | 438 " movl %1,%0\n" \ |
kaf24@2375 | 439 " negl %0\n" \ |
kaf24@2375 | 440 " andl $7,%0\n" \ |
kaf24@2375 | 441 " subl %0,%3\n" \ |
kaf24@2375 | 442 "4: rep; movsb\n" \ |
kaf24@2375 | 443 " movl %3,%0\n" \ |
kaf24@2375 | 444 " shrl $2,%0\n" \ |
kaf24@2375 | 445 " andl $3,%3\n" \ |
kaf24@2375 | 446 " .align 2,0x90\n" \ |
kaf24@2375 | 447 "0: rep; movsl\n" \ |
kaf24@2375 | 448 " movl %3,%0\n" \ |
kaf24@2375 | 449 "1: rep; movsb\n" \ |
kaf24@2375 | 450 "2:\n" \ |
kaf24@2375 | 451 ".section .fixup,\"ax\"\n" \ |
kaf24@2375 | 452 "5: addl %3,%0\n" \ |
kaf24@2375 | 453 " jmp 2b\n" \ |
kaf24@2375 | 454 "3: lea 0(%3,%0,4),%0\n" \ |
kaf24@2375 | 455 " jmp 2b\n" \ |
kaf24@2375 | 456 ".previous\n" \ |
kaf24@2375 | 457 ".section __ex_table,\"a\"\n" \ |
kaf24@2375 | 458 " .align 4\n" \ |
kaf24@2375 | 459 " .long 4b,5b\n" \ |
kaf24@2375 | 460 " .long 0b,3b\n" \ |
kaf24@2375 | 461 " .long 1b,2b\n" \ |
kaf24@2375 | 462 ".previous" \ |
kaf24@2375 | 463 : "=&c"(size), "=&D" (__d0), "=&S" (__d1), "=r"(__d2) \ |
kaf24@2375 | 464 : "3"(size), "0"(size), "1"(to), "2"(from) \ |
kaf24@2375 | 465 : "memory"); \ |
kaf24@2375 | 466 } while (0) |
kaf24@2375 | 467 |
kaf24@2375 | 468 #define __copy_user_zeroing(to,from,size) \ |
kaf24@2375 | 469 do { \ |
kaf24@2375 | 470 int __d0, __d1, __d2; \ |
kaf24@2375 | 471 __asm__ __volatile__( \ |
kaf24@2375 | 472 " cmp $7,%0\n" \ |
kaf24@2375 | 473 " jbe 1f\n" \ |
kaf24@2375 | 474 " movl %1,%0\n" \ |
kaf24@2375 | 475 " negl %0\n" \ |
kaf24@2375 | 476 " andl $7,%0\n" \ |
kaf24@2375 | 477 " subl %0,%3\n" \ |
kaf24@2375 | 478 "4: rep; movsb\n" \ |
kaf24@2375 | 479 " movl %3,%0\n" \ |
kaf24@2375 | 480 " shrl $2,%0\n" \ |
kaf24@2375 | 481 " andl $3,%3\n" \ |
kaf24@2375 | 482 " .align 2,0x90\n" \ |
kaf24@2375 | 483 "0: rep; movsl\n" \ |
kaf24@2375 | 484 " movl %3,%0\n" \ |
kaf24@2375 | 485 "1: rep; movsb\n" \ |
kaf24@2375 | 486 "2:\n" \ |
kaf24@2375 | 487 ".section .fixup,\"ax\"\n" \ |
kaf24@2375 | 488 "5: addl %3,%0\n" \ |
kaf24@2375 | 489 " jmp 6f\n" \ |
kaf24@2375 | 490 "3: lea 0(%3,%0,4),%0\n" \ |
kaf24@2375 | 491 "6: pushl %0\n" \ |
kaf24@2375 | 492 " pushl %%eax\n" \ |
kaf24@2375 | 493 " xorl %%eax,%%eax\n" \ |
kaf24@2375 | 494 " rep; stosb\n" \ |
kaf24@2375 | 495 " popl %%eax\n" \ |
kaf24@2375 | 496 " popl %0\n" \ |
kaf24@2375 | 497 " jmp 2b\n" \ |
kaf24@2375 | 498 ".previous\n" \ |
kaf24@2375 | 499 ".section __ex_table,\"a\"\n" \ |
kaf24@2375 | 500 " .align 4\n" \ |
kaf24@2375 | 501 " .long 4b,5b\n" \ |
kaf24@2375 | 502 " .long 0b,3b\n" \ |
kaf24@2375 | 503 " .long 1b,6b\n" \ |
kaf24@2375 | 504 ".previous" \ |
kaf24@2375 | 505 : "=&c"(size), "=&D" (__d0), "=&S" (__d1), "=r"(__d2) \ |
kaf24@2375 | 506 : "3"(size), "0"(size), "1"(to), "2"(from) \ |
kaf24@2375 | 507 : "memory"); \ |
kaf24@2375 | 508 } while (0) |
kaf24@2375 | 509 |
kaf24@2375 | 510 |
kaf24@2375 | 511 unsigned long __copy_to_user_ll(void __user *to, const void *from, unsigned long n) |
kaf24@2375 | 512 { |
kaf24@2375 | 513 if (movsl_is_ok(to, from, n)) |
kaf24@2375 | 514 __copy_user(to, from, n); |
kaf24@2375 | 515 else |
kaf24@2375 | 516 n = __copy_user_intel(to, from, n); |
kaf24@2375 | 517 return n; |
kaf24@2375 | 518 } |
kaf24@2375 | 519 |
kaf24@2375 | 520 unsigned long |
kaf24@2375 | 521 __copy_from_user_ll(void *to, const void __user *from, unsigned long n) |
kaf24@2375 | 522 { |
kaf24@2375 | 523 if (movsl_is_ok(to, from, n)) |
kaf24@2375 | 524 __copy_user_zeroing(to, from, n); |
kaf24@2375 | 525 else |
kaf24@2375 | 526 n = __copy_user_zeroing_intel(to, from, n); |
kaf24@2375 | 527 return n; |
kaf24@2375 | 528 } |
kaf24@2375 | 529 |
kaf24@2375 | 530 /** |
kaf24@2375 | 531 * copy_to_user: - Copy a block of data into user space. |
kaf24@2375 | 532 * @to: Destination address, in user space. |
kaf24@2375 | 533 * @from: Source address, in kernel space. |
kaf24@2375 | 534 * @n: Number of bytes to copy. |
kaf24@2375 | 535 * |
kaf24@2375 | 536 * Context: User context only. This function may sleep. |
kaf24@2375 | 537 * |
kaf24@2375 | 538 * Copy data from kernel space to user space. |
kaf24@2375 | 539 * |
kaf24@2375 | 540 * Returns number of bytes that could not be copied. |
kaf24@2375 | 541 * On success, this will be zero. |
kaf24@2375 | 542 */ |
kaf24@2375 | 543 unsigned long |
kaf24@2375 | 544 copy_to_user(void __user *to, const void *from, unsigned long n) |
kaf24@2375 | 545 { |
kaf24@2375 | 546 might_sleep(); |
kaf24@2375 | 547 if (access_ok(VERIFY_WRITE, to, n)) |
kaf24@2375 | 548 n = __copy_to_user(to, from, n); |
kaf24@2375 | 549 return n; |
kaf24@2375 | 550 } |
kaf24@2375 | 551 EXPORT_SYMBOL(copy_to_user); |
kaf24@2375 | 552 |
kaf24@2375 | 553 /** |
kaf24@2375 | 554 * copy_from_user: - Copy a block of data from user space. |
kaf24@2375 | 555 * @to: Destination address, in kernel space. |
kaf24@2375 | 556 * @from: Source address, in user space. |
kaf24@2375 | 557 * @n: Number of bytes to copy. |
kaf24@2375 | 558 * |
kaf24@2375 | 559 * Context: User context only. This function may sleep. |
kaf24@2375 | 560 * |
kaf24@2375 | 561 * Copy data from user space to kernel space. |
kaf24@2375 | 562 * |
kaf24@2375 | 563 * Returns number of bytes that could not be copied. |
kaf24@2375 | 564 * On success, this will be zero. |
kaf24@2375 | 565 * |
kaf24@2375 | 566 * If some data could not be copied, this function will pad the copied |
kaf24@2375 | 567 * data to the requested size using zero bytes. |
kaf24@2375 | 568 */ |
kaf24@2375 | 569 unsigned long |
kaf24@2375 | 570 copy_from_user(void *to, const void __user *from, unsigned long n) |
kaf24@2375 | 571 { |
kaf24@2375 | 572 might_sleep(); |
kaf24@2375 | 573 if (access_ok(VERIFY_READ, from, n)) |
kaf24@2375 | 574 n = __copy_from_user(to, from, n); |
kaf24@2375 | 575 else |
kaf24@2375 | 576 memset(to, 0, n); |
kaf24@2375 | 577 return n; |
kaf24@2375 | 578 } |
kaf24@2375 | 579 EXPORT_SYMBOL(copy_from_user); |