Merge branch 'upstream-linus' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik...
[pandora-kernel.git] / include / asm-arm / uaccess.h
index a2fdad0..09ad0ca 100644 (file)
@@ -40,16 +40,25 @@ struct exception_table_entry
 
 extern int fixup_exception(struct pt_regs *regs);
 
+/*
+ * These two are intentionally not defined anywhere - if the kernel
+ * code generates any references to them, that's a bug.
+ */
+extern int __get_user_bad(void);
+extern int __put_user_bad(void);
+
 /*
  * Note that this is actually 0x1,0000,0000
  */
 #define KERNEL_DS      0x00000000
-#define USER_DS                TASK_SIZE
-
 #define get_ds()       (KERNEL_DS)
+
+#ifdef CONFIG_MMU
+
+#define USER_DS                TASK_SIZE
 #define get_fs()       (current_thread_info()->addr_limit)
 
-static inline void set_fs (mm_segment_t fs)
+static inline void set_fs(mm_segment_t fs)
 {
        current_thread_info()->addr_limit = fs;
        modify_domain(DOMAIN_KERNEL, fs ? DOMAIN_CLIENT : DOMAIN_MANAGER);
@@ -75,8 +84,6 @@ static inline void set_fs (mm_segment_t fs)
                : "cc"); \
        flag; })
 
-#define access_ok(type,addr,size)      (__range_ok(addr,size) == 0)
-
 /*
  * Single-value transfer routines.  They automatically use the right
  * size if we just have the right pointer type.  Note that the functions
@@ -87,21 +94,10 @@ static inline void set_fs (mm_segment_t fs)
  * fixup code, but there are a few places where it intrudes on the
  * main code path.  When we only write to user space, there is no
  * problem.
- *
- * The "__xxx" versions of the user access functions do not verify the
- * address space - it must have been done previously with a separate
- * "access_ok()" call.
- *
- * The "xxx_error" versions set the third argument to EFAULT if an
- * error occurs, and leave it unchanged on success.  Note that these
- * versions are void (ie, don't return a value as such).
  */
-
 extern int __get_user_1(void *);
 extern int __get_user_2(void *);
 extern int __get_user_4(void *);
