aboutsummaryrefslogtreecommitdiffstats
path: root/xen/arch/x86/usercopy.c
diff options
context:
space:
mode:
authorkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>2005-06-06 10:52:53 +0000
committerkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>2005-06-06 10:52:53 +0000
commitc00ea59fcce0b921e5c6ccf2b0d25d6d85ff745c (patch)
tree54e7314bc8324f32541779700ec68731e5b2577d /xen/arch/x86/usercopy.c
parent4f7a49d8d0836ab8183893f79ac5fb7731cac32c (diff)
downloadxen-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.c139
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;
+}