fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / include / asm-mips / uaccess.h
index adbb24b..1cdd4ee 100644 (file)
@@ -9,8 +9,7 @@
 #ifndef _ASM_UACCESS_H
 #define _ASM_UACCESS_H
 
-#include <linux/config.h>
-#include <linux/compiler.h>
+#include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/thread_info.h>
 #include <asm-generic/uaccess.h>
@@ -22,7 +21,7 @@
  *
  * For historical reasons, these macros are grossly misnamed.
  */
-#ifdef CONFIG_MIPS32
+#ifdef CONFIG_32BIT
 
 #define __UA_LIMIT     0x80000000UL
 
@@ -32,9 +31,9 @@
 #define __UA_t0                "$8"
 #define __UA_t1                "$9"
 
-#endif /* CONFIG_MIPS32 */
+#endif /* CONFIG_32BIT */
 
-#ifdef CONFIG_MIPS64
+#ifdef CONFIG_64BIT
 
 #define __UA_LIMIT     (- TASK_SIZE)
 
@@ -44,7 +43,7 @@
 #define __UA_t0                "$12"
 #define __UA_t1                "$13"
 
-#endif /* CONFIG_MIPS64 */
+#endif /* CONFIG_64BIT */
 
 /*
  * USER_DS is a bitmask that has the bits set that may not be set in a valid
 #define access_ok(type, addr, size)                                    \
        likely(__access_ok((unsigned long)(addr), (size),__access_mask))
 
-/*
- * verify_area: - Obsolete, use access_ok()
- * @type: Type of access: %VERIFY_READ or %VERIFY_WRITE
- * @addr: User space pointer to start of block to check
- * @size: Size of block to check
- *
- * Context: User context only.  This function may sleep.
- *
- * This function has been replaced by access_ok().
- *
- * Checks if a pointer to a block of memory in user space is valid.
- *
- * Returns zero if the memory block may be valid, -EFAULT
- * if it is definitely invalid.
- *
- * See access_ok() for more details.
- */
-static inline int verify_area(int type, const void * addr, unsigned long size)
-{
-       return access_ok(type, addr, size) ? 0 : -EFAULT;
-}
-
 /*
  * put_user: - Write a simple value into user space.
  * @x:   Value to copy to user space.
@@ -150,7 +127,7 @@ static inline int verify_area(int type, const void * addr, unsigned long size)
  * Returns zero on success, or -EFAULT on error.
  */
 #define put_user(x,ptr)        \
