diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2007-11-22 23:30:49 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2007-11-22 23:30:49 +0000 |
commit | f759cbc10fee3cc3cceb8babff7e53b3e00f9c28 (patch) | |
tree | 7fa0412d3416720e7a4adf4c98c99d959a2ebb7a /sys | |
parent | 98803743fe4599010ed7599ea93efdb5b66de049 (diff) |
A decent workaround for errata #16. I have verified it gets triggered, the
hard way.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/arch/m88k/m88k/trap.c | 49 |
1 files changed, 39 insertions, 10 deletions
diff --git a/sys/arch/m88k/m88k/trap.c b/sys/arch/m88k/m88k/trap.c index 473ee1a1a95..5c0db513695 100644 --- a/sys/arch/m88k/m88k/trap.c +++ b/sys/arch/m88k/m88k/trap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: trap.c,v 1.50 2007/11/22 06:11:51 miod Exp $ */ +/* $OpenBSD: trap.c,v 1.51 2007/11/22 23:30:48 miod Exp $ */ /* * Copyright (c) 2004, Miodrag Vallat. * Copyright (c) 1998 Steve Murphree, Jr. @@ -613,15 +613,10 @@ m88110_trap(u_int type, struct trapframe *frame) if ((p = curproc) == NULL) p = &proc0; - if (USERMODE(frame->tf_epsr)) { - type += T_USER; - p->p_md.md_tf = frame; /* for ptrace/signals */ - } fault_type = 0; fault_code = 0; fault_addr = frame->tf_exip & XIP_ADDR; -#if 0 /* * 88110 errata #16 (4.2) or #3 (5.1.1): * ``bsr, br, bcnd, jsr and jmp instructions with the .n extension @@ -644,11 +639,44 @@ m88110_trap(u_int type, struct trapframe *frame) * whether the jsr.n problem applies to all registers or only * r1 -- miod) */ - if ((frame->tf_exip & 0x00000fff) == 0x00000001) { - panic("mc88110 errata #16, exip %p enip %p", - frame->tf_exip, frame->tf_enip); + if ((frame->tf_exip & 0x00000fff) == 0x00000001 && + (type == T_DATAFLT || type == T_INSTFLT)) { + u_int instr; + + /* + * Note that we have initialized fault_addr above, so that + * signals provide the correct address if necessary. + */ + frame->tf_exip = (frame->tf_exip & ~1) - 4; + + /* + * Check the instruction at the (backed up) exip. + * If it is a jsr.n, abort. + */ + if (USERMODE(frame->tf_epsr)) { + instr = *(u_int *)frame->tf_exip; + if ((instr & 0xffffffe0) == 0xf400cc00) + panic("mc88110 errata #16, exip %p enip %p", + (frame->tf_exip + 4) | 1, frame->tf_enip); + } else { + /* copyin here should not fail */ + if (copyin((const void *)frame->tf_exip, &instr, + sizeof instr) == 0 && + (instr & 0xffffffe0) == 0xf400cc00) { + uprintf("mc88110 errata #16, exip %p enip %p", + (frame->tf_exip + 4) | 1, frame->tf_enip); + sig = SIGILL; + } + } } -#endif + + if (USERMODE(frame->tf_epsr)) { + type += T_USER; + p->p_md.md_tf = frame; /* for ptrace/signals */ + } + + if (sig != 0) + goto deliver; switch (type) { default: @@ -1071,6 +1099,7 @@ m88110_user_fault: return; if (sig) { +deliver: sv.sival_int = fault_addr; KERNEL_PROC_LOCK(p); trapsignal(p, sig, fault_code, fault_type, sv); |