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

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