summaryrefslogtreecommitdiffstats
path: root/arch/sparc/kernel/traps.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1997-04-29 21:13:14 +0000
committer <ralf@linux-mips.org>1997-04-29 21:13:14 +0000
commit19c9bba94152148523ba0f7ef7cffe3d45656b11 (patch)
tree40b1cb534496a7f1ca0f5c314a523c69f1fee464 /arch/sparc/kernel/traps.c
parent7206675c40394c78a90e74812bbdbf8cf3cca1be (diff)
Import of Linux/MIPS 2.1.36
Diffstat (limited to 'arch/sparc/kernel/traps.c')
-rw-r--r--arch/sparc/kernel/traps.c68
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;