diff options
author | kaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk> | 2005-06-06 10:52:53 +0000 |
---|---|---|
committer | kaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk> | 2005-06-06 10:52:53 +0000 |
commit | c00ea59fcce0b921e5c6ccf2b0d25d6d85ff745c (patch) | |
tree | 54e7314bc8324f32541779700ec68731e5b2577d /xen/arch/x86/usercopy.c | |
parent | 4f7a49d8d0836ab8183893f79ac5fb7731cac32c (diff) | |
download | xen-c00ea59fcce0b921e5c6ccf2b0d25d6d85ff745c.tar.gz xen-c00ea59fcce0b921e5c6ccf2b0d25d6d85ff745c.tar.bz2 xen-c00ea59fcce0b921e5c6ccf2b0d25d6d85ff745c.zip |
bitkeeper revision 1.1682 (42a42b05Cvw3LyFcUHH4i1_9HWbLBA)
Merge x86/32 and x86/64 usercopy routines.
Signed-off-by: Keir Fraser <keir@xensource.com>
Diffstat (limited to 'xen/arch/x86/usercopy.c')
-rw-r--r-- | xen/arch/x86/usercopy.c | 139 |
1 files changed, 139 insertions, 0 deletions
diff --git a/xen/arch/x86/usercopy.c b/xen/arch/x86/usercopy.c new file mode 100644 index 0000000000..f16c4da102 --- /dev/null +++ b/xen/arch/x86/usercopy.c @@ -0,0 +1,139 @@ +/* + * User address space access functions. + * + * Copyright 1997 Andi Kleen <ak@muc.de> + * Copyright 1997 Linus Torvalds + * Copyright 2002 Andi Kleen <ak@suse.de> + */ + +#include <xen/config.h> +#include <xen/lib.h> +#include <asm/uaccess.h> + +unsigned long __copy_to_user_ll(void __user *to, const void *from, unsigned n) +{ + unsigned long __d0, __d1, __d2, __n = n; + __asm__ __volatile__( + " cmp $"STR(2*BYTES_PER_LONG-1)",%0\n" + " jbe 1f\n" + " mov %1,%0\n" + " neg %0\n" + " and $"STR(BYTES_PER_LONG-1)",%0\n" + " sub %0,%3\n" + "4: rep; movsb\n" /* make 'to' address aligned */ + " mov %3,%0\n" + " shr $"STR(LONG_BYTEORDER)",%0\n" + " and $"STR(BYTES_PER_LONG-1)",%3\n" + " .align 2,0x90\n" + "0: rep; movs"__OS"\n" /* as many words as possible... */ + " mov %3,%0\n" + "1: rep; movsb\n" /* ...remainder copied as bytes */ + "2:\n" + ".section .fixup,\"ax\"\n" + "5: add %3,%0\n" + " jmp 2b\n" + "3: lea 0(%3,%0,"STR(BYTES_PER_LONG)"),%0\n" + " jmp 2b\n" + ".previous\n" + ".section __ex_table,\"a\"\n" + " "__FIXUP_ALIGN"\n" + " "__FIXUP_WORD" 4b,5b\n" + " "__FIXUP_WORD" 0b,3b\n" + " "__FIXUP_WORD" 1b,2b\n" + ".previous" + : "=&c"(__n), "=&D" (__d0), "=&S" (__d1), "=r"(__d2) + : "3"(__n), "0"(__n), "1"(to), "2"(from) + : "memory"); + return (unsigned)__n; +} + +unsigned long +__copy_from_user_ll(void *to, const void __user *from, unsigned n) +{ + unsigned long __d0, __d1, __d2, __n = n; + __asm__ __volatile__( + " cmp $"STR(2*BYTES_PER_LONG-1)",%0\n" + " jbe 1f\n" + " mov %1,%0\n" + " neg %0\n" + " and $"STR(BYTES_PER_LONG-1)",%0\n" + " sub %0,%3\n" + "4: rep; movsb\n" /* make 'to' address aligned */ + " mov %3,%0\n" + " shr $"STR(LONG_BYTEORDER)",%0\n" + " and $"STR(BYTES_PER_LONG-1)",%3\n" + " .align 2,0x90\n" + "0: rep; movs"__OS"\n" /* as many words as possible... */ + " mov %3,%0\n" + "1: rep; movsb\n" /* ...remainder copied as bytes */ + "2:\n" + ".section .fixup,\"ax\"\n" + "5: add %3,%0\n" + " jmp 6f\n" + "3: lea 0(%3,%0,"STR(BYTES_PER_LONG)"),%0\n" + "6: push %0\n" + " push %%"__OP"ax\n" + " xor %%eax,%%eax\n" + " rep; stosb\n" + " pop %%"__OP"ax\n" + " pop %0\n" + " jmp 2b\n" + ".previous\n" + ".section __ex_table,\"a\"\n" + " "__FIXUP_ALIGN"\n" + " "__FIXUP_WORD" 4b,5b\n" + " "__FIXUP_WORD" 0b,3b\n" + " "__FIXUP_WORD" 1b,6b\n" + ".previous" + : "=&c"(__n), "=&D" (__d0), "=&S" (__d1), "=r"(__d2) + : "3"(__n), "0"(__n), "1"(to), "2"(from) + : "memory"); + return (unsigned)__n; +} + +/** + * copy_to_user: - Copy a block of data into user space. + * @to: Destination address, in user space. + * @from: Source address, in kernel space. + * @n: Number of bytes to copy. + * + * Context: User context only. This function may sleep. + * + * Copy data from kernel space to user space. + * + * Returns number of bytes that could not be copied. + * On success, this will be zero. + */ +unsigned long +copy_to_user(void __user *to, const void *from, unsigned n) +{ + if (access_ok(to, n)) + n = __copy_to_user(to, from, n); + return n; +} + +/** + * copy_from_user: - Copy a block of data from user space. + * @to: Destination address, in kernel space. + * @from: Source address, in user space. + * @n: Number of bytes to copy. + * + * Context: User context only. This function may sleep. + * + * Copy data from user space to kernel space. + * + * Returns number of bytes that could not be copied. + * On success, this will be zero. + * + * If some data could not be copied, this function will pad the copied + * data to the requested size using zero bytes. + */ +unsigned long +copy_from_user(void *to, const void __user *from, unsigned n) +{ + if (access_ok(from, n)) + n = __copy_from_user(to, from, n); + else + memset(to, 0, n); + return n; +} |