-       __put_user_check((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
+       __put_user_check((x),(ptr),sizeof(*(ptr)))
 
 /*
  * get_user: - Get a simple variable from user space.
@@ -170,7 +147,7 @@ static inline int verify_area(int type, const void * addr, unsigned long size)
  * On error, the variable @x is set to zero.
  */
 #define get_user(x,ptr) \
-       __get_user_check((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
+       __get_user_check((x),(ptr),sizeof(*(ptr)))
 
 /*
  * __put_user: - Write a simple value into user space, with less checking.
@@ -192,7 +169,7 @@ static inline int verify_area(int type, const void * addr, unsigned long size)
  * Returns zero on success, or -EFAULT on error.
  */
 #define __put_user(x,ptr) \
-       __put_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
+       __put_user_nocheck((x),(ptr),sizeof(*(ptr)))
 
 /*
  * __get_user: - Get a simple variable from user space, with less checking.
@@ -215,127 +192,122 @@ static inline int verify_area(int type, const void * addr, unsigned long size)
  * On error, the variable @x is set to zero.
  */
 #define __get_user(x,ptr) \
-       __get_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
+       __get_user_nocheck((x),(ptr),sizeof(*(ptr)))
 
 struct __large_struct { unsigned long buf[100]; };
-#define __m(x) (*(struct __large_struct *)(x))
+#define __m(x) (*(struct __large_struct __user *)(x))
 
 /*
  * Yuck.  We need two variants, one for 64bit operation and one
  * for 32 bit mode and old iron.
  */
-#ifdef __mips64
-#define __GET_USER_DW __get_user_asm("ld")
-#else
-#define __GET_USER_DW __get_user_asm_ll32
+#ifdef CONFIG_32BIT
+#define __GET_USER_DW(val, ptr) __get_user_asm_ll32(val, ptr)
+#endif
+#ifdef CONFIG_64BIT
+#define __GET_USER_DW(val, ptr) __get_user_asm(val, "ld", ptr)
 #endif
 
-#define __get_user_nocheck(x,ptr,size)                         \
-({                                                             \
-       long __gu_err;                                          \
-       __typeof(*(ptr)) __gu_val;                              \
-       long __gu_addr;                                         \
-       might_sleep();                                          \
-       __asm__("":"=r" (__gu_val));                            \
-       __gu_addr = (long) (ptr);                               \
-       __asm__("":"=r" (__gu_err));                            \
-       switch (size) {                                         \
-       case 1: __get_user_asm("lb"); break;                    \
-       case 2: __get_user_asm("lh"); break;                    \
-       case 4: __get_user_asm("lw"); break;                    \
-       case 8: __GET_USER_DW; break;                           \
-       default: __get_user_unknown(); break;                   \
-       } x = (__typeof__(*(ptr))) __gu_val; __gu_err;          \
-})
+extern void __get_user_unknown(void);
 
-#define __get_user_check(x,ptr,size)                                   \
+#define __get_user_common(val, size, ptr)                              \
+do {                                                                   \
+       switch (size) {                                                 \
+       case 1: __get_user_asm(val, "lb", ptr); break;                  \
+       case 2: __get_user_asm(val, "lh", ptr); break;                  \
+       case 4: __get_user_asm(val, "lw", ptr); break;                  \
+       case 8: __GET_USER_DW(val, ptr); break;                         \
+       default: __get_user_unknown(); break;                           \
+       }                                                               \
+} while (0)
+
+#define __get_user_nocheck(x,ptr,size)                                 \
 ({                                                                     \
        long __gu_err;                                                  \
-       __typeof__(*(ptr)) __gu_val;                                    \
-       long __gu_addr;                                                 \
-       might_sleep();                                                  \
-       __asm__("":"=r" (__gu_val));                                    \
-       __gu_addr = (long) (ptr);                                       \
-       __asm__("":"=r" (__gu_err));                                    \
-       if (access_ok(VERIFY_READ,__gu_addr,size)) {                    \
-               switch (size) {                                         \
-               case 1: __get_user_asm("lb"); break;                    \
-               case 2: __get_user_asm("lh"); break;                    \
-               case 4: __get_user_asm("lw"); break;                    \
-               case 8: __GET_USER_DW; break;                           \
-               default: __get_user_unknown(); break;                   \
-               }                                                       \
-       } x = (__typeof__(*(ptr))) __gu_val; __gu_err;                  \
+                                                                       \
+       __get_user_common((x), size, ptr);                              \
+       __gu_err;                                                       \
 })
 
-#define __get_user_asm(insn)                                           \
+#define __get_user_check(x,ptr,size)                                   \
 ({                                                                     \
-       __asm__ __volatile__(                                           \
-       "1:\t" insn "\t%1,%2\n\t"                                       \
-       "move\t%0,$0\n"                                                 \
-       "2:\n\t"                                                        \
-       ".section\t.fixup,\"ax\"\n"                                     \
-       "3:\tli\t%0,%3\n\t"                                             \
-       "move\t%1,$0\n\t"                                               \
-       "j\t2b\n\t"                                                     \
-       ".previous\n\t"                                                 \
-       ".section\t__ex_table,\"a\"\n\t"                                \
-       __UA_ADDR "\t1b,3b\n\t"                                         \
-       ".previous"                                                     \
-       :"=r" (__gu_err), "=r" (__gu_val)                               \
-       :"o" (__m(__gu_addr)), "i" (-EFAULT));                          \
+       long __gu_err = -EFAULT;                                        \
+       const __typeof__(*(ptr)) __user * __gu_ptr = (ptr);             \
+                                                                       \
+       if (likely(access_ok(VERIFY_READ,  __gu_ptr, size)))            \
+               __get_user_common((x), size, __gu_ptr);                 \
+                                                                       \
+       __gu_err;                                                       \
 })
 
+#define __get_user_asm(val, insn, addr)                                        \
+{                                                                      \
+       long __gu_tmp;                                                  \
+                                                                       \
+       __asm__ __volatile__(                                           \
+       "1:     " insn "        %1, %3                          \n"     \
+       "2:                                                     \n"     \
+       "       .section .fixup,\"ax\"                          \n"     \
+       "3:     li      %0, %4                                  \n"     \
+       "       j       2b                                      \n"     \
+       "       .previous                                       \n"     \
+       "       .section __ex_table,\"a\"                       \n"     \
+       "       "__UA_ADDR "\t1b, 3b                            \n"     \
+       "       .previous                                       \n"     \
+       : "=r" (__gu_err), "=r" (__gu_tmp)                              \
+       : "0" (0), "o" (__m(addr)), "i" (-EFAULT));                     \
+                                                                       \
+       (val) = (__typeof__(*(addr))) __gu_tmp;                         \
+}
+
 /*
  * Get a long long 64 using 32 bit registers.
  */
-#define __get_user_asm_ll32                                            \
-({                                                                     \
+#define __get_user_asm_ll32(val, addr)                                 \
+{                                                                      \
+        unsigned long long __gu_tmp;                                   \
+                                                                       \
        __asm__ __volatile__(                                           \
-       "1:\tlw\t%1,%2\n"                                               \
-       "2:\tlw\t%D1,%3\n\t"                                            \
-       "move\t%0,$0\n"                                                 \
-       "3:\t.section\t.fixup,\"ax\"\n"                                 \
-       "4:\tli\t%0,%4\n\t"                                             \
-       "move\t%1,$0\n\t"                                               \
-       "move\t%D1,$0\n\t"                                              \
-       "j\t3b\n\t"                                                     \
-       ".previous\n\t"                                                 \
-       ".section\t__ex_table,\"a\"\n\t"                                \
-       __UA_ADDR "\t1b,4b\n\t"                                         \
-       __UA_ADDR "\t2b,4b\n\t"                                         \
-       ".previous"                                                     \
-       :"=r" (__gu_err), "=&r" (__gu_val)                              \
-       :"o" (__m(__gu_addr)), "o" (__m(__gu_addr + 4)),                \
-        "i" (-EFAULT));                                                \
-})
-
-extern void __get_user_unknown(void);
+       "1:     lw      %1, (%3)                                \n"     \
+       "2:     lw      %D1, 4(%3)                              \n"     \
+       "       move    %0, $0                                  \n"     \
+       "3:     .section        .fixup,\"ax\"                   \n"     \
+       "4:     li      %0, %4                                  \n"     \
+       "       move    %1, $0                                  \n"     \
+       "       move    %D1, $0                                 \n"     \
+       "       j       3b                                      \n"     \
+       "       .previous                                       \n"     \
+       "       .section        __ex_table,\"a\"                \n"     \
+       "       " __UA_ADDR "   1b, 4b                          \n"     \
+       "       " __UA_ADDR "   2b, 4b                          \n"     \
+       "       .previous                                       \n"     \
+       : "=r" (__gu_err), "=&r" (__gu_tmp)                             \
+       : "0" (0), "r" (addr), "i" (-EFAULT));                          \
+       (val) = (__typeof__(*(addr))) __gu_tmp;                         \
+}
 
 /*
  * Yuck.  We need two variants, one for 64bit operation and one
  * for 32 bit mode and old iron.
  */
-#ifdef __mips64
-#define __PUT_USER_DW __put_user_asm("sd")
-#else
-#define __PUT_USER_DW __put_user_asm_ll32
+#ifdef CONFIG_32BIT
+#define __PUT_USER_DW(ptr) __put_user_asm_ll32(ptr)
+#endif
+#ifdef CONFIG_64BIT
+#define __PUT_USER_DW(ptr) __put_user_asm("sd", ptr)
 #endif
 
 #define __put_user_nocheck(x,ptr,size)                                 \
 ({                                                                     \
-       long __pu_err;                                                  \
        __typeof__(*(ptr)) __pu_val;                                    \
-       long __pu_addr;                                                 \
-       might_sleep();                                                  \
+       long __pu_err = 0;                                              \
+                                                                       \
        __pu_val = (x);                                                 \
-       __pu_addr = (long) (ptr);                                       \
-       __asm__("":"=r" (__pu_err));                                    \
        switch (size) {                                                 \
-       case 1: __put_user_asm("sb"); break;                            \
-       case 2: __put_user_asm("sh"); break;                            \
-       case 4: __put_user_asm("sw"); break;                            \
-       case 8: __PUT_USER_DW; break;                                   \
+       case 1: __put_user_asm("sb", ptr); break;                       \
+       case 2: __put_user_asm("sh", ptr); break;                       \
+       case 4: __put_user_asm("sw", ptr); break;                       \
+       case 8: __PUT_USER_DW(ptr); break;                              \
        default: __put_user_unknown(); break;                           \
        }                                                               \
        __pu_err;                                                       \
@@ -343,61 +315,57 @@ extern void __get_user_unknown(void);
 
 #define __put_user_check(x,ptr,size)                                   \
 ({                                                                     \
-       long __pu_err;                                                  \
-       __typeof__(*(ptr)) __pu_val;                                    \
-       long __pu_addr;                                                 \
-       might_sleep();                                                  \
-       __pu_val = (x);                                                 \
-       __pu_addr = (long) (ptr);                                       \
-       __asm__("":"=r" (__pu_err));                                    \
-       if (access_ok(VERIFY_WRITE, __pu_addr, size)) {                 \
+       __typeof__(*(ptr)) __user *__pu_addr = (ptr);                   \
+       __typeof__(*(ptr)) __pu_val = (x);                              \
+       long __pu_err = -EFAULT;                                        \
+                                                                       \
+       if (likely(access_ok(VERIFY_WRITE,  __pu_addr, size))) {        \
                switch (size) {                                         \
-               case 1: __put_user_asm("sb"); break;                    \
-               case 2: __put_user_asm("sh"); break;                    \
-               case 4: __put_user_asm("sw"); break;                    \
-               case 8: __PUT_USER_DW; break;                           \
+               case 1: __put_user_asm("sb", __pu_addr); break;         \
+               case 2: __put_user_asm("sh", __pu_addr); break;         \
+               case 4: __put_user_asm("sw", __pu_addr); break;         \
+               case 8: __PUT_USER_DW(__pu_addr); break;                \
                default: __put_user_unknown(); break;                   \
                }                                                       \
        }                                                               \
        __pu_err;                                                       \
 })
 
-#define __put_user_asm(insn)                                           \
-({                                                                     \
+#define __put_user_asm(insn, ptr)                                      \
+                                                                     \
        __asm__ __volatile__(                                           \
-       "1:\t" insn "\t%z1, %2\t\t\t# __put_user_asm\n\t"               \
-       "move\t%0, $0\n"                                                \
-       "2:\n\t"                                                        \
-       ".section\t.fixup,\"ax\"\n"                                     \
-       "3:\tli\t%0,%3\n\t"                                             \
-       "j\t2b\n\t"                                                     \
-       ".previous\n\t"                                                 \
-       ".section\t__ex_table,\"a\"\n\t"                                \
-       __UA_ADDR "\t1b,3b\n\t"                                         \
-       ".previous"                                                     \
-       :"=r" (__pu_err)                                                \
-       :"Jr" (__pu_val), "o" (__m(__pu_addr)), "i" (-EFAULT));         \
-})
+       "1:     " insn "        %z2, %3         # __put_user_asm\n"     \
+       "2:                                                     \n"     \
+       "       .section        .fixup,\"ax\"                   \n"     \
+       "3:     li      %0, %4                                  \n"     \
+       "       j       2b                                      \n"     \
+       "       .previous                                       \n"     \
+       "       .section        __ex_table,\"a\"                \n"     \
+       "       " __UA_ADDR "   1b, 3b                          \n"     \
+       "       .previous                                       \n"     \
+       : "=r" (__pu_err)                                               \
+       : "0" (0), "Jr" (__pu_val), "o" (__m(ptr)),                     \
+         "i" (-EFAULT));                                               \
+}
 
-#define __put_user_asm_ll32                                            \
-({                                                                     \
+#define __put_user_asm_ll32(ptr)                                       \
+                                                                     \
        __asm__ __volatile__(                                           \
-       "1:\tsw\t%1, %2\t\t\t# __put_user_asm_ll32\n\t"                 \
-       "2:\tsw\t%D1, %3\n"                                             \
-       "move\t%0, $0\n"                                                \
-       "3:\n\t"                                                        \
-       ".section\t.fixup,\"ax\"\n"                                     \
-       "4:\tli\t%0,%4\n\t"                                             \
-       "j\t3b\n\t"                                                     \
-       ".previous\n\t"                                                 \
-       ".section\t__ex_table,\"a\"\n\t"                                \
-       __UA_ADDR "\t1b,4b\n\t"                                         \
-       __UA_ADDR "\t2b,4b\n\t"                                         \
-       ".previous"                                                     \
-       :"=r" (__pu_err)                                                \
-       :"r" (__pu_val), "o" (__m(__pu_addr)),                          \
-        "o" (__m(__pu_addr + 4)), "i" (-EFAULT));                      \
-})
+       "1:     sw      %2, (%3)        # __put_user_asm_ll32   \n"     \
+       "2:     sw      %D2, 4(%3)                              \n"     \
+       "3:                                                     \n"     \
+       "       .section        .fixup,\"ax\"                   \n"     \
+       "4:     li      %0, %4                                  \n"     \
+       "       j       3b                                      \n"     \
+       "       .previous                                       \n"     \
+       "       .section        __ex_table,\"a\"                \n"     \
+       "       " __UA_ADDR "   1b, 4b                          \n"     \
+       "       " __UA_ADDR "   2b, 4b                          \n"     \
+       "       .previous"                                              \
+       : "=r" (__pu_err)                                               \
+       : "0" (0), "r" (__pu_val), "r" (ptr),                           \
+         "i" (-EFAULT));                                               \
+}
 
 extern void __put_user_unknown(void);
 
@@ -420,7 +388,7 @@ extern size_t __copy_user(void *__to, const void *__from, size_t __n);
 
 #define __invoke_copy_to_user(to,from,n)                               \
 ({                                                                     \
-       register void *__cu_to_r __asm__ ("$4");                        \
+       register void __user *__cu_to_r __asm__ ("$4");                 \
        register const void *__cu_from_r __asm__ ("$5");                \
        register long __cu_len_r __asm__ ("$6");                        \
                                                                        \
@@ -452,7 +420,7 @@ extern size_t __copy_user(void *__to, const void *__from, size_t __n);
  */
 #define __copy_to_user(to,from,n)                                      \
 ({                                                                     \
-       void *__cu_to;                                                  \
+       void __user *__cu_to;                                           \
        const void *__cu_from;                                          \
        long __cu_len;                                                  \
                                                                        \
@@ -482,7 +450,7 @@ extern size_t __copy_user(void *__to, const void *__from, size_t __n);
  */
 #define copy_to_user(to,from,n)                                                \
 ({                                                                     \
-       void *__cu_to;                                                  \
+       void __user *__cu_to;                                           \
        const void *__cu_from;                                          \
        long __cu_len;                                                  \
                                                                        \
@@ -499,7 +467,7 @@ extern size_t __copy_user(void *__to, const void *__from, size_t __n);
 #define __invoke_copy_from_user(to,from,n)                             \
 ({                                                                     \
        register void *__cu_to_r __asm__ ("$4");                        \
-       register const void *__cu_from_r __asm__ ("$5");                \
+       register const void __user *__cu_from_r __asm__ ("$5");         \
        register long __cu_len_r __asm__ ("$6");                        \
                                                                        \
        __cu_to_r = (to);                                               \
@@ -511,8 +479,7 @@ extern size_t __copy_user(void *__to, const void *__from, size_t __n);
        ".set\tnoat\n\t"                                                \
        __UA_ADDU "\t$1, %1, %2\n\t"                                    \
        ".set\tat\n\t"                                                  \
-       ".set\treorder\n\t"                                             \
-       "move\t%0, $6"          /* XXX */                               \
+       ".set\treorder"                                                 \
        : "+r" (__cu_to_r), "+r" (__cu_from_r), "+r" (__cu_len_r)       \
        :                                                               \
        : "$8", "$9", "$10", "$11", "$12", "$15", "$24", "$31",         \
@@ -539,7 +506,7 @@ extern size_t __copy_user(void *__to, const void *__from, size_t __n);
 #define __copy_from_user(to,from,n)                                    \
 ({                                                                     \
        void *__cu_to;                                                  \
-       const void *__cu_from;                                          \
+       const void __user *__cu_from;                                   \
        long __cu_len;                                                  \
                                                                        \
        might_sleep();                                                  \
@@ -570,7 +537,7 @@ extern size_t __copy_user(void *__to, const void *__from, size_t __n);
 #define copy_from_user(to,from,n)                                      \
 ({                                                                     \
        void *__cu_to;                                                  \
-       const void *__cu_from;                                          \
+       const void __user *__cu_from;                                   \
        long __cu_len;                                                  \
                                                                        \
        might_sleep();                                                  \
@@ -587,8 +554,8 @@ extern size_t __copy_user(void *__to, const void *__from, size_t __n);
 
 #define copy_in_user(to,from,n)                                                \
 ({                                                                     \
-       void *__cu_to;                                                  \
-       const void *__cu_from;                                          \
+       void __user *__cu_to;                                           \
+       const void __user *__cu_from;                                   \
        long __cu_len;                                                  \
                                                                        \
        might_sleep();                                                  \
@@ -614,7 +581,7 @@ extern size_t __copy_user(void *__to, const void *__from, size_t __n);
  * On success, this will be zero.
  */
 static inline __kernel_size_t
-__clear_user(void *addr, __kernel_size_t size)
+__clear_user(void __user *addr, __kernel_size_t size)
 {
        __kernel_size_t res;
 
@@ -634,7 +601,7 @@ __clear_user(void *addr, __kernel_size_t size)
 
 #define clear_user(addr,n)                                             \
 ({                                                                     \
-       void * __cl_addr = (addr);                                      \
+       void __user * __cl_addr = (addr);                               \
        unsigned long __cl_size = (n);                                  \
        if (__cl_size && access_ok(VERIFY_WRITE,                        \
                ((unsigned long)(__cl_addr)), __cl_size))               \
@@ -663,7 +630,7 @@ __clear_user(void *addr, __kernel_size_t size)
  * and returns @count.
  */
 static inline long
-__strncpy_from_user(char *__to, const char *__from, long __len)
+__strncpy_from_user(char *__to, const char __user *__from, long __len)
 {
        long res;
 
@@ -700,7 +667,7 @@ __strncpy_from_user(char *__to, const char *__from, long __len)
  * and returns @count.
  */
 static inline long
-strncpy_from_user(char *__to, const char *__from, long __len)
+strncpy_from_user(char *__to, const char __user *__from, long __len)
 {
        long res;
 
@@ -719,7 +686,7 @@ strncpy_from_user(char *__to, const char *__from, long __len)
 }
 
 /* Returns: 0 if bad, string length+1 (memory size) of string if ok */
-static inline long __strlen_user(const char *s)
+static inline long __strlen_user(const char __user *s)
 {
        long res;
 
@@ -749,7 +716,7 @@ static inline long __strlen_user(const char *s)
  * If there is a limit on the length of a valid string, you may wish to
  * consider using strnlen_user() instead.
  */
-static inline long strlen_user(const char *s)
+static inline long strlen_user(const char __user *s)
 {
        long res;
 
@@ -766,7 +733,7 @@ static inline long strlen_user(const char *s)
 }
 
 /* Returns: 0 if bad, string length+1 (memory size) of string if ok */
-static inline long __strnlen_user(const char *s, long n)
+static inline long __strnlen_user(const char __user *s, long n)
 {
        long res;
 
@@ -797,7 +764,7 @@ static inline long __strnlen_user(const char *s, long n)
  * If there is a limit on the length of a valid string, you may wish to
  * consider using strnlen_user() instead.
  */
-static inline long strnlen_user(const char *s, long n)
+static inline long strnlen_user(const char __user *s, long n)
 {
        long res;