Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / arch / mn10300 / lib / usercopy.c
diff --git a/kernel/arch/mn10300/lib/usercopy.c b/kernel/arch/mn10300/lib/usercopy.c
new file mode 100644 (file)
index 0000000..7826e6c
--- /dev/null
@@ -0,0 +1,166 @@
+/* MN10300 Userspace accessor functions
+ *
+ * Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd.
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <asm/uaccess.h>
+
+unsigned long
+__generic_copy_to_user(void *to, const void *from, unsigned long n)
+{
+       if (access_ok(VERIFY_WRITE, to, n))
+               __copy_user(to, from, n);
+       return n;
+}
+
+unsigned long
+__generic_copy_from_user(void *to, const void *from, unsigned long n)
+{
+       if (access_ok(VERIFY_READ, from, n))
+               __copy_user_zeroing(to, from, n);
+       return n;
+}
+
+/*
+ * Copy a null terminated string from userspace.
+ */
+#define __do_strncpy_from_user(dst, src, count, res)           \
+do {                                                           \
+       int w;                                                  \
+       asm volatile(                                           \
+               "       mov     %1,%0\n"                        \
+               "       cmp     0,%1\n"                         \
+               "       beq     2f\n"                           \
+               "0:\n"                                          \
+               "       movbu   (%5),%2\n"                      \
+               "1:\n"                                          \
+               "       movbu   %2,(%6)\n"                      \
+               "       inc     %5\n"                           \
+               "       inc     %6\n"                           \
+               "       cmp     0,%2\n"                         \
+               "       beq     2f\n"                           \
+               "       add     -1,%1\n"                        \
+               "       bne     0b\n"                           \
+               "2:\n"                                          \
+               "       sub     %1,%0\n"                        \
+               "3:\n"                                          \
+               "       .section .fixup,\"ax\"\n"               \
+               "4:\n"                                          \
+               "       mov     %3,%0\n"                        \
+               "       jmp     3b\n"                           \
+               "       .previous\n"                            \
+               "       .section __ex_table,\"a\"\n"            \
+               "       .balign 4\n"                            \
+               "       .long 0b,4b\n"                          \
+               "       .long 1b,4b\n"                          \
+               "       .previous"                              \
+               :"=&r"(res), "=r"(count), "=&r"(w)              \
+               :"i"(-EFAULT), "1"(count), "a"(src), "a"(dst)   \
+               : "memory", "cc");                                      \
+} while (0)
+
+long
+__strncpy_from_user(char *dst, const char *src, long count)
+{
+       long res;
+       __do_strncpy_from_user(dst, src, count, res);
+       return res;
+}
+
+long
+strncpy_from_user(char *dst, const char *src, long count)
+{
+       long res = -EFAULT;
+       if (access_ok(VERIFY_READ, src, 1))
+               __do_strncpy_from_user(dst, src, count, res);
+       return res;
+}
+
+
+/*
+ * Clear a userspace memory
+ */
+#define __do_clear_user(addr, size)            \
+do {                                           \
+       int w;                                  \
+       asm volatile(                           \
+               "       cmp 0,%0\n"             \
+               "       beq 1f\n"               \
+               "       clr %1\n"               \
+               "0:     movbu %1,(%3,%2)\n"     \
+               "       inc %3\n"               \
+               "       cmp %0,%3\n"            \
+               "       bne 0b\n"               \
+               "1:\n"                          \
+               "       sub %3,%0\n"            \
+               "2:\n"                          \
+               ".section .fixup,\"ax\"\n"      \
+               "3:     jmp 2b\n"               \
+               ".previous\n"                   \
+               ".section __ex_table,\"a\"\n"   \
+               "       .balign 4\n"            \
+               "       .long 0b,3b\n"          \
+               ".previous\n"                   \
+               : "+r"(size), "=&r"(w)          \
+               : "a"(addr), "d"(0)             \
+               : "memory", "cc");              \
+} while (0)
+
+unsigned long
+__clear_user(void *to, unsigned long n)
+{
+       __do_clear_user(to, n);
+       return n;
+}
+
+unsigned long
+clear_user(void *to, unsigned long n)
+{
+       if (access_ok(VERIFY_WRITE, to, n))
+               __do_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 *s, long n)
+{
+       unsigned long res, w;
+
+       if (!__addr_ok(s))
+               return 0;
+
+       if (n < 0 || n + (u_long) s > current_thread_info()->addr_limit.seg)
+               n = current_thread_info()->addr_limit.seg - (u_long)s;
+
+       asm volatile(
+               "0:     cmp %4,%0\n"
+               "       beq 2f\n"
+               "1:     movbu (%0,%3),%1\n"
+               "       inc %0\n"
+               "       cmp 0,%1\n"
+               "       beq 3f\n"
+               "       bra 0b\n"
+               "2:     clr %0\n"
+               "3:\n"
+               ".section .fixup,\"ax\"\n"
+               "4:     jmp 2b\n"
+               ".previous\n"
+               ".section __ex_table,\"a\"\n"
+               "       .balign 4\n"
+               "       .long 1b,4b\n"
+               ".previous\n"
+               :"=d"(res), "=&r"(w)
+               :"0"(0), "a"(s), "r"(n)
+               : "memory", "cc");
+       return res;
+}