diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-10-19 21:42:00 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-10-19 21:42:00 +0000 |
commit | 794d6411d976253c1761e3dcc0008bd63f79dc99 (patch) | |
tree | cf9bdbd07ac3ed6e0d8a875d869cc2ff0f8f34f1 /arch/mips64/kernel | |
parent | 69ec55a8553c83add3eafe0e2bf0305f2219ca6a (diff) |
Fix sysmips32(MIPS_ATOMIC_SET, ...). In case of a page fault on SMP
this might freeze the entire machine which killed my work several
times ...
Diffstat (limited to 'arch/mips64/kernel')
-rw-r--r-- | arch/mips64/kernel/syscall.c | 44 |
1 files changed, 35 insertions, 9 deletions
diff --git a/arch/mips64/kernel/syscall.c b/arch/mips64/kernel/syscall.c index a69558792..8b36b6e5e 100644 --- a/arch/mips64/kernel/syscall.c +++ b/arch/mips64/kernel/syscall.c @@ -31,6 +31,8 @@ #include <asm/sysmips.h> #include <asm/uaccess.h> +extern asmlinkage void syscall_trace(void); + asmlinkage int sys_pipe(abi64_no_regargs, struct pt_regs regs) { int fd[2]; @@ -131,7 +133,7 @@ sys_sysmips(int cmd, long arg1, int arg2, int arg3) { int *p; char *name; - int flags, tmp, len, errno; + int tmp, len, errno; switch(cmd) { case SETNAME: { @@ -154,8 +156,6 @@ sys_sysmips(int cmd, long arg1, int arg2, int arg3) } case MIPS_ATOMIC_SET: { - /* This is broken in case of page faults and SMP ... - Risc/OS faults after maximum 20 tries with EAGAIN. */ unsigned int tmp; p = (int *) arg1; @@ -163,15 +163,41 @@ sys_sysmips(int cmd, long arg1, int arg2, int arg3) if (errno) return errno; errno = 0; - save_and_cli(flags); - errno |= __get_user(tmp, p); - errno |= __put_user(arg2, p); - restore_flags(flags); + + __asm__(".set\tpush\t\t\t# sysmips(MIPS_ATOMIC, ...)\n\t" + ".set\tnoreorder\n\t" + ".set\tnoat\n\t" + "1:\tll\t%0, %4\n\t" + "2:\tmove\t$1, %3\n\t" + "3:\tsc\t$1, %1\n\t" + "beqzl\t$1, 2b\n\t" + "4:\t ll\t%0, %4\n\t" + ".set\tpop\n\t" + ".section\t.fixup,\"ax\"\n" + "5:\tli\t%2, 1\t\t\t# error\n\t" + ".previous\n\t" + ".section\t__ex_table,\"a\"\n\t" + ".dword\t1b, 5b\n\t" + ".dword\t3b, 5b\n\t" + ".dword\t4b, 5b\n\t" + ".previous\n\t" + : "=&r" (tmp), "=o" (* (u32 *) p), "=r" (errno) + : "r" (arg2), "o" (* (u32 *) p), "2" (errno) + : "$1"); if (errno) - return tmp; + return -EFAULT; + + /* We're skipping error handling etc. */ + if (current->ptrace & PT_TRACESYS) + syscall_trace(); - return tmp; /* This is broken ... */ + __asm__ __volatile__( + "move\t$29, %0\n\t" + "j\tret_from_sys_call" + : /* No outputs */ + : "r" (&cmd)); + /* Unreached */ } case MIPS_FIXADE: |