summaryrefslogtreecommitdiffstats
path: root/include/asm-mips/uaccess.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/asm-mips/uaccess.h')
-rw-r--r--include/asm-mips/uaccess.h247
1 files changed, 182 insertions, 65 deletions
diff --git a/include/asm-mips/uaccess.h b/include/asm-mips/uaccess.h
index 42a7df686..8b139fe23 100644
--- a/include/asm-mips/uaccess.h
+++ b/include/asm-mips/uaccess.h
@@ -5,16 +5,15 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (C) 1996, 1997 by Ralf Baechle
+ * Copyright (C) 1996, 1997, 1998 by Ralf Baechle
*
- * $Id: uaccess.h,v 1.7 1998/03/21 08:04:33 ralf Exp $
+ * $Id: uaccess.h,v 1.15 1998/05/03 11:13:54 ralf Exp $
*/
#ifndef __ASM_MIPS_UACCESS_H
#define __ASM_MIPS_UACCESS_H
#include <linux/errno.h>
#include <linux/sched.h>
-#include <asm/asm.h>
#define STR(x) __STR(x)
#define __STR(x) #x
@@ -32,11 +31,9 @@
#define VERIFY_READ 0
#define VERIFY_WRITE 1
-extern mm_segment_t active_ds;
-
-#define get_fs() (active_ds)
+#define get_fs() (current->tss.current_ds)
#define get_ds() (KERNEL_DS)
-#define set_fs(x) (active_ds=(x))
+#define set_fs(x) (current->tss.current_ds=(x))
#define segment_eq(a,b) ((a).seg == (b).seg)
@@ -107,24 +104,6 @@ if (__get_user(x,ptr)) return ret; })
struct __large_struct { unsigned long buf[100]; };
#define __m(x) (*(struct __large_struct *)(x))
-#define copy_to_user(to,from,n) __copy_tofrom_user((to),(from),(n),__cu_to)
-#define copy_from_user(to,from,n) __copy_tofrom_user((to),(from),(n),__cu_from)
-
-extern size_t __copy_user(void *__to, const void *__from, size_t __n);
-
-#define __copy_tofrom_user(to,from,n,v) ({ \
- void * __cu_to; \
- const void * __cu_from; \
- long __cu_len; \
- \
- __cu_to = (to); \
- __cu_from = (from); \
- __cu_len = (n); \
- if (__access_ok(((unsigned long)(v)),__cu_len,__access_mask)) \
- __cu_len = __copy_user(__cu_to, __cu_from, __cu_len); \
- __cu_len; \
-})
-
/*
* Yuck. We need two variants, one for 64bit operation and one
* for 32 bit mode and old iron.
@@ -174,10 +153,11 @@ __asm__ __volatile__( \
"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" \
- STR(PTR)"\t1b,3b\n\t" \
+ ".word\t1b,3b\n\t" \
".previous" \
:"=r" (__gu_err), "=r" (__gu_val) \
:"o" (__m(__gu_addr)), "i" (-EFAULT)); })
@@ -193,11 +173,13 @@ __asm__ __volatile__( \
"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" \
- STR(PTR)"\t1b,4b\n\t" \
- STR(PTR)"\t2b,4b\n\t" \
+ ".word\t1b,4b\n\t" \
+ ".word\t2b,4b\n\t" \
".previous" \
:"=r" (__gu_err), "=&r" (__gu_val) \
:"o" (__m(__gu_addr)), "o" (__m(__gu_addr + 4)), \
@@ -257,7 +239,7 @@ __asm__ __volatile__( \
"j\t2b\n\t" \
".previous\n\t" \
".section\t__ex_table,\"a\"\n\t" \
- STR(PTR)"\t1b,3b\n\t" \
+ ".word\t1b,3b\n\t" \
".previous" \
:"=r" (__pu_err) \
:"r" (__pu_val), "o" (__m(__pu_addr)), "i" (-EFAULT)); })
@@ -274,8 +256,8 @@ __asm__ __volatile__( \
"j\t3b\n\t" \
".previous\n\t" \
".section\t__ex_table,\"a\"\n\t" \
- STR(PTR)"\t1b,4b\n\t" \
- STR(PTR)"\t2b,4b\n\t" \
+ ".word\t1b,4b\n\t" \
+ ".word\t2b,4b\n\t" \
".previous" \
:"=r" (__pu_err) \
:"r" (__pu_val), "o" (__m(__pu_addr)), "o" (__m(__pu_addr + 4)), \
@@ -293,60 +275,195 @@ if (copy_from_user(to,from,n)) \
return retval; \
})
-#define __copy_to_user(to,from,n) \
- __copy_user((to),(from),(n))
+extern size_t __copy_user(void *__to, const void *__from, size_t __n);
-#define __copy_from_user(to,from,n) \
- __copy_user((to),(from),(n))
+#define __copy_to_user(to,from,n) ({ \
+ void *__cu_to; \
+ const void *__cu_from; \
+ long __cu_len; \
+ \
+ __cu_to = (to); \
+ __cu_from = (from); \
+ __cu_len = (n); \
+ __asm__ __volatile__( \
+ "move\t$4, %1\n\t" \
+ "move\t$5, %2\n\t" \
+ "move\t$6, %3\n\t" \
+ "jal\t__copy_user\n\t" \
+ "move\t%0, $6" \
+ : "=r" (__cu_len) \
+ : "r" (__cu_to), "r" (__cu_from), "r" (__cu_len) \
+ : "$4", "$5", "$6", "$8", "$9", "$10", "$11", "$12", "$15", \
+ "$24", "$31","memory"); \
+ __cu_len; \
+})
-#define __clear_user(addr,size) \
-({ \
- void *__cu_end; \
+#define __copy_from_user(to,from,n) ({ \
+ void *__cu_to; \
+ const void *__cu_from; \
+ long __cu_len; \
+ \
+ __cu_to = (to); \
+ __cu_from = (from); \
+ __cu_len = (n); \
__asm__ __volatile__( \
- ".set\tnoreorder\n\t" \
- "1:\taddiu\t%0,1\n" \
- "bne\t%0,%1,1b\n\t" \
- "sb\t$0,-1(%0)\n\t" \
- "2:\t.set\treorder\n\t" \
- ".section\t.fixup,\"ax\"\n" \
- "3:\tsubu\t%0,1\n\t" \
- "j\t2b\n\t" \
- ".previous\n\t" \
- ".section\t__ex_table,\"a\"\n\t" \
- STR(PTR)"\t1b,3b\n\t" \
- ".previous" \
- :"=r" (addr), "=r" (__cu_end) \
- :"0" (addr), "1" (addr + size), "i" (-EFAULT) \
- :"memory"); \
- size = __cu_end - (addr); \
+ "move\t$4, %1\n\t" \
+ "move\t$5, %2\n\t" \
+ "move\t$6, %3\n\t" \
+ ".set\tnoat\n\t" \
+ "addu\t$1, %2, %3\n\t" \
+ ".set\tat\n\t" \
+ "jal\t__copy_user\n\t" \
+ "move\t%0, $6" \
+ : "=r" (__cu_len) \
+ : "r" (__cu_to), "r" (__cu_from), "r" (__cu_len) \
+ : "$4", "$5", "$6", "$8", "$9", "$10", "$11", "$12", "$15", \
+ "$24", "$31","memory"); \
+ __cu_len; \
+})
+
+#define copy_to_user(to,from,n) ({ \
+ void *__cu_to; \
+ const void *__cu_from; \
+ long __cu_len; \
+ \
+ __cu_to = (to); \
+ __cu_from = (from); \
+ __cu_len = (n); \
+ if (access_ok(VERIFY_WRITE, __cu_to, __cu_len)) \
+ __asm__ __volatile__( \
+ "move\t$4, %1\n\t" \
+ "move\t$5, %2\n\t" \
+ "move\t$6, %3\n\t" \
+ "jal\t__copy_user\n\t" \
+ "move\t%0, $6" \
+ : "=r" (__cu_len) \
+ : "r" (__cu_to), "r" (__cu_from), "r" (__cu_len) \
+ : "$4", "$5", "$6", "$8", "$9", "$10", "$11", "$12", \
+ "$15", "$24", "$31","memory"); \
+ __cu_len; \
+})
+
+#define copy_from_user(to,from,n) ({ \
+ void *__cu_to; \
+ const void *__cu_from; \
+ long __cu_len; \
+ \
+ __cu_to = (to); \
+ __cu_from = (from); \
+ __cu_len = (n); \
+ if (access_ok(VERIFY_READ, __cu_from, __cu_len)) \
+ __asm__ __volatile__( \
+ "move\t$4, %1\n\t" \
+ "move\t$5, %2\n\t" \
+ "move\t$6, %3\n\t" \
+ ".set\tnoat\n\t" \
+ "addu\t$1, %2, %3\n\t" \
+ ".set\tat\n\t" \
+ "jal\t__copy_user\n\t" \
+ "move\t%0, $6" \
+ : "=r" (__cu_len) \
+ : "r" (__cu_to), "r" (__cu_from), "r" (__cu_len) \
+ : "$4", "$5", "$6", "$8", "$9", "$10", "$11", "$12", \
+ "$15", "$24", "$31","memory"); \
+ __cu_len; \
})
+extern inline __kernel_size_t
+__clear_user(void *addr, __kernel_size_t size)
+{
+ __kernel_size_t res;
+
+ __asm__ __volatile__(
+ "move\t$4, %1\n\t"
+ "move\t$5, $0\n\t"
+ "move\t$6, %2\n\t"
+ "jal\t__bzero\n\t"
+ "move\t%0, $6"
+ : "=r" (res)
+ : "r" (addr), "r" (size)
+ : "$4", "$5", "$6", "$8", "$9", "$31");
+
+ return res;
+}
+
#define clear_user(addr,n) ({ \
void * __cl_addr = (addr); \
unsigned long __cl_size = (n); \
if (__cl_size && __access_ok(VERIFY_WRITE, ((unsigned long)(__cl_addr)), __cl_size)) \
-__clear_user(__cl_addr, __cl_size); \
+__cl_size = __clear_user(__cl_addr, __cl_size); \
__cl_size; })
/*
* Returns: -EFAULT if exception before terminator, N if the entire
* buffer filled, else strlen.
*/
-extern long __strncpy_from_user(char *__to, const char *__from, long __to_len);
+extern inline long
+__strncpy_from_user(char *__to, const char *__from, long __len)
+{
+ long res;
+
+ __asm__ __volatile__(
+ "move\t$4, %1\n\t"
+ "move\t$5, %2\n\t"
+ "move\t$6, %3\n\t"
+ "jal\t__strncpy_from_user_nocheck_asm\n\t"
+ "move\t%0, $2"
+ : "=r" (res)
+ : "r" (__to), "r" (__from), "r" (__len)
+ : "$2", "$3", "$4", "$5", "$6", "$8", "$31", "memory");
+
+ return res;
+}
+
+extern inline long
+strncpy_from_user(char *__to, const char *__from, long __len)
+{
+ long res;
+
+ __asm__ __volatile__(
+ "move\t$4, %1\n\t"
+ "move\t$5, %2\n\t"
+ "move\t$6, %3\n\t"
+ "jal\t__strncpy_from_user_asm\n\t"
+ "move\t%0, $2"
+ : "=r" (res)
+ : "r" (__to), "r" (__from), "r" (__len)
+ : "$2", "$3", "$4", "$5", "$6", "$8", "$31", "memory");
+
+ return res;
+}
-#define strncpy_from_user(dest,src,count) ({ \
- const void * __sc_src = (src); \
- long __sc_res = -EFAULT; \
- if (access_ok(VERIFY_READ, __sc_src, 0)) { \
- __sc_res = __strncpy_from_user(dest, __sc_src, count); \
-} __sc_res; })
/* Returns: 0 if bad, string length+1 (memory size) of string if ok */
-extern long __strlen_user(const char *);
+extern inline long __strlen_user(const char *s)
+{
+ long res;
-extern inline long strlen_user(const char *str)
+ __asm__ __volatile__(
+ "move\t$4, %1\n\t"
+ "jal\t__strlen_user_nocheck_asm\n\t"
+ "move\t%0, $2"
+ : "=r" (res)
+ : "r" (s)
+ : "$2", "$4", "$8", "$31");
+
+ return res;
+}
+
+extern inline long strlen_user(const char *s)
{
- return access_ok(VERIFY_READ,str,0) ? __strlen_user(str) : 0;
+ long res;
+
+ __asm__ __volatile__(
+ "move\t$4, %1\n\t"
+ "jal\t__strlen_user_asm\n\t"
+ "move\t%0, $2"
+ : "=r" (res)
+ : "r" (s)
+ : "$2", "$4", "$8", "$31");
+
+ return res;
}
struct exception_table_entry