diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1998-03-27 04:47:53 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1998-03-27 04:47:53 +0000 |
commit | 36ea5120664550fae6d31f1c6f695e4f8975cb06 (patch) | |
tree | 7b985f066e6fa149027022366b9f3dd92506db24 /arch/mips/kernel/irixsig.c | |
parent | f7f4aaffdad04eb69ab618c771df0416ad04a952 (diff) |
o Speedup syscalls. Now 816ns per syscall. Yes, nanoseconds and goodbye
Pentium :-)
o Little bit smarter handling of unimplemented exceptions.
o Fix FPU context switches.
o Fix reboot / halt. Powerdown in software still doesn't work.
o Fix the fix for handling of return values of interrupted syscalls.
o Handling of the Indy second level cache now works as spec'ed. Purely
cosmentic, this was not causing any problems.
Diffstat (limited to 'arch/mips/kernel/irixsig.c')
-rw-r--r-- | arch/mips/kernel/irixsig.c | 59 |
1 files changed, 31 insertions, 28 deletions
diff --git a/arch/mips/kernel/irixsig.c b/arch/mips/kernel/irixsig.c index 88fca61f2..d0e286def 100644 --- a/arch/mips/kernel/irixsig.c +++ b/arch/mips/kernel/irixsig.c @@ -1,7 +1,9 @@ -/* $Id: irixsig.c,v 1.9 1998/03/17 00:59:35 ralf Exp $ +/* * irixsig.c: WHEEE, IRIX signals! YOW, am I compatable or what?!?! * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * + * $Id: irixsig.c,v 1.11 1998/03/26 07:39:09 ralf Exp $ */ #include <linux/kernel.h> @@ -154,30 +156,27 @@ static inline void handle_signal(unsigned long sig, struct k_sigaction *ka, } } -static inline void syscall_restart(unsigned long r0, unsigned long or2, - unsigned long or7, struct pt_regs *regs, - struct sigaction *sa) +static inline void syscall_restart(struct pt_regs *regs, struct k_sigaction *ka) { - switch(r0) { + switch(regs->regs[0]) { case ERESTARTNOHAND: - no_system_call_restart: - regs->regs[0] = regs->regs[2] = EINTR; + regs->regs[2] = EINTR; break; case ERESTARTSYS: - if(!(sa->sa_flags & SA_RESTART)) - goto no_system_call_restart; + if(!(ka->sa.sa_flags & SA_RESTART)) { + regs->regs[2] = EINTR; + break; + } /* fallthrough */ - case ERESTARTNOINTR: - regs->regs[0] = regs->regs[2] = or2; - regs->regs[7] = or7; - regs->cp0_epc -= 8; + case ERESTARTNOINTR: /* Userland will reload $v0. */ + regs->cp0_epc -= 8; } + + regs->regs[0] = 0; /* Don't deal with this again. */ } asmlinkage int do_irix_signal(sigset_t *oldset, struct pt_regs *regs) { - unsigned long r0 = regs->regs[0]; - unsigned long r7 = regs->orig_reg7; struct k_sigaction *ka; siginfo_t info; @@ -279,8 +278,8 @@ asmlinkage int do_irix_signal(sigset_t *oldset, struct pt_regs *regs) } } - if (r0) - syscall_restart(r0, regs->orig_reg2, r7, regs, &ka->sa); + if (regs->regs[0]) + syscall_restart(regs, ka); /* Whee! Actually deliver the signal. */ handle_signal(signr, ka, &info, oldset, regs); return 1; @@ -291,13 +290,12 @@ asmlinkage int do_irix_signal(sigset_t *oldset, struct pt_regs *regs) * dies here!!! The li instruction, a single machine instruction, * must directly be followed by the syscall instruction. */ - if (r0 && - (regs->regs[2] == ERESTARTNOHAND || - regs->regs[2] == ERESTARTSYS || - regs->regs[2] == ERESTARTNOINTR)) { - regs->regs[0] = regs->regs[2] = regs->orig_reg2; - regs->regs[7] = r7; - regs->cp0_epc -= 8; + if (regs->regs[0]) { + if (regs->regs[2] == ERESTARTNOHAND || + regs->regs[2] == ERESTARTSYS || + regs->regs[2] == ERESTARTNOINTR) { + regs->cp0_epc -= 8; + } } return 0; } @@ -356,10 +354,15 @@ asmlinkage unsigned long irix_sigreturn(struct pt_regs *regs) recalc_sigpending(current); spin_unlock_irq(¤t->sigmask_lock); - regs->orig_reg2 = -1; - __get_user(res, &context->regs[2]); - - return res; + /* + * Don't let your children do this ... + */ + __asm__ __volatile__( + "move\t$29,%0\n\t" + "j\tret_from_sys_call" + :/* no outputs */ + :"r" (®s)); + /* Unreached */ badframe: lock_kernel(); |