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
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);