diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1997-09-12 23:25:15 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1997-09-12 23:25:15 +0000 |
commit | 0c9824af05b775b18bff274f3a07d174c718bae1 (patch) | |
tree | 4890f863496f44ef27897017d7c1ac3feadba770 /arch/mips/kernel/signal.c | |
parent | e8ad72aaaa65930e821f72c4b568219f8392ba7b (diff) |
- Set caching mode for KSEG0 to cached-noncoherent for all machines.
On some MIPS boxes the firmware doesn't do that for us.
- We still had two unprotected loads in the sys_sigrestore(2). Use
__get_user().
- Handle QED-style L1 caches != 16kb per cache correctly.
- Protect the cacheflush instructions for the signal trampoline
just like the loads in __get_user(). Otherwise the following
code will result in a nice "Can not handle kernel paging request"
message:
#include <signal.h>
static void hurz(void)
{
}
main()
{
signal(SIGSEGV, hurz);
/* Chainsaw the stack pointer ... */
asm("move $29,%0" : :"r"(0x70000000));
*(int *) 8 = 0;
}
With the fix applied I still get the error message. The cause of
this problem is that gas produces an __ex_table section with wrong
contents. Oh well, how good that I have a nice working post 2.8.1
binutils version at home in good ol' Germany ...
Diffstat (limited to 'arch/mips/kernel/signal.c')
-rw-r--r-- | arch/mips/kernel/signal.c | 44 |
1 files changed, 18 insertions, 26 deletions
diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c index b2e76e8a7..4ff1a98b4 100644 --- a/arch/mips/kernel/signal.c +++ b/arch/mips/kernel/signal.c @@ -4,7 +4,7 @@ * Copyright (C) 1991, 1992 Linus Torvalds * Copyright (C) 1994, 1995, 1996 Ralf Baechle * - * $Id: signal.c,v 1.4 1997/08/06 19:15:07 miguel Exp $ + * $Id: signal.c,v 1.5 1997/09/12 01:30:24 ralf Exp $ */ #include <linux/config.h> #include <linux/sched.h> @@ -64,6 +64,8 @@ asmlinkage int sys_sigsuspend(struct pt_regs *regs) asmlinkage int sys_sigreturn(struct pt_regs *regs) { struct sigcontext *context; + unsigned long blocked; + long long reg; int i; context = (struct sigcontext *)(long) regs->regs[29]; @@ -71,36 +73,26 @@ asmlinkage int sys_sigreturn(struct pt_regs *regs) (regs->regs[29] & (SZREG - 1))) goto badframe; - current->blocked = context->sc_sigset & _BLOCKABLE; /* XXX */ - regs->cp0_epc = context->sc_pc; /* XXX */ + __get_user(blocked, &context->sc_sigset); + current->blocked = blocked & _BLOCKABLE; + __get_user(regs->cp0_epc, &context->sc_pc); -/* - * Disabled because we only use the lower 32 bit of the registers. - */ -#if 0 /* - * We only allow user processes in 64bit mode (n32, 64 bit ABI) to - * restore the upper half of registers. + * Restore all integer registers. */ - if (read_32bit_cp0_register(CP0_STATUS) & ST0_UX) { - for(i = 31;i >= 0;i--) - __get_user(regs->regs[i], &context->sc_regs[i]); - __get_user(regs->hi, &context->sc_mdhi); - __get_user(regs->lo, &context->sc_mdlo); - } else -#endif - { - long long reg; - for(i = 31;i >= 0;i--) { - __get_user(reg, &context->sc_regs[i]); - regs->regs[i] = (int) reg; - } - __get_user(reg, &context->sc_mdhi); - regs->hi = (int) reg; - __get_user(reg, &context->sc_mdlo); - regs->lo = (int) reg; + for(i = 31;i >= 0;i--) { + __get_user(reg, &context->sc_regs[i]); + regs->regs[i] = (int) reg; } + __get_user(reg, &context->sc_mdhi); + regs->hi = (int) reg; + __get_user(reg, &context->sc_mdlo); + regs->lo = (int) reg; + /* + * FP depends on what FPU in what mode we have. Best done in + * Assembler ... + */ restore_fp_context(context); /* |