diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1998-05-04 09:12:48 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1998-05-04 09:12:48 +0000 |
commit | 2e0f55e79c49509b7ff70ff1a10e1e9e90a3dfd4 (patch) | |
tree | 9ff1a23dd500f1c70eb99fcd688d47d38abb0253 /include | |
parent | bbc6b4b59f51131f040a752cbe20a1805db08b0b (diff) |
o New memset. Fastest in town for size > 6 bytes.
o New clear_user.
o Memcpy now efficiently copies the (src^dest)&3 != 0.
o Memmove new correctly deals with overlaps
o Rewrite csum_partial in assembler.
o Rewrte csum_partial_from_user in assembler.
o __copy_user is now integrated with memcpy.
o get_user now returns a zero value on error.
o copy_from_user now clears the destination buffer on error.
o strncpy_user now has a more efficient caller routine.
o strlen_user now has a more efficient caller routines and is faster.
o The unaligned handler is now much cleaner. It's now also save from
interrupt. Some more esotheric bugs fixed as well.
o Don't export bcopy anymore, it's now a inline function.
o Delete ancient junk from the first days of Linux/MIPS.
o Delete dead code in indy_sc.c.
o Including the IDE driver doesn't crash an Indy anymore.
o Eleminate active_ds. We now use current_ds directly in the thread
structure which is faster and threadsafe. Saves almost 2kb on the
kernel.
o Serial console should work again.
Diffstat (limited to 'include')
-rw-r--r-- | include/asm-mips/branch.h | 13 | ||||
-rw-r--r-- | include/asm-mips/ide.h | 76 | ||||
-rw-r--r-- | include/asm-mips/offset.h | 17 | ||||
-rw-r--r-- | include/asm-mips/processor.h | 11 | ||||
-rw-r--r-- | include/asm-mips/stackframe.h | 17 | ||||
-rw-r--r-- | include/asm-mips/string.h | 7 | ||||
-rw-r--r-- | include/asm-mips/system.h | 129 | ||||
-rw-r--r-- | include/asm-mips/uaccess.h | 247 |
8 files changed, 309 insertions, 208 deletions
diff --git a/include/asm-mips/branch.h b/include/asm-mips/branch.h index 08dda213e..d8882cfb1 100644 --- a/include/asm-mips/branch.h +++ b/include/asm-mips/branch.h @@ -5,7 +5,9 @@ * 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: branch.h,v 1.2 1998/04/28 19:37:46 ralf Exp $ */ #include <asm/ptrace.h> @@ -15,12 +17,13 @@ extern inline int delay_slot(struct pt_regs *regs) } extern int __compute_return_epc(struct pt_regs *regs); + extern inline int compute_return_epc(struct pt_regs *regs) { - if (delay_slot(regs)) { - return __compute_return_epc(regs); + if (!delay_slot(regs)) { + regs->cp0_epc += 4; + return 0; } - regs->cp0_epc += 4; - return 0; + return __compute_return_epc(regs); } diff --git a/include/asm-mips/ide.h b/include/asm-mips/ide.h index bda27206d..b54a7657c 100644 --- a/include/asm-mips/ide.h +++ b/include/asm-mips/ide.h @@ -21,40 +21,36 @@ typedef unsigned short ide_ioreg_t; #define ide_sti() sti() +struct ide_ops { + int (*ide_default_irq)(ide_ioreg_t base); + ide_ioreg_t (*ide_default_io_base)(int index); + void (*ide_init_hwif_ports)(ide_ioreg_t *p, ide_ioreg_t base, int *irq); + int (*ide_request_irq)(unsigned int irq, void (*handler)(int, void *, + struct pt_regs *), unsigned long flags, + const char *device, void *dev_id); + void (*ide_free_irq)(unsigned int irq, void *dev_id); + int (*ide_check_region) (ide_ioreg_t from, unsigned int extent); + void (*ide_request_region)(ide_ioreg_t from, unsigned int extent, + const char *name); + void (*ide_release_region)(ide_ioreg_t from, unsigned int extent); +}; + +extern struct ide_ops *ide_ops; + static __inline__ int ide_default_irq(ide_ioreg_t base) { - switch (base) { - case 0x1f0: return 14; - case 0x170: return 15; - case 0x1e8: return 11; - case 0x168: return 10; - default: - return 0; - } + return ide_ops->ide_default_irq(base); } static __inline__ ide_ioreg_t ide_default_io_base(int index) { - switch (index) { - case 0: return 0x1f0; - case 1: return 0x170; - case 2: return 0x1e8; - case 3: return 0x168; - default: - return 0; - } + return ide_ops->ide_default_io_base(index); } -static __inline__ void ide_init_hwif_ports (ide_ioreg_t *p, ide_ioreg_t base, int *irq) +static __inline__ void ide_init_hwif_ports(ide_ioreg_t *p, ide_ioreg_t base, + int *irq) { - ide_ioreg_t port = base; - int i = 8; - - while (i--) - *p++ = port++; - *p++ = base + 0x206; - if (irq != NULL) - *irq = 0; + ide_ops->ide_init_hwif_ports(p, base, irq); } typedef union { @@ -68,38 +64,41 @@ typedef union { } b; } select_t; -static __inline__ int ide_request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *), +static __inline__ int ide_request_irq(unsigned int irq, void (*handler)(int,void *, struct pt_regs *), unsigned long flags, const char *device, void *dev_id) { - return request_irq(irq, handler, flags, device, dev_id); -} + return ide_ops->ide_request_irq(irq, handler, flags, device, dev_id); +} static __inline__ void ide_free_irq(unsigned int irq, void *dev_id) { - free_irq(irq, dev_id); + ide_ops->ide_free_irq(irq, dev_id); } static __inline__ int ide_check_region (ide_ioreg_t from, unsigned int extent) { - return check_region(from, extent); + return ide_ops->ide_check_region(from, extent); } -static __inline__ void ide_request_region (ide_ioreg_t from, unsigned int extent, const char *name) +static __inline__ void ide_request_region(ide_ioreg_t from, + unsigned int extent, const char *name) { - request_region(from, extent, name); + ide_ops->ide_request_region(from, extent, name); } -static __inline__ void ide_release_region (ide_ioreg_t from, unsigned int extent) +static __inline__ void ide_release_region(ide_ioreg_t from, + unsigned int extent) { - release_region(from, extent); + ide_ops->ide_release_region(from, extent); } /* * The following are not needed for the non-m68k ports */ -static __inline__ int ide_ack_intr (ide_ioreg_t status_port, ide_ioreg_t irq_port) +static __inline__ int ide_ack_intr (ide_ioreg_t status_port, + ide_ioreg_t irq_port) { - return(1); + return 1; } static __inline__ void ide_fix_driveid(struct hd_driveid *id) @@ -110,7 +109,10 @@ static __inline__ void ide_release_lock (int *ide_lock) { } -static __inline__ void ide_get_lock (int *ide_lock, void (*handler)(int, void *, struct pt_regs *), void *data) +static __inline__ void ide_get_lock (int *ide_lock, + void (*handler)(int, void *, + struct pt_regs *), + void *data) { } diff --git a/include/asm-mips/offset.h b/include/asm-mips/offset.h index e211de3cc..32deafe7b 100644 --- a/include/asm-mips/offset.h +++ b/include/asm-mips/offset.h @@ -50,7 +50,7 @@ #define TASK_PRIORITY 56 #define TASK_FLAGS 4 #define TASK_SIGPENDING 8 -#define TASK_MM 920 +#define TASK_MM 928 /* MIPS specific thread_struct offsets. */ #define THREAD_REG16 568 @@ -67,13 +67,14 @@ #define THREAD_STATUS 612 #define THREAD_FPU 616 #define THREAD_BVADDR 880 -#define THREAD_ECODE 884 -#define THREAD_TRAPNO 888 -#define THREAD_PGDIR 892 -#define THREAD_MFLAGS 896 -#define THREAD_CURDS 900 -#define THREAD_TRAMP 904 -#define THREAD_OLDCTX 908 +#define THREAD_BUADDR 884 +#define THREAD_ECODE 888 +#define THREAD_TRAPNO 892 +#define THREAD_PGDIR 896 +#define THREAD_MFLAGS 900 +#define THREAD_CURDS 904 +#define THREAD_TRAMP 908 +#define THREAD_OLDCTX 912 /* Linux mm_struct offsets. */ #define MM_COUNT 12 diff --git a/include/asm-mips/processor.h b/include/asm-mips/processor.h index 765208d3e..98d5e6a86 100644 --- a/include/asm-mips/processor.h +++ b/include/asm-mips/processor.h @@ -5,7 +5,7 @@ * written by Ralf Baechle * Modified further for R[236]000 compatibility by Paul M. Antoine * - * $Id: processor.h,v 1.8 1998/03/27 04:47:59 ralf Exp $ + * $Id: processor.h,v 1.13 1998/04/25 05:35:15 ralf Exp $ */ #ifndef __ASM_MIPS_PROCESSOR_H #define __ASM_MIPS_PROCESSOR_H @@ -90,7 +90,7 @@ typedef struct { */ struct thread_struct { /* Saved main processor registers. */ - unsigned long reg16 __attribute__ ((aligned (8))); + unsigned long reg16; unsigned long reg17, reg18, reg19, reg20, reg21, reg22, reg23; unsigned long reg29, reg30, reg31; @@ -98,10 +98,11 @@ struct thread_struct { unsigned long cp0_status; /* Saved fpu/fpu emulator stuff. */ - union mips_fpu_union fpu __attribute__ ((aligned (8))); + union mips_fpu_union fpu; /* Other stuff associated with the thread. */ - unsigned long cp0_badvaddr; + unsigned long cp0_badvaddr; /* Last user fault */ + unsigned long cp0_baduaddr; /* Last kernel fault accessing USEG */ unsigned long error_code; unsigned long trap_no; unsigned long pg_dir; /* used in tlb refill */ @@ -135,7 +136,7 @@ struct thread_struct { /* \ * Other stuff associated with the process \ */ \ - 0, 0, 0, (unsigned long) swapper_pg_dir, \ + 0, 0, 0, 0, (unsigned long) swapper_pg_dir, \ /* \ * For now the default is to fix address errors \ */ \ diff --git a/include/asm-mips/stackframe.h b/include/asm-mips/stackframe.h index e925dcd50..726e82f23 100644 --- a/include/asm-mips/stackframe.h +++ b/include/asm-mips/stackframe.h @@ -3,7 +3,7 @@ * * Copyright (C) 1994, 1995, 1996 by Ralf Baechle and Paul M. Antoine. * - * $Id: stackframe.h,v 1.6 1998/03/26 07:39:21 ralf Exp $ + * $Id: stackframe.h,v 1.7 1998/04/28 19:39:15 ralf Exp $ */ #ifndef __ASM_MIPS_STACKFRAME_H #define __ASM_MIPS_STACKFRAME_H @@ -174,10 +174,6 @@ /* * Move to kernel mode and enable interrupts. * Set cp0 enable bit as sign that we're running on the kernel stack - * - * Note that the mtc0 will be effective on R4000 pipeline stage 7. This - * means that another three instructions will be executed with interrupts - * disabled. Arch/mips/mips3/r4xx0.S makes use of this fact. */ #define STI \ mfc0 t0,CP0_STATUS; \ @@ -186,4 +182,15 @@ xori t0,0x1e; \ mtc0 t0,CP0_STATUS +/* + * Just move to kernel mode and leave interrupts as they are. + * Set cp0 enable bit as sign that we're running on the kernel stack + */ +#define KMODE \ + mfc0 t0,CP0_STATUS; \ + li t1,ST0_CU0|0x1e; \ + or t0,t1; \ + xori t0,0x1e; \ + mtc0 t0,CP0_STATUS + #endif /* __ASM_MIPS_STACKFRAME_H */ diff --git a/include/asm-mips/string.h b/include/asm-mips/string.h index 39e6b445c..7f4bded24 100644 --- a/include/asm-mips/string.h +++ b/include/asm-mips/string.h @@ -7,7 +7,7 @@ * * Copyright (c) 1994, 1995, 1996, 1997 by Ralf Baechle * - * $Id: string.h,v 1.4 1998/03/21 19:31:09 ralf Exp $ + * $Id: string.h,v 1.7 1998/03/25 00:24:10 ralf Exp $ */ #ifndef __ASM_MIPS_STRING_H #define __ASM_MIPS_STRING_H @@ -128,7 +128,10 @@ extern void *memcpy(void *__to, __const__ void *__from, size_t __n); extern void *memmove(void *__dest, __const__ void *__src, size_t __n); #define __HAVE_ARCH_BCOPY -extern char * bcopy(const char * src, char * dest, int count); +extern __inline__ char * bcopy(const char * src, char * dest, int count) +{ + memmove(dest, src, count); +} #define __HAVE_ARCH_MEMSCAN extern __inline__ void *memscan(void *__addr, int __c, size_t __size) diff --git a/include/asm-mips/system.h b/include/asm-mips/system.h index abeaa3343..ab8faf278 100644 --- a/include/asm-mips/system.h +++ b/include/asm-mips/system.h @@ -7,6 +7,8 @@ * * Copyright (C) 1994, 1995 by Ralf Baechle * Modified further for R[236]000 by Paul M. Antoine, 1996 + * + * $Id: system.h,v 1.6 1998/05/03 11:13:54 ralf Exp $ */ #ifndef __ASM_MIPS_SYSTEM_H #define __ASM_MIPS_SYSTEM_H @@ -17,18 +19,18 @@ extern __inline__ void __sti(void) { - __asm__ __volatile__( - ".set\tnoreorder\n\t" - ".set\tnoat\n\t" - "mfc0\t$1,$12\n\t" - "ori\t$1,0x1f\n\t" - "xori\t$1,0x1e\n\t" - "mtc0\t$1,$12\n\t" - ".set\tat\n\t" - ".set\treorder" - : /* no outputs */ - : /* no inputs */ - : "$1", "memory"); + __asm__ __volatile__( + ".set\tnoreorder\n\t" + ".set\tnoat\n\t" + "mfc0\t$1,$12\n\t" + "ori\t$1,0x1f\n\t" + "xori\t$1,0x1e\n\t" + "mtc0\t$1,$12\n\t" + ".set\tat\n\t" + ".set\treorder" + : /* no outputs */ + : /* no inputs */ + : "$1", "memory"); } /* @@ -41,21 +43,21 @@ __sti(void) extern __inline__ void __cli(void) { - __asm__ __volatile__( - ".set\tnoreorder\n\t" - ".set\tnoat\n\t" - "mfc0\t$1,$12\n\t" - "ori\t$1,1\n\t" - "xori\t$1,1\n\t" - "mtc0\t$1,$12\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t" - ".set\tat\n\t" - ".set\treorder" - : /* no outputs */ - : /* no inputs */ - : "$1", "memory"); + __asm__ __volatile__( + ".set\tnoreorder\n\t" + ".set\tnoat\n\t" + "mfc0\t$1,$12\n\t" + "ori\t$1,1\n\t" + "xori\t$1,1\n\t" + "mtc0\t$1,$12\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + ".set\tat\n\t" + ".set\treorder" + : /* no outputs */ + : /* no inputs */ + : "$1", "memory"); } #define __save_flags(x) \ @@ -87,16 +89,16 @@ __asm__ __volatile__( \ extern void __inline__ __restore_flags(int flags) { - __asm__ __volatile__( - ".set\tnoreorder\n\t" - "mtc0\t%0,$12\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t" - ".set\treorder" - : /* no output */ - : "r" (flags) - : "memory"); + __asm__ __volatile__( + ".set\tnoreorder\n\t" + "mtc0\t%0,$12\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + ".set\treorder" + : /* no output */ + : "r" (flags) + : "memory"); } /* @@ -113,7 +115,7 @@ __asm__ __volatile__( \ "# prevent instructions being moved around\n\t" \ ".set\tnoreorder\n\t" \ ".set\treorder" \ - : /* no output */ \ + : /* no output */ \ : /* no input */ \ : "memory") @@ -125,47 +127,12 @@ __asm__ __volatile__( \ extern asmlinkage void (*resume)(void *tsk); #endif /* !defined (__LANGUAGE_ASSEMBLY__) */ -/* - * FIXME: resume() assumes current == prev - */ #define switch_to(prev,next) \ do { \ - prev->tss.current_ds = active_ds; \ - active_ds = next->tss.current_ds; \ - resume(next); \ + resume(next); \ } while(0) /* - * The 8 and 16 bit variants have to disable interrupts temporarily. - * Both are currently unused. - */ -extern __inline__ unsigned long xchg_u8(volatile char * m, unsigned long val) -{ - unsigned long flags, retval; - - save_flags(flags); - cli(); - retval = *m; - *m = val; - restore_flags(flags); - - return retval; -} - -extern __inline__ unsigned long xchg_u16(volatile short * m, unsigned long val) -{ - unsigned long flags, retval; - - save_flags(flags); - cli(); - retval = *m; - *m = val; - restore_flags(flags); - - return retval; -} - -/* * For 32 and 64 bit operands we can take advantage of ll and sc. * FIXME: This doesn't work for R3000 machines. */ @@ -186,8 +153,9 @@ extern __inline__ unsigned long xchg_u32(volatile int * m, unsigned long val) ".set\tat\n\t" ".set\treorder" : "=r" (val), "=r" (m), "=r" (dummy) - : "1" (m), "2" (val)); -#else /* FIXME: Brain-dead approach, but then again, I AM hacking - PMA */ + : "1" (m), "2" (val) + : "memory"); +#else unsigned long flags, retval; save_flags(flags); @@ -218,7 +186,8 @@ extern __inline__ unsigned long xchg_u64(volatile long * m, unsigned long val) ".set\tat\n\t" ".set\treorder" : "=r" (val), "=r" (m), "=r" (dummy) - : "1" (m), "2" (val)); + : "1" (m), "2" (val) + : "memory"); return val; } @@ -239,14 +208,12 @@ extern void __xchg_called_with_bad_pointer(void); static __inline__ unsigned long __xchg(unsigned long x, volatile void * ptr, int size) { switch (size) { - case 1: - return xchg_u8(ptr, x); - case 2: - return xchg_u16(ptr, x); case 4: return xchg_u32(ptr, x); +#if defined(__mips64) case 8: return xchg_u64(ptr, x); +#endif } __xchg_called_with_bad_pointer(); return x; 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 |