Title: [3931] trunk: [#3719] Rather that duplicate code, connect Hardware Errors ( irq5) into trap_c,
Revision
3931
Author
rgetz
Date
2007-11-24 15:10:00 -0600 (Sat, 24 Nov 2007)

Log Message

[#3719] Rather that duplicate code, connect Hardware Errors (irq5) into trap_c,
so user space processes get killed properly.

The rest of irq_panic() can be moved into traps.c (later)

There is still a small corner case that causes problems when a
pheriperal interrupt goes off a single cycle before a user space
hardware error. This causes a kernel panic, rather than the user
space process being killed.

But, this checkin makes things work in 99.9% of the cases, and is a vast
improvement from what is there today (which fails 100% of the time).

Diffstat

 arch/blackfin/kernel/traps.c          |   54 ++++++++++++++++++++++++++++------
 arch/blackfin/mach-common/interrupt.S |   38 ++++++++++++++++++-----
 arch/blackfin/mach-common/irqpanic.c  |   50 -------------------------------
 include/asm-blackfin/traps.h          |    4 ++
 4 files changed, 79 insertions(+), 67 deletions(-)

Modified Paths

Diff

Modified: trunk/arch/blackfin/kernel/traps.c (3930 => 3931)


--- trunk/arch/blackfin/kernel/traps.c	2007-11-24 03:55:08 UTC (rev 3930)
+++ trunk/arch/blackfin/kernel/traps.c	2007-11-24 21:10:00 UTC (rev 3931)
@@ -432,6 +432,36 @@
 	/* 0x3D - Reserved, Caught by default */
 	/* 0x3E - Reserved, Caught by default */
 	/* 0x3F - Reserved, Caught by default */
+	case VEC_HWERR:
+		info.si_code = BUS_ADRALN;
+		sig = SIGBUS;
+		switch (fp->seqstat & SEQSTAT_HWERRCAUSE) {
+		/* System MMR Error */
+		case (SEQSTAT_HWERRCAUSE_SYSTEM_MMR):
+			info.si_code = BUS_ADRALN;
+			sig = SIGBUS;
+			printk(KERN_NOTICE HWC_x2(KERN_NOTICE));
+			break;
+		/* External Memory Addressing Error */
+		case (SEQSTAT_HWERRCAUSE_EXTERN_ADDR):
+			info.si_code = BUS_ADRERR;
+			sig = SIGBUS;
+			printk(KERN_NOTICE HWC_x3(KERN_NOTICE));
+			break;
+		/* Performance Monitor Overflow */
+		case (SEQSTAT_HWERRCAUSE_PERF_FLOW):
+			printk(KERN_NOTICE HWC_x12(KERN_NOTICE));
+			break;
+		/* RAISE 5 instruction */
+		case (SEQSTAT_HWERRCAUSE_RAISE_5):
+			printk(KERN_NOTICE HWC_x18(KERN_NOTICE));
+			break;
+		default:        /* Reserved */
+			printk(KERN_NOTICE HWC_default(KERN_NOTICE));
+			break;
+		}
+		CHK_DEBUGGER_TRAP();
+		break;
 	default:
 		info.si_code = TRAP_ILLTRAP;
 		sig = SIGTRAP;
@@ -446,7 +476,11 @@
 	if (sig != SIGTRAP) {
 		unsigned long stack;
 		dump_bfin_process(fp);
-		dump_bfin_mem((void *)fp->retx);
+		/* Is it an interrupt, or an exception? */
+		if (trapnr == VEC_HWERR)
+			dump_bfin_mem((void *)fp->pc);
+		else
+			dump_bfin_mem((void *)fp->retx);
 		show_regs(fp);
 
 		/* Print out the trace buffer if it makes sense */
@@ -664,12 +698,11 @@
 			 * context, which should mean an oops is happening
 			 */
 			if (oops_in_progress && x >= 0x0040 && x <= 0x0047 && i <= 0)
-				panic("\n\nWARNING : You should reconfigure"
+				printk(KERN_EMERG "\n"
+					KERN_EMERG "WARNING : You should reconfigure"
 					" the kernel to turn on\n"
-					" 'Hardware error interrupt"
-					" debugging'\n"
-					" The rest of this error"
-					" is meanless\n");
+					KERN_EMERG " 'Hardware error interrupt debugging'\n"
+					KERN_EMERG " The rest of this error is meanless\n");
 #endif
 			if (i == (unsigned int)retaddr)
 				printk("[%04x]", x);
@@ -690,6 +723,10 @@
 	printk(KERN_NOTICE "\n" KERN_NOTICE "SEQUENCER STATUS:\n");
 	printk(KERN_NOTICE " SEQSTAT: %08lx  IPEND: %04lx  SYSCFG: %04lx\n",
 		(long)fp->seqstat, fp->ipend, fp->syscfg);
+	printk(KERN_NOTICE "  HWERRCAUSE: 0x%lx\n",
+		(fp->seqstat & SEQSTAT_HWERRCAUSE) >> 14);
+	printk(KERN_NOTICE "  EXCAUSE   : 0x%lx\n",
+		fp->seqstat & SEQSTAT_EXCAUSE);
 
 	decode_address(buf, fp->rete);
 	printk(KERN_NOTICE " RETE: %s\n", buf);
@@ -700,9 +737,10 @@
 	decode_address(buf, fp->rets);
 	printk(KERN_NOTICE " RETS: %s\n", buf);
 	decode_address(buf, fp->pc);
-	printk(KERN_NOTICE " PC: %s\n", buf);
+	printk(KERN_NOTICE " PC  : %s\n", buf);
 
-	if ((long)fp->seqstat & SEQSTAT_EXCAUSE) {
+	if (((long)fp->seqstat &  SEQSTAT_EXCAUSE) &&
+	    (((long)fp->seqstat & SEQSTAT_EXCAUSE) != VEC_HWERR)) {
 		decode_address(buf, bfin_read_DCPLB_FAULT_ADDR());
 		printk(KERN_NOTICE "DCPLB_FAULT_ADDR: %s\n", buf);
 		decode_address(buf, bfin_read_ICPLB_FAULT_ADDR());

Modified: trunk/arch/blackfin/mach-common/interrupt.S (3930 => 3931)


--- trunk/arch/blackfin/mach-common/interrupt.S	2007-11-24 03:55:08 UTC (rev 3930)
+++ trunk/arch/blackfin/mach-common/interrupt.S	2007-11-24 21:10:00 UTC (rev 3931)
@@ -34,9 +34,13 @@
 #include <asm/entry.h>
 #include <asm/asm-offsets.h>
 #include <asm/trace.h>
+#include <asm/traps.h>
+#include <asm/thread_info.h>
 
 #include <asm/mach-common/context.S>
 
+.extern _ret_from_exception
+
 #ifdef CONFIG_I_ENTRY_L1
 .section .l1.text
 #else
@@ -134,10 +138,11 @@
 
 /* interrupt routine for ivhw - 5 */
 ENTRY(_evt_ivhw)
-	SAVE_CONTEXT
+	SAVE_ALL_SYS
 #ifdef CONFIG_FRAME_POINTER
 	fp = 0;
 #endif
+
 #if ANOMALY_05000283
 	cc = r7 == r7;
 	p5.h = HI(CHIPID);
@@ -147,13 +152,8 @@
 1:
 #endif
 
-	trace_buffer_stop(p0, r0);
-
-	r0 = IRQ_HWERR;
-	r1 = sp;
-
 #ifdef CONFIG_HARDWARE_PM
-	r7 = SEQSTAT;
+	r7 = [sp + PT_SEQSTAT];
 	r7 = r7 >>> 0xe;
 	r6 = 0x1F;
 	r7 = r7 & r6;
@@ -161,11 +161,29 @@
 	cc = r7 == r5;
 	if cc jump .Lcall_do_ovf; /* deal with performance counter overflow */
 #endif
+	# We are going to dump something out, so make sure we print IPEND properly
+	p2.l = lo(IPEND);
+	p2.h = hi(IPEND);
+	r0 = [p2];
+	[sp + PT_IPEND] = r0;
 
+	/* set the EXCAUSE to HWERR for trap_c */
+	r0 = [sp + PT_SEQSTAT];
+	R1.L = LO(VEC_HWERR);
+	R1.H = HI(VEC_HWERR);
+	R0 = R0 | R1;
+	[sp + PT_SEQSTAT] = R0;
+
+	r0 = sp;        /* stack frame pt_regs pointer argument ==> r0 */
 	SP += -12;
-	call _irq_panic;
+	call _trap_c;
 	SP += 12;
+
+	call _ret_from_exception;
+.Lcommon_restore_all_sys:
+	RESTORE_ALL_SYS
 	rti;
+
 #ifdef CONFIG_HARDWARE_PM
 .Lcall_do_ovf:
 
@@ -173,9 +191,11 @@
 	call _pm_overflow;
 	SP += 12;
 
-	jump .Lcommon_restore_context;
+	jump .Lcommon_restore_all_sys;
 #endif
 
+ENDPROC(_evt_ivhw)
+
 /* Interrupt routine for evt2 (NMI).
  * We don't actually use this, so just return.
  * For inner circle type details, please see:

Modified: trunk/arch/blackfin/mach-common/irqpanic.c (3930 => 3931)


--- trunk/arch/blackfin/mach-common/irqpanic.c	2007-11-24 03:55:08 UTC (rev 3930)
+++ trunk/arch/blackfin/mach-common/irqpanic.c	2007-11-24 21:10:00 UTC (rev 3931)
@@ -46,9 +46,6 @@
  */
 asmlinkage void irq_panic(int reason, struct pt_regs *regs)
 {
-	int sig = 0;
-	siginfo_t info;
-
 #ifdef CONFIG_DEBUG_ICACHE_CHECK
 	unsigned int cmd, tag, ca, cache_hi, cache_lo, *pa;
 	unsigned short i, j, die;
@@ -136,53 +133,6 @@
 	}
 #endif
 
-	printk(KERN_EMERG "\n");
-	printk(KERN_EMERG "Exception: IRQ 0x%x entered\n", reason);
-	printk(KERN_EMERG " code=[0x%08lx],   stack frame=0x%08lx,  "
-	    " bad PC=0x%08lx\n",
-	    (unsigned long)regs->seqstat,
-	    (unsigned long)regs,
-	    (unsigned long)regs->pc);
-	if (reason == 0x5) {
-		printk(KERN_EMERG "----------- HARDWARE ERROR -----------\n");
-
-		/* There is only need to check for Hardware Errors, since other
-		 * EXCEPTIONS are handled in TRAPS.c (MH)
-		 */
-		switch (regs->seqstat & SEQSTAT_HWERRCAUSE) {
-		case (SEQSTAT_HWERRCAUSE_SYSTEM_MMR):	/* System MMR Error */
-			info.si_code = BUS_ADRALN;
-			sig = SIGBUS;
-			printk(KERN_EMERG HWC_x2(KERN_EMERG));
-			break;
-		case (SEQSTAT_HWERRCAUSE_EXTERN_ADDR):	/* External Memory Addressing Error */
-			info.si_code = BUS_ADRERR;
-			sig = SIGBUS;
-			printk(KERN_EMERG HWC_x3(KERN_EMERG));
-			break;
-		case (SEQSTAT_HWERRCAUSE_PERF_FLOW):	/* Performance Monitor Overflow */
-			printk(KERN_EMERG HWC_x12(KERN_EMERG));
-			break;
-		case (SEQSTAT_HWERRCAUSE_RAISE_5):	/* RAISE 5 instruction */
-			printk(KERN_EMERG HWC_x18(KERN_EMERG));
-			break;
-		default:	/* Reserved */
-			printk(KERN_EMERG HWC_default(KERN_EMERG));
-			break;
-		}
-	}
-
-	regs->ipend = bfin_read_IPEND();
-	dump_bfin_process(regs);
-	dump_bfin_mem((void *)regs->pc);
-	show_regs(regs);
-	if (0 == (info.si_signo = sig) || 0 == user_mode(regs))	/* in kernelspace */
-		panic("Unhandled IRQ or exceptions!\n");
-	else {			/* in userspace */
-		info.si_errno = 0;
-		info.si_addr = (void *)regs->pc;
-		force_sig_info(sig, &info, current);
-	}
 }
 
 #ifdef CONFIG_HARDWARE_PM

Modified: trunk/include/asm-blackfin/traps.h (3930 => 3931)


--- trunk/include/asm-blackfin/traps.h	2007-11-24 03:55:08 UTC (rev 3930)
+++ trunk/include/asm-blackfin/traps.h	2007-11-24 21:10:00 UTC (rev 3931)
@@ -45,6 +45,10 @@
 #define VEC_CPLB_I_M	(44)
 #define VEC_CPLB_I_MHIT	(45)
 #define VEC_ILL_RES	(46)	/* including unvalid supervisor mode insn */
+/* The hardware reserves (63) for future use - we use it to tell our
+ * normal exception handling code we have a hardware error
+ */
+#define VEC_HWERR	(63)
 
 #ifndef __ASSEMBLY__
 
_______________________________________________
Linux-kernel-commits mailing list
[email protected]
http://blackfin.uclinux.org/mailman/listinfo/linux-kernel-commits

Reply via email to