-extern int __get_user_8(void *);
-extern int __get_user_bad(void);
 
 #define __get_user_x(__r2,__p,__e,__s,__i...)                          \
           __asm__ __volatile__ (                                       \
@@ -114,7 +110,7 @@ extern int __get_user_bad(void);
 #define get_user(x,p)                                                  \
        ({                                                              \
                const register typeof(*(p)) __user *__p asm("r0") = (p);\
-               register typeof(*(p)) __r2 asm("r2");                   \
+               register unsigned long __r2 asm("r2");                  \
                register int __e asm("r0");                             \
                switch (sizeof(*(__p))) {                               \
                case 1:                                                 \
@@ -126,15 +122,80 @@ extern int __get_user_bad(void);
                case 4:                                                 \
                        __get_user_x(__r2, __p, __e, 4, "lr");          \
                        break;                                          \
-               case 8:                                                 \
-                       __get_user_x(__r2, __p, __e, 8, "lr");          \
-                       break;                                          \
                default: __e = __get_user_bad(); break;                 \
                }                                                       \
-               x = __r2;                                               \
+               x = (typeof(*(p))) __r2;                                \
                __e;                                                    \
        })
 
+extern int __put_user_1(void *, unsigned int);
+extern int __put_user_2(void *, unsigned int);
+extern int __put_user_4(void *, unsigned int);
+extern int __put_user_8(void *, unsigned long long);
+
+#define __put_user_x(__r2,__p,__e,__s)                                 \
+          __asm__ __volatile__ (                                       \
+               __asmeq("%0", "r0") __asmeq("%2", "r2")                 \
+               "bl     __put_user_" #__s                               \
+               : "=&r" (__e)                                           \
+               : "0" (__p), "r" (__r2)                                 \
+               : "ip", "lr", "cc")
+
+#define put_user(x,p)                                                  \
+       ({                                                              \
+               const register typeof(*(p)) __r2 asm("r2") = (x);       \
+               const register typeof(*(p)) __user *__p asm("r0") = (p);\
+               register int __e asm("r0");                             \
+               switch (sizeof(*(__p))) {                               \
+               case 1:                                                 \
+                       __put_user_x(__r2, __p, __e, 1);                \
+                       break;                                          \
+               case 2:                                                 \
+                       __put_user_x(__r2, __p, __e, 2);                \
+                       break;                                          \
+               case 4:                                                 \
+                       __put_user_x(__r2, __p, __e, 4);                \
+                       break;                                          \
+               case 8:                                                 \
+                       __put_user_x(__r2, __p, __e, 8);                \
+                       break;                                          \
+               default: __e = __put_user_bad(); break;                 \
+               }                                                       \
+               __e;                                                    \
+       })
+
+#else /* CONFIG_MMU */
+
+/*
+ * uClinux has only one addr space, so has simplified address limits.
+ */
+#define USER_DS                        KERNEL_DS
+
+#define segment_eq(a,b)                (1)
+#define __addr_ok(addr)                (1)
+#define __range_ok(addr,size)  (0)
+#define get_fs()               (KERNEL_DS)
+
+static inline void set_fs(mm_segment_t fs)
+{
+}
+
+#define get_user(x,p)  __get_user(x,p)
+#define put_user(x,p)  __put_user(x,p)
+
+#endif /* CONFIG_MMU */
+
+#define access_ok(type,addr,size)      (__range_ok(addr,size) == 0)
+
+/*
+ * The "__xxx" versions of the user access functions do not verify the
+ * address space - it must have been done previously with a separate
+ * "access_ok()" call.
+ *
+ * The "xxx_error" versions set the third argument to EFAULT if an
+ * error occurs, and leave it unchanged on success.  Note that these
+ * versions are void (ie, don't return a value as such).
+ */
 #define __get_user(x,ptr)                                              \
 ({                                                                     \
        long __gu_err = 0;                                              \
@@ -216,43 +277,6 @@ do {                                                                       \
        : "r" (addr), "i" (-EFAULT)                             \
        : "cc")
 
-extern int __put_user_1(void *, unsigned int);
-extern int __put_user_2(void *, unsigned int);
-extern int __put_user_4(void *, unsigned int);
-extern int __put_user_8(void *, unsigned long long);
-extern int __put_user_bad(void);
-
-#define __put_user_x(__r2,__p,__e,__s)                                 \
-          __asm__ __volatile__ (                                       \
-               __asmeq("%0", "r0") __asmeq("%2", "r2")                 \
-               "bl     __put_user_" #__s                               \
-               : "=&r" (__e)                                           \
-               : "0" (__p), "r" (__r2)                                 \
-               : "ip", "lr", "cc")
-
-#define put_user(x,p)                                                  \
-       ({                                                              \
-               const register typeof(*(p)) __r2 asm("r2") = (x);       \
-               const register typeof(*(p)) __user *__p asm("r0") = (p);\
-               register int __e asm("r0");                             \
-               switch (sizeof(*(__p))) {                               \
-               case 1:                                                 \
-                       __put_user_x(__r2, __p, __e, 1);                \
-                       break;                                          \
-               case 2:                                                 \
-                       __put_user_x(__r2, __p, __e, 2);                \
-                       break;                                          \
-               case 4:                                                 \
-                       __put_user_x(__r2, __p, __e, 4);                \
-                       break;                                          \
-               case 8:                                                 \
-                       __put_user_x(__r2, __p, __e, 8);                \
-                       break;                                          \
-               default: __e = __put_user_bad(); break;                 \
-               }                                                       \
-               __e;                                                    \
-       })
-
 #define __put_user(x,ptr)                                              \
 ({                                                                     \
        long __pu_err = 0;                                              \
@@ -357,66 +381,54 @@ do {                                                                      \
        : "r" (x), "i" (-EFAULT)                                \
        : "cc")
 
-extern unsigned long __arch_copy_from_user(void *to, const void __user *from, unsigned long n);
-extern unsigned long __arch_copy_to_user(void __user *to, const void *from, unsigned long n);
-extern unsigned long __arch_clear_user(void __user *addr, unsigned long n);
-extern unsigned long __arch_strncpy_from_user(char *to, const char __user *from, unsigned long count);
-extern unsigned long __arch_strnlen_user(const char __user *s, long n);
+
+#ifdef CONFIG_MMU
+extern unsigned long __copy_from_user(void *to, const void __user *from, unsigned long n);
+extern unsigned long __copy_to_user(void __user *to, const void *from, unsigned long n);
+extern unsigned long __clear_user(void __user *addr, unsigned long n);
+#else
+#define __copy_from_user(to,from,n)    (memcpy(to, (void __force *)from, n), 0)
+#define __copy_to_user(to,from,n)      (memcpy((void __force *)to, from, n), 0)
+#define __clear_user(addr,n)           (memset((void __force *)addr, 0, n), 0)
+#endif
+
+extern unsigned long __strncpy_from_user(char *to, const char __user *from, unsigned long count);
+extern unsigned long __strnlen_user(const char __user *s, long n);
 
 static inline unsigned long copy_from_user(void *to, const void __user *from, unsigned long n)
 {
        if (access_ok(VERIFY_READ, from, n))
-               n = __arch_copy_from_user(to, from, n);
+               n = __copy_from_user(to, from, n);
        else /* security hole - plug it */
                memzero(to, n);
        return n;
 }
 
-static inline unsigned long __copy_from_user(void *to, const void __user *from, unsigned long n)
-{
-       return __arch_copy_from_user(to, from, n);
-}
-
 static inline unsigned long copy_to_user(void __user *to, const void *from, unsigned long n)
 {
        if (access_ok(VERIFY_WRITE, to, n))
-               n = __arch_copy_to_user(to, from, n);
+               n = __copy_to_user(to, from, n);
        return n;
 }
 
-static inline unsigned long __copy_to_user(void __user *to, const void *from, unsigned long n)
-{
-       return __arch_copy_to_user(to, from, n);
-}
-
 #define __copy_to_user_inatomic __copy_to_user
 #define __copy_from_user_inatomic __copy_from_user
 
-static inline unsigned long clear_user (void __user *to, unsigned long n)
+static inline unsigned long clear_user(void __user *to, unsigned long n)
 {
        if (access_ok(VERIFY_WRITE, to, n))
-               n = __arch_clear_user(to, n);
+               n = __clear_user(to, n);
        return n;
 }
 
-static inline unsigned long __clear_user (void __user *to, unsigned long n)
-{
-       return __arch_clear_user(to, n);
-}
-
-static inline long strncpy_from_user (char *dst, const char __user *src, long count)
+static inline long strncpy_from_user(char *dst, const char __user *src, long count)
 {
        long res = -EFAULT;
        if (access_ok(VERIFY_READ, src, 1))
-               res = __arch_strncpy_from_user(dst, src, count);
+               res = __strncpy_from_user(dst, src, count);
        return res;
 }
 
-static inline long __strncpy_from_user (char *dst, const char __user *src, long count)
-{
-       return __arch_strncpy_from_user(dst, src, count);
-}
-
 #define strlen_user(s) strnlen_user(s, ~0UL >> 1)
 
 static inline long strnlen_user(const char __user *s, long n)
@@ -424,7 +436,7 @@ static inline long strnlen_user(const char __user *s, long n)
        unsigned long res = 0;
 
        if (__addr_ok(s))
-               res = __arch_strnlen_user(s, n);
+               res = __strnlen_user(s, n);
 
        return res;
 }