summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2010-12-20 20:07:50 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2010-12-20 20:07:50 +0000
commite1ba3d87b27a0df466cdaa571e51baa7a16cdf22 (patch)
tree8045e37a21c65f61cdffb574070146888a8f199b
parent73c1e35be32e71244dc6c9d880e2924fcdd5e38a (diff)
mvme88k kernels running on 88110 systems have been prone to panicing for
``invalid opcode'' in kernel mode after being idle for a few hours, since many months already. This panic does not make sense. Recently, I've been able to gather enough samples and, looking at the instructions surrounding the panic location, I have narrowed a pattern, and I'll conveniently blame these panics upon a (to the best of my knowledge) new genuine 88110 bug. The exception handler will now recognize this situation and apply a large hammer of workaround - probably not the best workaround that could be devised, but it's short, easy to implement, and works 100% of the time so far. Besides, since the machine is idle, who cares as long as it keeps running? (the curious reader will find more information in the trap.c comments)
-rw-r--r--sys/arch/m88k/m88k/trap.c52
1 files changed, 50 insertions, 2 deletions
diff --git a/sys/arch/m88k/m88k/trap.c b/sys/arch/m88k/m88k/trap.c
index 50539debcb5..eaad8bdfdf8 100644
--- a/sys/arch/m88k/m88k/trap.c
+++ b/sys/arch/m88k/m88k/trap.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: trap.c,v 1.69 2009/03/01 17:43:25 miod Exp $ */
+/* $OpenBSD: trap.c,v 1.70 2010/12/20 20:07:49 miod Exp $ */
/*
* Copyright (c) 2004, Miodrag Vallat.
* Copyright (c) 1998 Steve Murphree, Jr.
@@ -742,7 +742,55 @@ lose:
return;
#endif /* DDB */
case T_ILLFLT:
- printf("Unimplemented opcode!\n");
+ /*
+ * The 88110 seems to trigger an instruction fault in
+ * supervisor mode when running the following sequence:
+ *
+ * bcnd.n cond, reg, 1f
+ * arithmetic insn
+ * ...
+ * the same exact arithmetic insn
+ * 1: another arithmetic insn stalled by the previous one
+ * ...
+ *
+ * The exception is reported with exip pointing to the
+ * branch address. I don't know, at this point, if there
+ * is any better workaround than the aggressive one
+ * implemented below; I don't see how this could relate to
+ * any of the 88110 errata (although it might be related to
+ * branch prediction).
+ *
+ * For the record, the exact sequence triggering the
+ * spurious exception is:
+ *
+ * bcnd.n eq0, r2, 1f
+ * or r25, r0, r22
+ * bsr somewhere
+ * or r25, r0, r22
+ * 1: cmp r13, r25, r20
+ *
+ * within the same cache line.
+ *
+ * Simply ignoring the exception and returning does not
+ * cause the exception to disappear. Clearing the
+ * instruction cache works, but on 88110+88410 systems,
+ * the 88410 needs to be invalidated as well. (note that
+ * the size passed to the flush routines does not matter
+ * since there is no way to flush a subset of the 88110
+ * I$ anyway)
+ */
+ {
+ extern void *kernel_text, *etext;
+
+ if (fault_addr >= (vaddr_t)kernel_text &&
+ fault_addr <(vaddr_t)&etext) {
+ cmmu_flush_inst_cache(curcpu()->ci_cpuid,
+ trunc_page(fault_addr), PAGE_SIZE);
+ cmmu_flush_cache(curcpu()->ci_cpuid,
+ trunc_page(fault_addr), PAGE_SIZE);
+ return;
+ }
+ }
goto lose;
case T_MISALGNFLT:
printf("kernel mode misaligned access exception @ 0x%08x\n",