summaryrefslogtreecommitdiffstats
path: root/arch/mips/kernel/signal.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1997-09-12 23:25:15 +0000
committerRalf Baechle <ralf@linux-mips.org>1997-09-12 23:25:15 +0000
commit0c9824af05b775b18bff274f3a07d174c718bae1 (patch)
tree4890f863496f44ef27897017d7c1ac3feadba770 /arch/mips/kernel/signal.c
parente8ad72aaaa65930e821f72c4b568219f8392ba7b (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.c44
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);
/*