NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
port-powerpc/51367: kernel panic for powerpc/ibm4xx with "option DDB"
>Number: 51367
>Category: port-powerpc
>Synopsis: kernel panic for powerpc/ibm4xx with "option DDB"
>Confidential: no
>Severity: critical
>Priority: high
>Responsible: port-powerpc-maintainer
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Wed Jul 27 15:05:00 +0000 2016
>Originator: Rin Okuyama
>Release: HEAD
>Organization:
Faculty of Science and Technology, Keio University
>Environment:
NetBSD obs266 7.99.34 NetBSD 7.99.34 (OPENBLOCKS266) #1: Wed Jul 27 22:09:26 JST 2016 rin@XXX:XXX evbppc
>Description:
Kernel panic occurs for powerpc/ibm4xx (e.g., evbppc/OPENBLOCKS266) when
an userland process issues an illegal instruction. For example, reboot
system with sshd=YES in rc.conf, then, you will observe
====================
...
Updating motd.
Stopped in pid 358.1 (ssh-keygen) at 0: illegal instruction 7074000
db>
====================
Here, ssh-keygen issues an illegal instruction because of assembler codes
in OpenSSL. This is due to the trap handler for ddb: ssh-keygen, for
example, works fine with kernel compiled without DDB option.
>How-To-Repeat:
Described above.
>Fix:
In the trap handler for ddb, check whether it is called in the privileged
mode or user mode. If it is called in the user mode, switch to the default
trap handler, as in a similar manner to powerpc/powerpc/trap_subr.S. Then,
an illegal instruction in the user mode does not trigger kernel panic.
I've checked that ddb can be activated from console, and also "continue"
command works fine. The patch attached below contains fix to ipkdb, but it
is not tested.
====================
--- src/sys/arch/powerpc/ibm4xx/trap_subr.S.orig 2016-07-26 17:22:14.111178887 +0900
+++ src/sys/arch/powerpc/ibm4xx/trap_subr.S 2016-07-26 17:50:49.971311997 +0900
@@ -205,7 +205,27 @@
_C_LABEL(ddblow):
mtsprg1 %r1 /* save SP */
GET_CPUINFO(%r1)
- stmw %r28,CI_DDBSAVE(%r1) /* free r28-r31 */
+ stmw %r30,(CI_DDBSAVE+CPUSAVE_R30)(%r1); /* free r30-r31 */
+ mfcr %r30; /* save CR */
+ mfsrr1 %r31;
+ mtcr %r31;
+ bf MSR_PR,1f /* branch if privileged */
+ mtcr %r30; /* restore CR */
+ lmw %r30,(CI_DDBSAVE+CPUSAVE_R30)(%r1); /* restore r30-r31 */
+ stmw %r28,(CI_TEMPSAVE+CPUSAVE_R28)(%r1); /* free r28-r31 */
+ mflr %r28; /* save LR */
+ mfcr %r29; /* save CR */
+ mfsrr0 %r30;
+ mfsrr1 %r31;
+ stmw %r30,(CI_TEMPSAVE+CPUSAVE_SRR0)(%r1); /* save srr0/srr1 */
+ mfsprg1 %r1; /* restore SP */
+ GET_PCB(%r1);
+ addi %r1,%r1,USPACE-CALLFRAMELEN; /* stack is top of user struct */
+ bla s_trap;
+1:
+ mtcr %r30; /* restore CR */
+ lmw %r30,(CI_DDBSAVE+CPUSAVE_R30)(%r1); /* restore r30-r31 */
+ stmw %r28,(CI_DDBSAVE+CPUSAVE_R28)(%r1) /* free r28-r31 */
mflr %r28 /* save LR */
mfcr %r29 /* save CR */
mfsrr0 %r30
@@ -228,7 +248,28 @@
_C_LABEL(ipkdblow):
mtsprg1 %r1 /* save SP */
GET_CPUINFO(%r1)
- stmw %r28,CI_IPKDBSAVE(%r1) /* free r28-r31 */
+ stmw %r30,(CI_IPKDBSAVE+CPUSAVE_R30)(%r1); /* free r30-r31 */
+ mfcr %r30; /* save CR */
+ mfsrr1 %r31;
+ mtcr %r31;
+ bf MSR_PR,1f /* branch if privileged */
+ mtcr %r30; /* restore CR */
+ lmw %r30,(CI_IPKDBSAVE+CPUSAVE_R30)(%r1); /* restore r30-r31 */
+ stmw %r28,(CI_TEMPSAVE+CPUSAVE_R28)(%r1); /* free r28-r31 */
+ mflr %r28; /* save LR */
+ mfcr %r29; /* save CR */
+ mfsrr0 %r30;
+ mfsrr1 %r31;
+ stmw %r30,(CI_TEMPSAVE+CPUSAVE_SRR0)(%r1); /* save srr0/srr1 */
+ mfsprg1 %r1; /* restore SP */
+ GET_PCB(%r1);
+ addi %r1,%r1,USPACE-CALLFRAMELEN; /* stack is top of user struct */
+ bla s_trap;
+1:
+ mtcr %r30; /* restore CR */
+ lmw %r30,(CI_IPKDBSAVE+CPUSAVE_R30)(%r1); /* restore r30-r31 */
+ lwz %r31,(CI_IPKDBSAVE+CPUSAVE_R31)(%r1); /* restore r31 */
+ stmw %r28,(CI_IPKDBSAVE+CPUSAVE_R28)(%r1) /* free r28-r31 */
mflr %r28 /* save LR */
mfcr %r29 /* save CR */
mfsrr0 %r30
@@ -536,7 +577,7 @@
stw %r3,(CI_DDBSAVE+CPUSAVE_SRR1)(%r4)
wrteei 0 /* disable interrupts */
isync
- stmw %r28,CI_DDBSAVE(%r4)
+ stmw %r28,(CI_DDBSAVE+CPUSAVE_R28)(%r4)
mflr %r28
stw %r28,(CI_DDBSAVE+CPUSAVE_SRR0)(%r4)
li %r29,EXC_BPT
@@ -568,7 +609,7 @@
stw %r3,(CI_IPKDBSAVE+CPUSAVE_SRR1)(%r4)
wrteei 0 /* disable interrupts */
isync
- stmw %r28,CI_IPKDBSAVE(%r4)
+ stmw %r28,(CI_IPKDBSAVE+CPUSAVE_R28)(%r4)
mflr %r28
stw %r28,(CI_IPKDBSAVE+CPUSAVE_SRR0)(%r4)
li %r29,EXC_BPT
====================
Here I attached another tiny patch which enables us to compile kernel
without DDB option. It also corrects a typo and a harmless logic error.
====================
--- src/sys/arch/powerpc/fpu/fpu_emu.c.orig 2016-07-26 06:43:25.645354519 +0900
+++ src/sys/arch/powerpc/fpu/fpu_emu.c 2016-07-26 06:45:23.596533829 +0900
@@ -248,14 +248,14 @@
case NOTFPU:
default:
DPRINTF(FPE_EX, ("fpu_emulate: SIGILL\n"));
-#ifdef DEBUG
+#if defined(DDB) && defined(DEBUG)
if (fpe_debug & FPE_EX) {
printf("fpu_emulate: illegal insn %x at %p:",
insn.i_int, (void *) (tf->tf_srr0));
opc_disasm((vaddr_t)(tf->tf_srr0), insn.i_int);
}
#endif
-#if defined(PPC_IBM4XX) && defined(DEBUG)
+#if defined(PPC_IBM4XX) && defined(DDB) && defined(DEBUG)
/*
* XXXX retry an illegal insn once due to cache issues.
*/
@@ -265,7 +265,7 @@
Debugger();
}
lastill = tf->tf_srr0;
-#endif /* PPC_IBM4XX && DEBUG */
+#endif /* PPC_IBM4XX && DDB && DEBUG */
return false;
}
}
--- src/sys/arch/powerpc/ibm4xx/ibm4xx_machdep.c.orig 2016-07-26 06:36:01.337826518 +0900
+++ src/sys/arch/powerpc/ibm4xx/ibm4xx_machdep.c 2016-07-26 14:58:11.074394305 +0900
@@ -75,6 +75,7 @@
#include "opt_kgdb.h"
#include "opt_ipkdb.h"
#include "opt_modular.h"
+#include "ksyms.h" /* for NKSYMS */
#include <sys/param.h>
#include <sys/msgbuf.h>
@@ -133,6 +134,8 @@
extern const uint32_t errata51handler[], errata51size;
#ifdef DDB
extern const uint32_t ddblow[], ddbsize;
+#endif
+#ifdef IPKDB
extern const uint32_t ipkdblow[], ipkdbsize;
#endif
static const struct exc_info trap_table[] = {
@@ -147,12 +150,12 @@
{ EXC_DEBUG, debugtrap, (uintptr_t)&debugsize },
{ (EXC_DTMISS|EXC_ALI),
errata51handler, (uintptr_t)&errata51size },
-#if defined(DDB)
+#ifdef DDB
{ EXC_PGM, ddblow, (uintptr_t)&ddbsize },
-#endif /* DDB */
-#if defined(IPKBD)
+#endif
+#ifdef IPKDB
{ EXC_PGM, ipkdblow, (uintptr_t)&ipkdbsize },
-#endif /* DDB */
+#endif
};
/*
====================
Home |
Main Index |
Thread Index |
Old Index