diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2010-12-20 20:07:50 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2010-12-20 20:07:50 +0000 |
commit | e1ba3d87b27a0df466cdaa571e51baa7a16cdf22 (patch) | |
tree | 8045e37a21c65f61cdffb574070146888a8f199b | |
parent | 73c1e35be32e71244dc6c9d880e2924fcdd5e38a (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.c | 52 |
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", |