From: Mike Frysinger <vapier@gentoo.org>
To: linux-kernel@vger.kernel.org
Cc: uclinux-dist-devel@blackfin.uclinux.org,
Robin Getz <robin.getz@analog.com>
Subject: [PATCH 38/62] Blackfin: make deferred hardware errors more exact
Date: Fri, 5 Jun 2009 04:04:47 -0400 [thread overview]
Message-ID: <1244189111-19639-39-git-send-email-vapier@gentoo.org> (raw)
In-Reply-To: <1244189111-19639-1-git-send-email-vapier@gentoo.org>
From: Robin Getz <robin.getz@analog.com>
Hardware errors on the Blackfin architecture are queued by nature of the
hardware design. Things that could generate a hardware level queue up at
the system interface and might not process until much later, at which
point the system would send a notification back to the core.
As such, it is possible for user space code to do something that would
trigger a hardware error, but have it delay long enough for the process
context to switch. So when the hardware error does signal, we mistakenly
evaluate it as a different process or as kernel context and panic (erp!).
This makes it pretty difficult to find the offending context. But wait,
there is good news somewhere.
By forcing a SSYNC in the interrupt entry, we force all pending queues at
the system level to be processed and all hardware errors to be signaled.
Then we check the current interrupt state to see if the hardware error is
now signaled. If so, we re-queue the current interrupt and return thus
allowing the higher priority hardware error interrupt to process properly.
Since we haven't done any other context processing yet, the right context
will be selected and killed. There is still the possibility that the
exact offending instruction will be unknown, but at least we'll have a
much better idea of where to look.
The downside of course is that this causes system-wide syncs at every
interrupt point which results in significant performance degradation.
Since this situation should not occur in any properly configured system
(as hardware errors are triggered by things like bad pointers), make it a
debug configuration option and disable it by default.
Signed-off-by: Robin Getz <robin.getz@analog.com>
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
---
arch/blackfin/Kconfig.debug | 13 +++++
arch/blackfin/include/asm/entry.h | 92 +++++++++++++++++++++++++++++++-
arch/blackfin/mach-common/entry.S | 59 +++++++++++++++------
arch/blackfin/mach-common/interrupt.S | 27 ++++++++++
4 files changed, 170 insertions(+), 21 deletions(-)
diff --git a/arch/blackfin/Kconfig.debug b/arch/blackfin/Kconfig.debug
index 79e7e63..1fc4981 100644
--- a/arch/blackfin/Kconfig.debug
+++ b/arch/blackfin/Kconfig.debug
@@ -54,6 +54,19 @@ config DEBUG_HWERR
hardware error interrupts and need to know where they are coming
from.
+config EXACT_HWERR
+ bool "Try to make Hardware errors exact"
+ depends on DEBUG_HWERR
+ help
+ By default, the Blackfin hardware errors are not exact - the error
+ be reported multiple cycles after the error happens. This delay
+ can cause the wrong application, or even the kernel to receive a
+ signal to be killed. If you are getting HW errors in your system,
+ try turning this on to ensure they are at least comming from the
+ proper thread.
+
+ On production systems, it is safe (and a small optimization) to say N.
+
config DEBUG_DOUBLEFAULT
bool "Debug Double Faults"
default n
diff --git a/arch/blackfin/include/asm/entry.h b/arch/blackfin/include/asm/entry.h
index b30a296..ec58efc 100644
--- a/arch/blackfin/include/asm/entry.h
+++ b/arch/blackfin/include/asm/entry.h
@@ -35,21 +35,39 @@
#else
# define LOAD_IPIPE_IPEND
#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*/ \
+ [--sp] = R0; /*orig_r0*/ \
+ [--sp] = (R7:0,P5:0); \
+ 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. */
+ *macro accesses it to determine where to account time.
+ */
#define TIMER_INTERRUPT_ENTRY(N) \
[--sp] = SYSCFG; \
- \
[--sp] = P0; /*orig_p0*/ \
[--sp] = R0; /*orig_r0*/ \
[--sp] = (R7:0,P5:0); \
@@ -58,6 +76,74 @@
r1 = [p0]; \
R0 = (N); \
jump __common_int_entry;
+#else /* CONFIG_EXACT_HWERR is defined */
+
+/* if we want hardware error to be exact, we need to do a SSYNC (which forces
+ * read/writes to complete to the memory controllers), and check to see that
+ * caused a pending HW error condition. If so, we assume it was caused by user
+ * 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.
+ * 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*/ \
+ [--sp] = (R7:0,P5:0); \
+ R1 = ASTAT; \
+ P0.L = LO(ILAT); \
+ P0.H = HI(ILAT); \
+ 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; \
+1: ASTAT = R1; \
+ RAISE N; \
+ (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*/ \
+ [--sp] = (R7:0,P5:0); \
+ R1 = ASTAT; \
+ P0.L = LO(ILAT); \
+ P0.H = HI(ILAT); \
+ 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); \
+ jump __common_int_entry; \
+1: ASTAT = R1; \
+ RAISE N; \
+ (R7:0, P5:0) = [SP++]; \
+ SP += 0x8; \
+ SYSCFG = [SP++]; \
+ CSYNC; \
+ RTI;
+#endif /* CONFIG_EXACT_HWERR */
/* This one pushes RETI without using CLI. Interrupts are enabled. */
#define SAVE_CONTEXT_SYSCALL save_context_syscall
diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S
index f0636fd..da0558a 100644
--- a/arch/blackfin/mach-common/entry.S
+++ b/arch/blackfin/mach-common/entry.S
@@ -200,7 +200,18 @@ ENTRY(_ex_single_step)
cc = r7 == 0;
if !cc jump 1f;
#endif
-
+#ifdef CONFIG_EXACT_HWERR
+ /* Read the ILAT, and to check to see if the process we are
+ * single stepping caused a previous hardware error
+ * If so, do not single step, (which lowers to IRQ5, and makes
+ * us miss the error).
+ */
+ p5.l = lo(ILAT);
+ p5.h = hi(ILAT);
+ r7 = [p5];
+ cc = bittst(r7, EVT_IVHW_P);
+ if cc jump 1f;
+#endif
/* Single stepping only a single instruction, so clear the trace
* bit here. */
r7 = syscfg;
@@ -262,15 +273,6 @@ ENTRY(_bfin_return_from_exception)
r6 = 0x25;
CC = R7 == R6;
if CC JUMP _double_fault;
-
- /* Did we cause a HW error? */
- p5.l = lo(ILAT);
- p5.h = hi(ILAT);
- r6 = [p5];
- r7 = 0x20; /* Did I just cause anther HW error? */
- r6 = r7 & r6;
- CC = R7 == R6;
- if CC JUMP _double_fault;
#endif
(R7:6,P5:4) = [sp++];
@@ -472,6 +474,16 @@ ENTRY(_trap) /* Exception: 4th entry into system event table(supervisor mode)*/
[--sp] = ASTAT;
[--sp] = (R7:6,P5:4);
+#ifdef CONFIG_EXACT_HWERR
+ /* Make sure all pending read/writes complete. This will ensure any
+ * accesses which could cause hardware errors completes, and signal
+ * the the hardware before we do something silly, like crash the
+ * kernel. We don't need to work around anomaly 05000312, since
+ * we are already atomic
+ */
+ ssync;
+#endif
+
#if ANOMALY_05000283 || ANOMALY_05000315
cc = r7 == r7;
p5.h = HI(CHIPID);
@@ -854,7 +866,7 @@ ENTRY(_ret_from_exception)
p1.h = _schedule_and_signal;
[p0] = p1;
csync;
- raise 15; /* raise evt14 to do signal or reschedule */
+ raise 15; /* raise evt15 to do signal or reschedule */
4:
r0 = syscfg;
bitclr(r0, 0);
@@ -915,7 +927,7 @@ ENTRY(_return_from_int)
p1.h = _schedule_and_signal_from_int;
[p0] = p1;
csync;
-#if ANOMALY_05000281
+#if ANOMALY_05000281 || ANOMALY_05000461
r0.l = lo(SAFE_USER_INSTRUCTION);
r0.h = hi(SAFE_USER_INSTRUCTION);
reti = r0;
@@ -929,18 +941,27 @@ ENTRY(_return_from_int)
ENDPROC(_return_from_int)
ENTRY(_lower_to_irq14)
-#if ANOMALY_05000281
+#if ANOMALY_05000281 || ANOMALY_05000461
r0.l = lo(SAFE_USER_INSTRUCTION);
r0.h = hi(SAFE_USER_INSTRUCTION);
reti = r0;
#endif
- r0 = 0x401f;
+
+#ifdef CONFIG_DEBUG_HWERR
+ /* enable irq14 & hwerr interrupt, until we transition to _evt14_softirq */
+ r0 = (EVT_IVG14 | EVT_IVHW | EVT_IRPTEN | EVT_EVX | EVT_NMI | EVT_RST | EVT_EMU);
+#else
+ /* Only enable irq14 interrupt, until we transition to _evt14_softirq */
+ r0 = (EVT_IVG14 | EVT_IRPTEN | EVT_EVX | EVT_NMI | EVT_RST | EVT_EMU);
+#endif
sti r0;
raise 14;
rti;
+ENDPROC(_lower_to_irq14)
+
ENTRY(_evt14_softirq)
#ifdef CONFIG_DEBUG_HWERR
- r0 = 0x3f;
+ r0 = (EVT_IVHW | EVT_IRPTEN | EVT_EVX | EVT_NMI | EVT_RST | EVT_EMU);
sti r0;
#else
cli r0;
@@ -948,8 +969,9 @@ ENTRY(_evt14_softirq)
[--sp] = RETI;
SP += 4;
rts;
+ENDPROC(_evt14_softirq)
-_schedule_and_signal_from_int:
+ENTRY(_schedule_and_signal_from_int)
/* To end up here, vector 15 was changed - so we have to change it
* back.
*/
@@ -982,8 +1004,9 @@ _schedule_and_signal_from_int:
call _finish_atomic_sections;
sp += 12;
jump.s .Lresume_userspace;
+ENDPROC(_schedule_and_signal_from_int)
-_schedule_and_signal:
+ENTRY(_schedule_and_signal)
SAVE_CONTEXT_SYSCALL
/* To end up here, vector 15 was changed - so we have to change it
* back.
@@ -1001,7 +1024,7 @@ _schedule_and_signal:
1:
RESTORE_CONTEXT
rti;
-ENDPROC(_lower_to_irq14)
+ENDPROC(_schedule_and_signal)
/* We handle this 100% in exception space - to reduce overhead
* Only potiential problem is if the software buffer gets swapped out of the
diff --git a/arch/blackfin/mach-common/interrupt.S b/arch/blackfin/mach-common/interrupt.S
index 0069c2d..9c46680 100644
--- a/arch/blackfin/mach-common/interrupt.S
+++ b/arch/blackfin/mach-common/interrupt.S
@@ -145,6 +145,14 @@ __common_int_entry:
/* 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 @@ ENTRY(_evt_ivhw)
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);
--
1.6.3.1
next prev parent reply other threads:[~2009-06-05 8:20 UTC|newest]
Thread overview: 63+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-06-05 8:04 [PATCH 00/62] Blackfin arch updates for 2.6.31 Mike Frysinger
2009-06-05 8:04 ` [PATCH 01/62] Blackfin: add comment for anomaly 05000171 to init code Mike Frysinger
2009-06-05 8:04 ` [PATCH 02/62] Blackfin: add some help text to the EBIU_AMBCTL settings Mike Frysinger
2009-06-05 8:04 ` [PATCH 03/62] Blackfin: bf527-ezkit: add support for mmc-spi Mike Frysinger
2009-06-05 8:04 ` [PATCH 04/62] Blackfin: Allow bf548 ATAPI to be routed to GPIO Mike Frysinger
2009-06-05 8:04 ` [PATCH 05/62] Blackfin: allow scheduler functions to be placed into L1 Mike Frysinger
2009-06-05 8:04 ` [PATCH 06/62] Blackfin: fix link failure due to CONFIG_EXCEPTION_L1_SCRATCH Mike Frysinger
2009-06-05 8:04 ` [PATCH 07/62] Blackfin: fix data cache flushing when doing icache flushing Mike Frysinger
2009-06-05 8:04 ` [PATCH 08/62] Blackfin: fix bug found by traps test case 21 Mike Frysinger
2009-06-05 8:04 ` [PATCH 09/62] Blackfin: fix parentheses balance and convert some tab/space mixing Mike Frysinger
2009-06-05 8:04 ` [PATCH 10/62] Blackfin: fix warnings with I/O port macros Mike Frysinger
2009-06-05 8:04 ` [PATCH 11/62] Blackfin: merge Philippe's recent ipipe patch Mike Frysinger
2009-06-05 8:04 ` [PATCH 12/62] Blackfin: fix up PATA resource handling in bf537-stamp Mike Frysinger
2009-06-05 8:04 ` [PATCH 13/62] Blackfin: pull updated anomaly lists from toolchain Mike Frysinger
2009-06-05 8:04 ` [PATCH 14/62] Blackfin: do not error if GPIO IRQ is requested already as GPIO Mike Frysinger
2009-06-05 8:04 ` [PATCH 15/62] Blackfin: set bf51x/bf52x to 0.0 rev by default and bf54x to 0.2 Mike Frysinger
2009-06-05 8:04 ` [PATCH 16/62] Blackfin: simplify the do_flush macro Mike Frysinger
2009-06-05 8:04 ` [PATCH 17/62] Blackfin: update defconfigs Mike Frysinger
2009-06-05 8:04 ` [PATCH 18/62] Blackfin: simplify BF561 coreb driver greatly Mike Frysinger
2009-06-05 8:04 ` [PATCH 19/62] Blackfin: fix detection of cached L2 SRAM Mike Frysinger
2009-06-05 8:04 ` [PATCH 20/62] Blackfin: add MDMA defines to make cross-variant coding easier Mike Frysinger
2009-06-05 8:04 ` [PATCH 21/62] Blackfin: fix early L1 relocation crash Mike Frysinger
2009-06-05 8:04 ` [PATCH 22/62] Blackfin: document anomaly 05000234 workaround Mike Frysinger
2009-06-05 8:04 ` [PATCH 23/62] Blackfin: annotate anomaly 05000119 in core DMA code Mike Frysinger
2009-06-05 8:04 ` [PATCH 24/62] Blackfin: punt useless GPIO init call Mike Frysinger
2009-06-05 8:04 ` [PATCH 25/62] Blackfin: work around anomaly 05000287 Mike Frysinger
2009-06-05 8:04 ` [PATCH 26/62] Blackfin: delete unused sys_getpagesize() function Mike Frysinger
2009-06-05 8:04 ` [PATCH 27/62] Blackfin: workaround anomaly 05000227 Mike Frysinger
2009-06-05 8:04 ` [PATCH 28/62] Blackfin: do not append newlines to panic() messages Mike Frysinger
2009-06-05 8:04 ` [PATCH 29/62] Blackfin: detect anomaly 05000274 Mike Frysinger
2009-06-05 8:04 ` [PATCH 30/62] Blackfin: BF518F-EZBRD: handle required portmuxing of async pins Mike Frysinger
2009-06-05 8:04 ` [PATCH 31/62] Blackfin: annotate anomaly 05000120 Mike Frysinger
2009-06-05 8:04 ` [PATCH 32/62] Blackfin: add support for gptimer0 as a tick source Mike Frysinger
2009-06-05 8:04 ` [PATCH 33/62] Blackfin: add workaround for anomaly 05000287 Mike Frysinger
2009-06-05 8:04 ` [PATCH 34/62] Blackfin: make sure MPU CPLB for first 1k is marked as valid Mike Frysinger
2009-06-05 8:04 ` [PATCH 35/62] Blackfin: rename some Blackfin drivers Mike Frysinger
2009-06-05 8:04 ` [PATCH 36/62] Blackfin: work around anomaly 05000220 Mike Frysinger
2009-06-05 8:04 ` [PATCH 37/62] Blackfin: add note about anomaly 05000242 being worked around Mike Frysinger
2009-06-05 8:04 ` Mike Frysinger [this message]
2009-06-05 8:04 ` [PATCH 39/62] Blackfin: make sure stack is accessible before dumping it Mike Frysinger
2009-06-05 8:04 ` [PATCH 40/62] Blackfin: add workaround for anomaly 05000461 Mike Frysinger
2009-06-05 8:04 ` [PATCH 41/62] Blackfin: include system/processor info in dump messages Mike Frysinger
2009-06-05 8:04 ` [PATCH 42/62] Blackfin: update gptimers API Mike Frysinger
2009-06-05 8:04 ` [PATCH 43/62] Blackfin: drop unused reserve_pda() function Mike Frysinger
2009-06-05 8:04 ` [PATCH 44/62] Blackfin: merge sram init functions Mike Frysinger
2009-06-05 8:04 ` [PATCH 45/62] Blackfin: fix handling of initial L1 reservation Mike Frysinger
2009-06-05 8:04 ` [PATCH 46/62] Blackfin: fix command line corruption with DEBUG_DOUBLEFAULT Mike Frysinger
2009-06-05 8:04 ` [PATCH 47/62] Blackfin: override default uClinux MTD addr/size Mike Frysinger
2009-06-05 8:04 ` [PATCH 48/62] Blackfin: bf548-ezkit: add resources for ADXL345/346 Mike Frysinger
2009-06-05 8:04 ` [PATCH 49/62] Blackfin: convert SMP to only use generic time framework Mike Frysinger
2009-06-05 8:04 ` [PATCH 50/62] Blackfin: add SSYNC to set_dma_sg() for descriptor fetching Mike Frysinger
2009-06-05 8:05 ` [PATCH 51/62] Blackfin: check SIC defines rather than variant names Mike Frysinger
2009-06-05 8:05 ` [PATCH 52/62] Blackfin: rename Blackfin relocs according to the toolchain Mike Frysinger
2009-06-05 8:05 ` [PATCH 53/62] Blackfin: document the lsl variants of the L1 allocator Mike Frysinger
2009-06-05 8:05 ` [PATCH 54/62] Blackfin: convert early_printk EVT init to a loop Mike Frysinger
2009-06-05 8:05 ` [PATCH 55/62] Blackfin: add missing access_ok() checks to user functions Mike Frysinger
2009-06-05 8:05 ` [PATCH 56/62] Blackfin: punt duplicated search_exception_table() prototype Mike Frysinger
2009-06-05 8:05 ` [PATCH 57/62] Blackfin: push access_ok() L1 attribute down Mike Frysinger
2009-06-05 8:05 ` [PATCH 58/62] Blackfin: kgdb: fix up error return values Mike Frysinger
2009-06-05 8:05 ` [PATCH 59/62] Blackfin: fix length checking in kgdb_ebin2mem Mike Frysinger
2009-06-05 8:05 ` [PATCH 60/62] Blackfin: export the last exception cause via debugfs Mike Frysinger
2009-06-05 8:05 ` [PATCH 61/62] Blackfin: fix unused warnings after nommu update Mike Frysinger
2009-06-05 8:05 ` [PATCH 62/62] Blackfin: fix sparseirq/kstat_irqs fallout Mike Frysinger
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1244189111-19639-39-git-send-email-vapier@gentoo.org \
--to=vapier@gentoo.org \
--cc=linux-kernel@vger.kernel.org \
--cc=robin.getz@analog.com \
--cc=uclinux-dist-devel@blackfin.uclinux.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®