patch-2.1.23 linux/arch/sparc/kernel/traps.c
Next file: linux/arch/sparc/kernel/unaligned.c
Previous file: linux/arch/sparc/kernel/time.c
Back to the patch index
Back to the overall index
- Lines: 255
- Date:
Sun Jan 26 12:07:08 1997
- Orig file:
v2.1.22/linux/arch/sparc/kernel/traps.c
- Orig date:
Tue Dec 31 21:41:00 1996
diff -u --recursive --new-file v2.1.22/linux/arch/sparc/kernel/traps.c linux/arch/sparc/kernel/traps.c
@@ -1,4 +1,4 @@
-/* $Id: traps.c,v 1.50 1996/12/29 20:46:05 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)
@@ -11,6 +11,8 @@
#include <linux/sched.h> /* for jiffies */
#include <linux/kernel.h>
#include <linux/signal.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
#include <asm/delay.h>
#include <asm/system.h>
@@ -21,7 +23,6 @@
#include <asm/kdebug.h>
#include <asm/unistd.h>
#include <asm/traps.h>
-#include <asm/smp.h>
/* #define TRAP_DEBUG */
@@ -93,6 +94,7 @@
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);
@@ -101,20 +103,21 @@
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
@@ -124,21 +127,25 @@
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))
- return;
+ 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 */
@@ -146,6 +153,7 @@
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]);
@@ -160,6 +168,7 @@
printk ("do_MNA!\n");
#endif
send_sig(SIGBUS, current, 1);
+ unlock_kernel();
}
extern void fpsave(unsigned long *fpregs, unsigned long *fsr,
@@ -176,6 +185,7 @@
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);
@@ -184,7 +194,7 @@
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;
@@ -208,6 +218,10 @@
}
current->flags |= PF_USEDFPU;
#endif
+#ifndef __SMP__
+out:
+#endif
+ unlock_kernel();
}
static unsigned long fake_regs[32] __attribute__ ((aligned (8)));
@@ -224,7 +238,7 @@
#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
@@ -237,7 +251,7 @@
#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);
@@ -258,7 +272,7 @@
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__
@@ -267,21 +281,26 @@
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);
@@ -289,49 +308,60 @@
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
@@ -340,7 +370,6 @@
extern void sparc_cpu_startup(void);
-extern int linux_num_cpus;
extern ctxd_t *srmmu_ctx_table_phys;
int linux_smp_still_initting;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov