Title: [6535] trunk/arch/blackfin: [#5120] Ok - with this addition - hardware errors seem to be exact, and
Revision
6535
Author
rgetz
Date
2009-06-02 08:45:28 -0500 (Tue, 02 Jun 2009)

Log Message

[#5120] Ok - with this addition - hardware errors seem to be exact, and
don't crash the kernel when done from userspace.

[!no_src_qa!] - checkpatch doesn't like assembly in .h files :(

Modified Paths

Diff

Modified: trunk/arch/blackfin/include/asm/entry.h (6534 => 6535)


--- trunk/arch/blackfin/include/asm/entry.h	2009-06-02 10:43:39 UTC (rev 6534)
+++ trunk/arch/blackfin/include/asm/entry.h	2009-06-02 13:45:28 UTC (rev 6535)
@@ -37,6 +37,10 @@
 #endif
 
 #ifndef CONFIG_EXACT_HWERR
+/* As a debugging aid - we save IPEND when DEBUG_KERNEL is on,
+ * otherwise it is a waste of cycles.
+ */
+# ifndef CONFIG_DEBUG_KERNEL
 #define INTERRUPT_ENTRY(N)						\
     [--sp] = SYSCFG;							\
     [--sp] = P0;	/*orig_p0*/					\
@@ -45,6 +49,19 @@
     R0 = (N);								\
     LOAD_IPIPE_IPEND							\
     jump __common_int_entry;
+# else /* CONFIG_DEBUG_KERNEL */
+#define INTERRUPT_ENTRY(N)						\
+    [--sp] = SYSCFG;							\
+    [--sp] = P0;	/*orig_p0*/					\
+    [--sp] = R0;	/*orig_r0*/					\
+    [--sp] = (R7:0,P5:0);						\
+    p0.l = lo(IPEND);							\
+    p0.h = hi(IPEND);							\
+    r1 = [p0];								\
+    R0 = (N);								\
+    LOAD_IPIPE_IPEND							\
+    jump __common_int_entry;
+# endif /* CONFIG_DEBUG_KERNEL */
 
 /* For timer interrupts, we need to save IPEND, since the user_mode
  *macro accesses it to determine where to account time.
@@ -67,9 +84,14 @@
  * space, by setting the same interrupt that we are in (so it goes off again)
  * and context restore, and a RTI (without servicing anything). This should
  * cause the pending HWERR to fire, and when that is done, this interrupt will
- * be re-serviced properly.
+ * be re-serviced properly. 
+ * As you can see by the code - we actually need to do two SSYNCS - one to
+ * make sure the read/writes complete, and another to make sure the hardware
+ * error is recognized by the core.
  */
 #define INTERRUPT_ENTRY(N)						\
+    SSYNC;								\
+    SSYNC;								\
     [--sp] = SYSCFG;							\
     [--sp] = P0;	/*orig_p0*/					\
     [--sp] = R0;	/*orig_r0*/					\
@@ -77,11 +99,13 @@
     R1 = ASTAT;								\
     P0.L = LO(ILAT);							\
     P0.H = HI(ILAT);							\
-    SSYNC;								\
     R0 = [P0];								\
     CC = BITTST(R0, EVT_IVHW_P);					\
     IF CC JUMP 1f;							\
     ASTAT = R1;								\
+    p0.l = lo(IPEND);							\
+    p0.h = hi(IPEND);							\
+    r1 = [p0];								\
     R0 = (N);								\
     LOAD_IPIPE_IPEND							\
     jump __common_int_entry;						\
@@ -90,9 +114,12 @@
     (R7:0, P5:0) = [SP++];						\
     SP += 0x8;								\
     SYSCFG = [SP++];							\
+    CSYNC;								\
     RTI;
 
 #define TIMER_INTERRUPT_ENTRY(N)					\
+    SSYNC;								\
+    SSYNC;								\
     [--sp] = SYSCFG;							\
     [--sp] = P0;	/*orig_p0*/					\
     [--sp] = R0;	/*orig_r0*/					\
@@ -100,7 +127,6 @@
     R1 = ASTAT;								\
     P0.L = LO(ILAT);							\
     P0.H = HI(ILAT);							\
-    SSYNC;								\
     R0 = [P0];								\
     CC = BITTST(R0, EVT_IVHW_P);					\
     IF CC JUMP 1f;							\
@@ -115,6 +141,7 @@
     (R7:0, P5:0) = [SP++];						\
     SP += 0x8;								\
     SYSCFG = [SP++];							\
+    CSYNC;								\
     RTI;
 #endif	/* CONFIG_EXACT_HWERR */
 

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


--- trunk/arch/blackfin/mach-common/interrupt.S	2009-06-02 10:43:39 UTC (rev 6534)
+++ trunk/arch/blackfin/mach-common/interrupt.S	2009-06-02 13:45:28 UTC (rev 6535)
@@ -145,6 +145,14 @@
 
 /* interrupt routine for ivhw - 5 */
 ENTRY(_evt_ivhw)
+	/* In case a single action kicks off multiple memory transactions, (like
+	 * a cache line fetch, - this can cause multiple hardware errors, let's
+	 * catch them all. First - make sure all the actions are complete, and
+	 * the core sees the hardware errors.
+	 */
+	SSYNC;
+	SSYNC;
+
 	SAVE_ALL_SYS
 #ifdef CONFIG_FRAME_POINTER
 	fp = 0;
@@ -159,6 +167,25 @@
 1:
 #endif
 
+	/* Handle all stacked hardware errors
+	 * To make sure we don't hang forever, only do it 10 times
+	 */
+	R0 = 0;
+	R2 = 10;
+1:
+	P0.L = LO(ILAT);
+	P0.H = HI(ILAT);
+	R1 = [P0];
+	CC = BITTST(R1, EVT_IVHW_P);
+	IF ! CC JUMP 2f;
+	/* OK a hardware error is pending - clear it */
+	R1 = EVT_IVHW_P;
+	[P0] = R1;
+	R0 += 1;
+	CC = R1 == R2;
+	if CC JUMP 2f;
+	JUMP 1b;
+2:
 	# We are going to dump something out, so make sure we print IPEND properly
 	p2.l = lo(IPEND);
 	p2.h = hi(IPEND);
_______________________________________________
Linux-kernel-commits mailing list
[email protected]
https://blackfin.uclinux.org/mailman/listinfo/linux-kernel-commits

Reply via email to