diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1997-04-29 21:13:14 +0000 |
---|---|---|
committer | <ralf@linux-mips.org> | 1997-04-29 21:13:14 +0000 |
commit | 19c9bba94152148523ba0f7ef7cffe3d45656b11 (patch) | |
tree | 40b1cb534496a7f1ca0f5c314a523c69f1fee464 /arch/sparc/kernel/traps.c | |
parent | 7206675c40394c78a90e74812bbdbf8cf3cca1be (diff) |
Import of Linux/MIPS 2.1.36
Diffstat (limited to 'arch/sparc/kernel/traps.c')
-rw-r--r-- | arch/sparc/kernel/traps.c | 68 |
1 files changed, 49 insertions, 19 deletions
diff --git a/arch/sparc/kernel/traps.c b/arch/sparc/kernel/traps.c index 798ca3aca..19a3afbd0 100644 --- a/arch/sparc/kernel/traps.c +++ b/arch/sparc/kernel/traps.c @@ -1,4 +1,4 @@ -/* $Id: traps.c,v 1.47 1996/10/27 08:36:17 davem Exp $ +/* $Id: traps.c,v 1.53 1997/01/25 02:43:05 miguel Exp $ * arch/sparc/kernel/traps.c * * Copyright 1995 David S. Miller (davem@caip.rutgers.edu) @@ -10,8 +10,9 @@ #include <linux/sched.h> /* for jiffies */ #include <linux/kernel.h> -#include <linux/config.h> #include <linux/signal.h> +#include <linux/smp.h> +#include <linux/smp_lock.h> #include <asm/delay.h> #include <asm/system.h> @@ -22,7 +23,6 @@ #include <asm/kdebug.h> #include <asm/unistd.h> #include <asm/traps.h> -#include <asm/smp.h> /* #define TRAP_DEBUG */ @@ -85,9 +85,6 @@ void die_if_kernel(char *str, struct pt_regs *regs) printk("%s(%d): %s\n", current->comm, current->pid, str); show_regs(regs); -#if CONFIG_AP1000 - ap_panic(); -#endif printk("Instruction DUMP:"); instruction_dump ((unsigned long *) regs->pc); if(regs->psr & PSR_PS) @@ -97,6 +94,7 @@ void die_if_kernel(char *str, struct pt_regs *regs) void do_hw_interrupt(unsigned long type, unsigned long psr, unsigned long pc) { + lock_kernel(); if(type < 0x80) { /* Sun OS's puke from bad traps, Linux survives! */ printk("Unimplemented Sparc TRAP, type = %02lx\n", type); @@ -105,39 +103,49 @@ void do_hw_interrupt(unsigned long type, unsigned long psr, unsigned long pc) if(type == SP_TRAP_SBPT) { send_sig(SIGTRAP, current, 1); - return; - } - - if(psr & PSR_PS) - die_if_kernel("Kernel bad trap", current->tss.kregs); + } else { + if(psr & PSR_PS) + die_if_kernel("Kernel bad trap", current->tss.kregs); - current->tss.sig_desc = SUBSIG_BADTRAP(type - 0x80); - current->tss.sig_address = pc; - send_sig(SIGILL, current, 1); + current->tss.sig_desc = SUBSIG_BADTRAP(type - 0x80); + current->tss.sig_address = pc; + send_sig(SIGILL, current, 1); + } + unlock_kernel(); } void do_illegal_instruction(struct pt_regs *regs, unsigned long pc, unsigned long npc, unsigned long psr) { + lock_kernel(); if(psr & PSR_PS) die_if_kernel("Kernel illegal instruction", regs); #ifdef TRAP_DEBUG printk("Ill instr. at pc=%08lx instruction is %08lx\n", regs->pc, *(unsigned long *)regs->pc); #endif + if (sparc_cpu_model == sun4c || sparc_cpu_model == sun4) { + extern int do_user_muldiv (struct pt_regs *, unsigned long); + if (!do_user_muldiv (regs, pc)) + goto out; + } current->tss.sig_address = pc; current->tss.sig_desc = SUBSIG_ILLINST; send_sig(SIGILL, current, 1); +out: + unlock_kernel(); } void do_priv_instruction(struct pt_regs *regs, unsigned long pc, unsigned long npc, unsigned long psr) { + lock_kernel(); if(psr & PSR_PS) die_if_kernel("Penguin instruction from Penguin mode??!?!", regs); current->tss.sig_address = pc; current->tss.sig_desc = SUBSIG_PRIVINST; send_sig(SIGILL, current, 1); + unlock_kernel(); } /* XXX User may want to be allowed to do this. XXX */ @@ -145,6 +153,7 @@ void do_priv_instruction(struct pt_regs *regs, unsigned long pc, unsigned long n void do_memaccess_unaligned(struct pt_regs *regs, unsigned long pc, unsigned long npc, unsigned long psr) { + lock_kernel(); if(regs->psr & PSR_PS) { printk("KERNEL MNA at pc %08lx npc %08lx called by %08lx\n", pc, npc, regs->u_regs[UREG_RETPC]); @@ -159,6 +168,7 @@ void do_memaccess_unaligned(struct pt_regs *regs, unsigned long pc, unsigned lon printk ("do_MNA!\n"); #endif send_sig(SIGBUS, current, 1); + unlock_kernel(); } extern void fpsave(unsigned long *fpregs, unsigned long *fsr, @@ -175,6 +185,7 @@ static unsigned long init_fregs[32] __attribute__ ((aligned (8))) = void do_fpd_trap(struct pt_regs *regs, unsigned long pc, unsigned long npc, unsigned long psr) { + lock_kernel(); /* Sanity check... */ if(psr & PSR_PS) die_if_kernel("Kernel gets FloatingPenguinUnit disabled trap", regs); @@ -183,7 +194,7 @@ void do_fpd_trap(struct pt_regs *regs, unsigned long pc, unsigned long npc, regs->psr |= PSR_EF; #ifndef __SMP__ if(last_task_used_math == current) - return; + goto out; if(last_task_used_math) { /* Other processes fpu state, save away */ struct task_struct *fptask = last_task_used_math; @@ -207,6 +218,10 @@ void do_fpd_trap(struct pt_regs *regs, unsigned long pc, unsigned long npc, } current->flags |= PF_USEDFPU; #endif +#ifndef __SMP__ +out: +#endif + unlock_kernel(); } static unsigned long fake_regs[32] __attribute__ ((aligned (8))); @@ -223,7 +238,7 @@ void do_fpe_trap(struct pt_regs *regs, unsigned long pc, unsigned long npc, #else struct task_struct *fpt = current; #endif - + lock_kernel(); put_psr(get_psr() | PSR_EF); /* If nobody owns the fpu right now, just clear the * error into our fake static buffer and hope it don't @@ -236,7 +251,7 @@ void do_fpe_trap(struct pt_regs *regs, unsigned long pc, unsigned long npc, #endif fpsave(&fake_regs[0], &fake_fsr, &fake_queue[0], &fake_depth); regs->psr &= ~PSR_EF; - return; + goto out; } fpsave(&fpt->tss.float_regs[0], &fpt->tss.fsr, &fpt->tss.fpqueue[0], &fpt->tss.fpqdepth); @@ -257,7 +272,7 @@ void do_fpe_trap(struct pt_regs *regs, unsigned long pc, unsigned long npc, if(calls > 2) die_if_kernel("Too many Penguin-FPU traps from kernel mode", regs); - return; + goto out; } send_sig(SIGFPE, fpt, 1); #ifndef __SMP__ @@ -266,21 +281,26 @@ void do_fpe_trap(struct pt_regs *regs, unsigned long pc, unsigned long npc, regs->psr &= ~PSR_EF; if(calls > 0) calls=0; +out: + unlock_kernel(); } void handle_tag_overflow(struct pt_regs *regs, unsigned long pc, unsigned long npc, unsigned long psr) { + lock_kernel(); if(psr & PSR_PS) die_if_kernel("Penguin overflow trap from kernel mode", regs); current->tss.sig_address = pc; current->tss.sig_desc = SUBSIG_TAG; /* as good as any */ send_sig(SIGEMT, current, 1); + unlock_kernel(); } void handle_watchpoint(struct pt_regs *regs, unsigned long pc, unsigned long npc, unsigned long psr) { + lock_kernel(); #ifdef TRAP_DEBUG printk("Watchpoint detected at PC %08lx NPC %08lx PSR %08lx\n", pc, npc, psr); @@ -288,49 +308,60 @@ void handle_watchpoint(struct pt_regs *regs, unsigned long pc, unsigned long npc if(psr & PSR_PS) panic("Tell me what a watchpoint trap is, and I'll then deal " "with such a beast..."); + unlock_kernel(); } void handle_reg_access(struct pt_regs *regs, unsigned long pc, unsigned long npc, unsigned long psr) { + lock_kernel(); #ifdef TRAP_DEBUG printk("Register Access Exception at PC %08lx NPC %08lx PSR %08lx\n", pc, npc, psr); #endif send_sig(SIGILL, current, 1); + unlock_kernel(); } void handle_cp_disabled(struct pt_regs *regs, unsigned long pc, unsigned long npc, unsigned long psr) { + lock_kernel(); send_sig(SIGILL, current, 1); + unlock_kernel(); } void handle_bad_flush(struct pt_regs *regs, unsigned long pc, unsigned long npc, unsigned long psr) { + lock_kernel(); #ifdef TRAP_DEBUG printk("Unimplemented FLUSH Exception at PC %08lx NPC %08lx PSR %08lx\n", pc, npc, psr); #endif printk("INSTRUCTION=%08lx\n", *((unsigned long *) regs->pc)); send_sig(SIGILL, current, 1); + unlock_kernel(); } void handle_cp_exception(struct pt_regs *regs, unsigned long pc, unsigned long npc, unsigned long psr) { + lock_kernel(); #ifdef TRAP_DEBUG printk("Co-Processor Exception at PC %08lx NPC %08lx PSR %08lx\n", pc, npc, psr); #endif send_sig(SIGILL, current, 1); + unlock_kernel(); } void handle_hw_divzero(struct pt_regs *regs, unsigned long pc, unsigned long npc, unsigned long psr) { + lock_kernel(); send_sig(SIGILL, current, 1); + unlock_kernel(); } /* Since we have our mappings set up, on multiprocessors we can spin them @@ -339,7 +370,6 @@ void handle_hw_divzero(struct pt_regs *regs, unsigned long pc, unsigned long npc extern void sparc_cpu_startup(void); -extern int linux_num_cpus; extern ctxd_t *srmmu_ctx_table_phys; int linux_smp_still_initting; |