summaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorBarry Song <barry.song@analog.com>2009-11-27 10:18:21 +0100
committerMike Frysinger <vapier@gentoo.org>2009-12-15 06:15:59 +0100
commita00b4fe5ce4b98f7c4457fffdb392d7bfece2e78 (patch)
treec4416dd2c7264aac87cd1d4be948f6ca4379158f /arch
parentBlackfin: drop ptrace() write support for fixed code/bootrom (diff)
downloadlinux-a00b4fe5ce4b98f7c4457fffdb392d7bfece2e78.tar.xz
linux-a00b4fe5ce4b98f7c4457fffdb392d7bfece2e78.zip
Blackfin: workaround anomaly 05000310
While fetching instructions at the boundary of L1 instruction SRAM, a false External Memory Addressing Error might be triggered. We should ignore this and continue on our way to avoid random crashes. Because hardware errors are not exact in the Blackfin architecture, we need to catch a few more common cases when the code flow changes and the signal is finally delivered. Signed-off-by: Barry Song <barry.song@analog.com> Signed-off-by: Mike Frysinger <vapier@gentoo.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/blackfin/kernel/traps.c30
1 files changed, 30 insertions, 0 deletions
diff --git a/arch/blackfin/kernel/traps.c b/arch/blackfin/kernel/traps.c
index 427294c47f1b..e4fd516ce482 100644
--- a/arch/blackfin/kernel/traps.c
+++ b/arch/blackfin/kernel/traps.c
@@ -524,6 +524,36 @@ asmlinkage notrace void trap_c(struct pt_regs *fp)
break;
/* External Memory Addressing Error */
case (SEQSTAT_HWERRCAUSE_EXTERN_ADDR):
+ if (ANOMALY_05000310) {
+ static unsigned long anomaly_rets;
+
+ if ((fp->pc >= (L1_CODE_START + L1_CODE_LENGTH - 512)) &&
+ (fp->pc < (L1_CODE_START + L1_CODE_LENGTH))) {
+ /*
+ * A false hardware error will happen while fetching at
+ * the L1 instruction SRAM boundary. Ignore it.
+ */
+ anomaly_rets = fp->rets;
+ goto traps_done;
+ } else if (fp->rets == anomaly_rets) {
+ /*
+ * While boundary code returns to a function, at the ret
+ * point, a new false hardware error might occur too based
+ * on tests. Ignore it too.
+ */
+ goto traps_done;
+ } else if ((fp->rets >= (L1_CODE_START + L1_CODE_LENGTH - 512)) &&
+ (fp->rets < (L1_CODE_START + L1_CODE_LENGTH))) {
+ /*
+ * If boundary code calls a function, at the entry point,
+ * a new false hardware error maybe happen based on tests.
+ * Ignore it too.
+ */
+ goto traps_done;
+ } else
+ anomaly_rets = 0;
+ }
+
info.si_code = BUS_ADRERR;
sig = SIGBUS;
strerror = KERN_NOTICE HWC_x3(KERN_NOTICE);