diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1998-03-17 22:05:47 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1998-03-17 22:05:47 +0000 |
commit | 27cfca1ec98e91261b1a5355d10a8996464b63af (patch) | |
tree | 8e895a53e372fa682b4c0a585b9377d67ed70d0e /arch/i386/lib | |
parent | 6a76fb7214c477ccf6582bd79c5b4ccc4f9c41b1 (diff) |
Look Ma' what I found on my harddisk ...
o New faster syscalls for 2.1.x, too
o Upgrade to 2.1.89.
Don't try to run this. It's flaky as hell. But feel free to debug ...
Diffstat (limited to 'arch/i386/lib')
-rw-r--r-- | arch/i386/lib/.cvsignore | 1 | ||||
-rw-r--r-- | arch/i386/lib/Makefile | 2 | ||||
-rw-r--r-- | arch/i386/lib/checksum.c | 2 | ||||
-rw-r--r-- | arch/i386/lib/delay.c | 8 | ||||
-rw-r--r-- | arch/i386/lib/getuser.S | 73 | ||||
-rw-r--r-- | arch/i386/lib/putuser.S | 71 | ||||
-rw-r--r-- | arch/i386/lib/usercopy.c | 136 |
7 files changed, 284 insertions, 9 deletions
diff --git a/arch/i386/lib/.cvsignore b/arch/i386/lib/.cvsignore index 4671378ae..857dd22e9 100644 --- a/arch/i386/lib/.cvsignore +++ b/arch/i386/lib/.cvsignore @@ -1 +1,2 @@ .depend +.*.flags diff --git a/arch/i386/lib/Makefile b/arch/i386/lib/Makefile index 6b76e32d6..a4e4b1486 100644 --- a/arch/i386/lib/Makefile +++ b/arch/i386/lib/Makefile @@ -11,6 +11,6 @@ else endif L_TARGET = lib.a -L_OBJS = checksum.o semaphore.o locks.o delay.o +L_OBJS = checksum.o semaphore.o locks.o delay.o usercopy.o getuser.o putuser.o include $(TOPDIR)/Rules.make diff --git a/arch/i386/lib/checksum.c b/arch/i386/lib/checksum.c index 2293a6c5e..88f250d62 100644 --- a/arch/i386/lib/checksum.c +++ b/arch/i386/lib/checksum.c @@ -208,7 +208,7 @@ unsigned int csum_partial_copy_generic (const char *src, char *dst, # Exception handler: ################################################ # -.section .fixup, \"a\" # +.section .fixup, \"ax\" # # 6000: # # diff --git a/arch/i386/lib/delay.c b/arch/i386/lib/delay.c index 4afc206e5..12b6b4683 100644 --- a/arch/i386/lib/delay.c +++ b/arch/i386/lib/delay.c @@ -15,12 +15,6 @@ #include <asm/smp.h> #endif -#ifdef __SMP__ -#define __udelay_val cpu_data[smp_processor_id()].udelay_val -#else -#define __udelay_val loops_per_sec -#endif - void __delay(unsigned long loops) { __asm__ __volatile__( @@ -34,7 +28,7 @@ inline void __const_udelay(unsigned long xloops) { __asm__("mull %0" :"=d" (xloops) - :"a" (xloops),"0" (__udelay_val) + :"a" (xloops),"0" (current_cpu_data.loops_per_sec) :"ax"); __delay(xloops); } diff --git a/arch/i386/lib/getuser.S b/arch/i386/lib/getuser.S new file mode 100644 index 000000000..c244721e7 --- /dev/null +++ b/arch/i386/lib/getuser.S @@ -0,0 +1,73 @@ +/* + * __get_user functions. + * + * (C) Copyright 1998 Linus Torvalds + * + * These functions have a non-standard call interface + * to make them more efficient, especially as they + * return an error value in addition to the "real" + * return value. + */ + +/* + * __get_user_X + * + * Inputs: %eax contains the address + * + * Outputs: %eax is error code (0 or -EFAULT) + * %edx contains zero-extended value + * + * These functions should not modify any other registers, + * as they get called from within inline assembly. + */ + +addr_limit = 12 + +.text +.align 4 +.globl __get_user_1 +__get_user_1: + movl %esp,%edx + andl $0xffffe000,%edx + cmpl addr_limit(%edx),%eax + jae bad_get_user +1: movzbl (%eax),%edx + xorl %eax,%eax + ret + +.align 4 +.globl __get_user_2 +__get_user_2: + addl $1,%eax + movl %esp,%edx + jc bad_get_user + andl $0xffffe000,%edx + cmpl addr_limit(%edx),%eax + jae bad_get_user +2: movzwl -1(%eax),%edx + xorl %eax,%eax + ret + +.align 4 +.globl __get_user_4 +__get_user_4: + addl $3,%eax + movl %esp,%edx + jc bad_get_user + andl $0xffffe000,%edx + cmpl addr_limit(%edx),%eax + jae bad_get_user +3: movl -3(%eax),%edx + xorl %eax,%eax + ret + +bad_get_user: + xorl %edx,%edx + movl $-14,%eax + ret + +.section __ex_table,"a" + .long 1b,bad_get_user + .long 2b,bad_get_user + .long 3b,bad_get_user +.previous diff --git a/arch/i386/lib/putuser.S b/arch/i386/lib/putuser.S new file mode 100644 index 000000000..ee56d83f7 --- /dev/null +++ b/arch/i386/lib/putuser.S @@ -0,0 +1,71 @@ +/* + * __put_user functions. + * + * (C) Copyright 1998 Linus Torvalds + * + * These functions have a non-standard call interface + * to make them more efficient. + */ + +/* + * __put_user_X + * + * Inputs: %eax contains the address + * %edx contains the value + * + * Outputs: %eax is error code (0 or -EFAULT) + * %ecx is corrupted (will contain "current_task"). + * + * These functions should not modify any other registers, + * as they get called from within inline assembly. + */ + +addr_limit = 12 + +.text +.align 4 +.globl __put_user_1 +__put_user_1: + movl %esp,%ecx + andl $0xffffe000,%ecx + cmpl addr_limit(%ecx),%eax + jae bad_put_user +1: movb %dl,(%eax) + xorl %eax,%eax + ret + +.align 4 +.globl __put_user_2 +__put_user_2: + addl $1,%eax + movl %esp,%ecx + jc bad_put_user + andl $0xffffe000,%ecx + cmpl addr_limit(%ecx),%eax + jae bad_put_user +2: movw %dx,-1(%eax) + xorl %eax,%eax + ret + +.align 4 +.globl __put_user_4 +__put_user_4: + addl $3,%eax + movl %esp,%ecx + jc bad_put_user + andl $0xffffe000,%ecx + cmpl addr_limit(%ecx),%eax + jae bad_put_user +3: movl %edx,-3(%eax) + xorl %eax,%eax + ret + +bad_put_user: + movl $-14,%eax + ret + +.section __ex_table,"a" + .long 1b,bad_put_user + .long 2b,bad_put_user + .long 3b,bad_put_user +.previous diff --git a/arch/i386/lib/usercopy.c b/arch/i386/lib/usercopy.c new file mode 100644 index 000000000..6b313d99c --- /dev/null +++ b/arch/i386/lib/usercopy.c @@ -0,0 +1,136 @@ +/* + * User address space access functions. + * The non inlined parts of asm-i386/uaccess.h are here. + * + * Copyright 1997 Andi Kleen <ak@muc.de> + * Copyright 1997 Linus Torvalds + */ +#include <asm/uaccess.h> + +inline 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; +} + +inline unsigned long +__generic_copy_from_user(void *to, const void *from, unsigned long n) +{ + if (access_ok(VERIFY_READ, from, n)) + __copy_user(to,from,n); + return n; +} + + +/* + * Copy a null terminated string from userspace. + */ + +#define __do_strncpy_from_user(dst,src,count,res) \ + __asm__ __volatile__( \ + " testl %1,%1\n" \ + " jz 2f\n" \ + "0: lodsb\n" \ + " stosb\n" \ + " testb %%al,%%al\n" \ + " jz 1f\n" \ + " decl %1\n" \ + " jnz 0b\n" \ + "1: subl %1,%0\n" \ + "2:\n" \ + ".section .fixup,\"ax\"\n" \ + "3: movl %2,%0\n" \ + " jmp 2b\n" \ + ".previous\n" \ + ".section __ex_table,\"a\"\n" \ + " .align 4\n" \ + " .long 0b,3b\n" \ + ".previous" \ + : "=d"(res), "=c"(count) \ + : "i"(-EFAULT), "0"(count), "1"(count), "S"(src), "D"(dst) \ + : "si", "di", "ax", "memory") + +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; +} + + +/* + * Zero Userspace + */ + +#define __do_clear_user(addr,size) \ + __asm__ __volatile__( \ + "0: rep; stosl\n" \ + " movl %1,%0\n" \ + "1: rep; stosb\n" \ + "2:\n" \ + ".section .fixup,\"ax\"\n" \ + "3: lea 0(%1,%0,4),%0\n" \ + " jmp 2b\n" \ + ".previous\n" \ + ".section __ex_table,\"a\"\n" \ + " .align 4\n" \ + " .long 0b,3b\n" \ + " .long 1b,2b\n" \ + ".previous" \ + : "=&c"(size) \ + : "r"(size & 3), "0"(size / 4), "D"(addr), "a"(0) \ + : "di") + +unsigned long +clear_user(void *to, unsigned long n) +{ + if (access_ok(VERIFY_WRITE, to, n)) + __do_clear_user(to, n); + return n; +} + +unsigned long +__clear_user(void *to, unsigned long n) +{ + __do_clear_user(to, n); + return n; +} + +/* + * Return the size of a string (including the ending 0) + * + * Return 0 for error + */ + +long strlen_user(const char *s) +{ + unsigned long res; + + __asm__ __volatile__( + "0: repne; scasb\n" + " notl %0\n" + "1:\n" + ".section .fixup,\"ax\"\n" + "2: xorl %0,%0\n" + " jmp 1b\n" + ".previous\n" + ".section __ex_table,\"a\"\n" + " .align 4\n" + " .long 0b,2b\n" + ".previous" + :"=c" (res), "=D" (s) + :"1" (s), "a" (0), "0" (-__addr_ok(s))); + return res & -__addr_ok(s); +} |