Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Merge branch 'devel'
[palacios.git] / kitten / arch / x86_64 / lib / usercopy.c
diff --git a/kitten/arch/x86_64/lib/usercopy.c b/kitten/arch/x86_64/lib/usercopy.c
new file mode 100644 (file)
index 0000000..d92277b
--- /dev/null
@@ -0,0 +1,155 @@
+/* 
+ * User address space access functions.
+ *
+ * Copyright 1997 Andi Kleen <ak@muc.de>
+ * Copyright 1997 Linus Torvalds
+ * Copyright 2002 Andi Kleen <ak@suse.de>
+ */
+#include <arch/uaccess.h>
+
+/*
+ * Copy a null terminated string from userspace.
+ */
+
+#define __do_strncpy_from_user(dst,src,count,res)                         \
+do {                                                                      \
+       long __d0, __d1, __d2;                                             \
+       __asm__ __volatile__(                                              \
+               "       testq %1,%1\n"                                     \
+               "       jz 2f\n"                                           \
+               "0:     lodsb\n"                                           \
+               "       stosb\n"                                           \
+               "       testb %%al,%%al\n"                                 \
+               "       jz 1f\n"                                           \
+               "       decq %1\n"                                         \
+               "       jnz 0b\n"                                          \
+               "1:     subq %1,%0\n"                                      \
+               "2:\n"                                                     \
+               ".section .fixup,\"ax\"\n"                                 \
+               "3:     movq %5,%0\n"                                      \
+               "       jmp 2b\n"                                          \
+               ".previous\n"                                              \
+               ".section __ex_table,\"a\"\n"                              \
+               "       .align 8\n"                                        \
+               "       .quad 0b,3b\n"                                     \
+               ".previous"                                                \
+               : "=r"(res), "=c"(count), "=&a" (__d0), "=&S" (__d1),      \
+                 "=&D" (__d2)                                             \
+               : "i"(-EFAULT), "0"(count), "1"(count), "3"(src), "4"(dst) \
+               : "memory");                                               \
+} while (0)
+
+long
+__strncpy_from_user(char *dst, const char __user *src, long count)
+{
+       long res;
+       __do_strncpy_from_user(dst, src, count, res);
+       return res;
+}
+
+long
+strncpy_from_user(char *dst, const char __user *src, long count)
+{
+       long res = -EFAULT;
+       if (access_ok(VERIFY_READ, src, 1))
+               return __strncpy_from_user(dst, src, count);
+       return res;
+}
+
+/*
+ * Zero Userspace
+ */
+
+unsigned long __clear_user(void __user *addr, unsigned long size)
+{
+       long __d0;
+       /* no memory constraint because it doesn't change any memory gcc knows
+          about */
+       asm volatile(
+               "       testq  %[size8],%[size8]\n"
+               "       jz     4f\n"
+               "0:     movq %[zero],(%[dst])\n"
+               "       addq   %[eight],%[dst]\n"
+               "       decl %%ecx ; jnz   0b\n"
+               "4:     movq  %[size1],%%rcx\n"
+               "       testl %%ecx,%%ecx\n"
+               "       jz     2f\n"
+               "1:     movb   %b[zero],(%[dst])\n"
+               "       incq   %[dst]\n"
+               "       decl %%ecx ; jnz  1b\n"
+               "2:\n"
+               ".section .fixup,\"ax\"\n"
+               "3:     lea 0(%[size1],%[size8],8),%[size8]\n"
+               "       jmp 2b\n"
+               ".previous\n"
+               ".section __ex_table,\"a\"\n"
+               "       .align 8\n"
+               "       .quad 0b,3b\n"
+               "       .quad 1b,2b\n"
+               ".previous"
+               : [size8] "=c"(size), [dst] "=&D" (__d0)
+               : [size1] "r"(size & 7), "[size8]" (size / 8), "[dst]"(addr),
+                 [zero] "r" (0UL), [eight] "r" (8UL));
+       return size;
+}
+
+unsigned long clear_user(void __user *to, unsigned long n)
+{
+       if (access_ok(VERIFY_WRITE, to, n))
+               return __clear_user(to, n);
+       return n;
+}
+
+/*
+ * Return the size of a string (including the ending 0)
+ *
+ * Return 0 on exception, a value greater than N if too long
+ */
+
+long __strnlen_user(const char __user *s, long n)
+{
+       long res = 0;
+       char c;
+
+       while (1) {
+               if (res>n)
+                       return n+1;
+               if (__get_user(c, s))
+                       return 0;
+               if (!c)
+                       return res+1;
+               res++;
+               s++;
+       }
+}
+
+long strnlen_user(const char __user *s, long n)
+{
+       if (!access_ok(VERIFY_READ, s, n))
+               return 0;
+       return __strnlen_user(s, n);
+}
+
+long strlen_user(const char __user *s)
+{
+       long res = 0;
+       char c;
+
+       for (;;) {
+               if (get_user(c, s))
+                       return 0;
+               if (!c)
+                       return res+1;
+               res++;
+               s++;
+       }
+}
+
+unsigned long copy_in_user(void __user *to, const void __user *from, unsigned len)
+{
+       if (access_ok(VERIFY_WRITE, to, len) && access_ok(VERIFY_READ, from, len)) { 
+               return copy_user_generic((__force void *)to, (__force void *)from, len);
+       } 
+       return len;             
+}
+