NetBSD Problem Report #24096
Received: (qmail 20735 invoked by uid 605); 14 Jan 2004 23:32:51 -0000
Message-Id: <200401142332.i0ENWe0j022859@cerumen.trpz.com>
Date: Wed, 14 Jan 2004 15:32:40 -0800 (PST)
From: djg@trpz.com
Sender: gnats-bugs-owner@NetBSD.org
Reply-To: djg@trpz.com
To: gnats-bugs@gnats.netbsd.org
Subject: ctitcal 405GP/EP interrupts non-functional/ gdb/ss fails
X-Send-Pr-Version: 3.95
>Number: 24096
>Category: port-evbppc
>Synopsis: ctitcal 405GP/EP interrupts non-functional/ gdb/ss fails
>Confidential: no
>Severity: critical
>Priority: high
>Responsible: port-evbppc-maintainer
>State: closed
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Wed Jan 14 23:33:00 +0000 2004
>Closed-Date: Mon May 10 02:06:15 +0000 2021
>Last-Modified: Mon May 10 02:06:15 +0000 2021
>Originator:
>Release: NetBSD 1.6ZD
>Organization:
>Environment:
System: NetBSD cerumen.trpz.com 1.6ZD NetBSD 1.6ZD (NATES) #1: Mon Nov 10 12:58:16 PST 2003 djg@nates.trpz.com:/home/djg/src/NetBSD/usr/src/sys/arch/i386/compile/NATES i386
Architecture: powerpc
Machine: evbppc
>Description:
The critcal interupt in arch/powerpc/ibm4xx/trap_subr.S is
non functional. Most ports only use crtitcal interrupts
for machine-check which is disabled along with comments
of the machine hanging. The debug interrupt is also
a critical interrupt on the 405GP and 405EP. This is
the interrupt from "single stepping". The current
code declares "debug" as a normal interrupt but it
isn't. The existing code
(CRITICAL_PROLOG) has several problems.
1) it uses sprg1 without reagard to NORMAL_PROLOG
2) it uses the same save area as normal interrups
3) it sets srr0 and srr1 without reagrd to other
(normal) interrupts.
For machine check, since death is imminent this problably
dosn't matter but for single steeping its really useful
to be able to return to a running system. In most cases
taking a DEBUG interrupt would incorrectly use srr0 and srr1
which by very good fortune happens to be benign except that
the PC is off by 4. It is benign bacuse gdb uses "trap" instructions
which cause a PGM exception and hence srr0 and srr1 happend to
correspend to that. Thus gdb/single step fails - everything
else works.
Of note on GP/EP when gdb starts an executable the very first
instruction is set witk msr=PSL_SE, but this will result in a TLBMISS.
The very first DEBUG interrupt therfore occurs in kernel mode
on the first instruction of the interrupt handdler for tlmiss.
(I read this in the linux code). Thus all of the conditions
obove are met. This kernel mode debug trap has to be ignored
(with PSL_SE unset) to get back to the orignal user mode PSL_SE trap .
>How-To-Repeat:
gdb and single step on the ppc405
>Fix:
I've tried several things but it looks like the only workable
solution is to separate the crital from the non-critical code.
The following code works, but if the direction of trap_subr.S
were to change to be more like the OEA code then that ought to
be considerd (or maybe the OEA code should tend towards the
IBM4XX), anyway, using spgr2 for the critcal SP, its own
stack, its own s_trap variation (for critsave) and using
rfci for the returns (preserving srr0 and srr1 throughout).
3 files: sys/arch/powerpc/ibm4xx/ibm40x_machdep.c (see comment
below)
sys/arch/powerpc/ibm4xx/trap_subr.c
sys/arch/powerpc/ibm4xx/trap.c
also included is support for critcal external interrupts, however,
that requires an "ibm4xx_install_extcin()" which dosn't fit
well into the current evbppc scheme. (behind #ifdef trpz)
There again that seems to be overly complicated and for more
flexibilty than I've seen needed. (but I'm sure it fixed somebody's
problem). The code has only been run on a 405EP which isn't supportd
in current, and still has debug code left in. (PS the wdog interrupt
on a 405/EP should end a rfci too). complete source available
on request.
*** trap_subr.S Wed Jan 14 14:53:02 2004
--- /usr/src_current/src/sys/arch/powerpc/ibm4xx/trap_subr.S Mon Aug 11 20:09:19 2003
***************
*** 76,83 ****
/*
* Data used during primary/secondary traps/interrupts
*/
- #define critsave 0x1e0 /* primary save area for trap handling */
#define tempsave 0x2e0 /* primary save area for trap handling */
#define exitsave 0x4e0 /* use this so trap return does not conflict */
/*
* XXX Interrupt and spill stacks need to be per-CPU.
--- 76,83 ----
/*
* Data used during primary/secondary traps/interrupts
*/
#define tempsave 0x2e0 /* primary save area for trap handling */
+ #define disisave 0x3e0 /* primary save area for dsi/isi traps */
#define exitsave 0x4e0 /* use this so trap return does not conflict */
/*
* XXX Interrupt and spill stacks need to be per-CPU.
***************
*** 87,100 ****
GET_CPUINFO(rX); \
lwz rX,CI_CURPCB(rX)
- /*
- * Please note a critcal interrupt can occure during this
- * code segment. (PT_STEP on exec will cause a DEBUG interrupt
- * on the tlbmiss of the first instruction in the vector!, Also
- * a tlbmiss in this segment would be very bad - but we are kenrnel
- * mode so r1 ought be usable)
- */
-
#define STANDARD_PROLOG(savearea) \
mtsprg 1,1; /* save SP */ \
stmw 28,savearea(0); /* free r28-r31 */ \
--- 87,92 ----
***************
*** 108,117 ****
1:
#define CRITICAL_PROLOG(savearea) \
! mtsprg 2,1; /* save SP in sprg2 */ \
stmw 28,savearea(0); /* free r28-r31 */ \
mflr 28; /* save LR */ \
! mfcr 29; /* save CR */
/* Standard handler saves r1,r28-31,LR,CR, sets up the stack and calls s_trap */
--- 100,118 ----
1:
#define CRITICAL_PROLOG(savearea) \
! mtsprg 1,1; /* save SP */ \
stmw 28,savearea(0); /* free r28-r31 */ \
mflr 28; /* save LR */ \
! mfcr 29; /* save CR */ \
! mfsrr2 30; /* Fake a standard trap */ \
! mtsrr0 30; \
! mfsrr3 31; /* Test whether we already had PR set */ \
! mtsrr1 31; \
! mtcr 31; \
! bc 4,17,1f; /* branch if PSL_PR is clear */ \
! GET_PCB(1); \
! addi 1,1,USPACE; /* stack is top of user struct */ \
! 1:
/* Standard handler saves r1,r28-31,LR,CR, sets up the stack and calls s_trap */
***************
*** 119,128 ****
.globl _C_LABEL(name ## trap),_C_LABEL(name ## size) ; \
_C_LABEL(name ## trap): \
STANDARD_PROLOG(tempsave); \
- mfesr 31; \
- stw 31,20+tempsave(0); \
bla s_trap ; \
- trap; \
_C_LABEL(name ## size) = .-_C_LABEL(name ## trap)
/* Access exceptions also need DEAR and ESR saved */
--- 120,126 ----
***************
*** 134,152 ****
mfesr 31; \
stmw 30,16+tempsave(0); \
bla s_trap ; \
- trap; \
_C_LABEL(name ## size) = .-_C_LABEL(name ## trap)
! /* Maybe this should call ddb.... save ESR too */
#define CRITICAL_EXC_HANDLER(name)\
.globl _C_LABEL(name ## trap),_C_LABEL(name ## size) ; \
_C_LABEL(name ## trap): \
! CRITICAL_PROLOG(critsave); \
! mfdear 30; \
! mfesr 31; \
! stw 30,16+critsave(0); \
! bla s_ctrap ; \
! trap; \
_C_LABEL(name ## size) = .-_C_LABEL(name ## trap)
/*
--- 132,145 ----
mfesr 31; \
stmw 30,16+tempsave(0); \
bla s_trap ; \
_C_LABEL(name ## size) = .-_C_LABEL(name ## trap)
! /* Maybe this should call ddb.... */
#define CRITICAL_EXC_HANDLER(name)\
.globl _C_LABEL(name ## trap),_C_LABEL(name ## size) ; \
_C_LABEL(name ## trap): \
! CRITICAL_PROLOG(tempsave); \
! bla s_trap ; \
_C_LABEL(name ## size) = .-_C_LABEL(name ## trap)
/*
***************
*** 159,165 ****
ACCESS_EXC_HANDLER(ali)
ACCESS_EXC_HANDLER(dsi)
ACCESS_EXC_HANDLER(isi)
! CRITICAL_EXC_HANDLER(debug)
CRITICAL_EXC_HANDLER(mchk)
/*
--- 152,158 ----
ACCESS_EXC_HANDLER(ali)
ACCESS_EXC_HANDLER(dsi)
ACCESS_EXC_HANDLER(isi)
! STANDARD_EXC_HANDLER(debug)
CRITICAL_EXC_HANDLER(mchk)
/*
***************
*** 183,208 ****
ba extintr
_C_LABEL(extsize) = .-_C_LABEL(extint)
- /*
- * This one for the external critical interrupt handler.
- */
- .globl _C_LABEL(cintr),_C_LABEL(cintrsize)
- _C_LABEL(cintr):
- mtsprg 2,1 /* save SP in sprg2 */
- stmw 28,tempsave(0) /* free r28-r31 */
- mflr 28 /* save LR */
- mfcr 29 /* save CR */
- mfxer 30 /* save XER */
- GET_CPUINFO(1)
- lwz 31,CI_INTRDEPTH(1) /* were we already running on intstk? */
- addic. 31,31,1
- stw 31,CI_INTRDEPTH(1)
- lwz 1,CI_INTSTK(1) /* get intstk */
- beq 1f
- mfsprg 1,2
- 1:
- ba extcintr
- _C_LABEL(cintrsize) = .-_C_LABEL(cintr)
#ifdef DDB
#define ddbsave 0xde0 /* primary save area for DDB */
--- 176,181 ----
***************
*** 218,225 ****
stmw 28,ddbsave(0) /* free r28-r31 */
mflr 28 /* save LR */
mfcr 29 /* save CR */
- mfesr 31 /* save ESR */
- stw 31,20+ddbsave(0)
lis 1,ddbstk+INTSTK@ha /* get new SP */
addi 1,1,ddbstk+INTSTK@l
bla ddbtrap
--- 191,196 ----
***************
*** 249,258 ****
#ifdef DEBUG
#define TRAP_IF_ZERO(r) tweqi r,0
- #define TRAP_IF_NZERO(r) twnei r,0
#else
#define TRAP_IF_ZERO(r)
- #define TRAP_IF_NZERO(r)
#endif
/*
--- 220,227 ----
***************
*** 329,408 ****
mtpid 30; \
lmw 29,savearea(0)
- /*
- * CFRAME_SETUP assumes:
- * SPRG2 SP (1)
- * savearea r28-r31,DEAR,ESR (DEAR & ESR only for DSI traps)
- * 28 LR
- * 29 CR
- * 1 kernel critical stack
- * LR trap type
- * SRR2/3 as at start of trap
- */
- #define CFRAME_SETUP(savearea) \
- /* Have to enable translation to allow access of kernel stack: */ \
- mfsrr2 30; \
- mfsrr3 31; \
- stmw 30,savearea+24(0); \
- mfpid 30; \
- li 31,KERNEL_PID; \
- mtpid 31; \
- mfmsr 31; \
- ori 31,31,(PSL_DR|PSL_IR)@l; \
- mtmsr 31; \
- isync; \
- mfsprg2 31; \
- stwu 31,-FRAMELEN(1); \
- stw 30,FRAME_PID+8(1); \
- stw 0,FRAME_0+8(1); \
- stw 31,FRAME_1+8(1); \
- stw 28,FRAME_LR+8(1); \
- stw 29,FRAME_CR+8(1); \
- lmw 28,savearea(0); \
- stmw 2,FRAME_2+8(1); \
- lmw 28,savearea+16(0); \
- mfxer 3; \
- mfctr 4; \
- mflr 5; \
- andi. 5,5,0xff00; \
- stw 3,FRAME_XER+8(1); \
- stw 4,FRAME_CTR+8(1); \
- stw 5,FRAME_EXC+8(1); \
- stw 28,FRAME_DEAR+8(1); \
- stw 29,FRAME_ESR+8(1); \
- stw 30,FRAME_SRR0+8(1); \
- stw 31,FRAME_SRR1+8(1)
-
- #define CFRAME_LEAVE(savearea) \
- /* Now restore regs: */ \
- lwz 3,FRAME_PID+8(1); \
- lwz 4,FRAME_SRR1+8(1); \
- bl _C_LABEL(ctx_setup); \
- TRAP_IF_ZERO(3); \
- stw 3,FRAME_PID+8(1); \
- lmw 26,FRAME_LR+8(1); \
- mtlr 26; \
- mtcr 27; \
- mtxer 28; \
- mtctr 29; \
- mtsrr2 30; \
- mtsrr3 31; \
- lmw 2,FRAME_2+8(1); \
- lwz 0,FRAME_0+8(1); \
- stmw 29,savearea(0); \
- lwz 30,FRAME_PID+8(1); \
- lwz 1,FRAME_1+8(1); \
- mfmsr 31; \
- li 29,(PSL_DR|PSL_IR)@l; \
- andc 31,31,29; \
- mfcr 29; \
- mtcr 29; \
- mtmsr 31; \
- isync; \
- TRAP_IF_ZERO(30); \
- mtpid 30; \
- lmw 29,savearea(0)
-
realtrap: /* entry point after IPKDB is done with exception */
/* Test whether we already had PR set */
mfsrr1 1
--- 298,303 ----
***************
*** 444,478 ****
ba . /* Protect against prefetch */
- /* critical traps */
- /*
- * this is the stack for critical interupts. We only only
- * have one outstanding stack + machine check
- */
- .local critstk
- .comm critstk,INTSTK,8 /* critical interrupt stack */
-
- s_ctrap:
- lis 1,critstk+INTSTK@ha /* get new SP */
- addi 1,1,critstk+INTSTK@l
- mfsrr3 31 /* Test whether we already had PR set */
- mtcr 31
- bc 4,17,1f /* branch if PSL_PR is clear */
- GET_PCB(1)
- addi 1,1,USPACE; /* stack is top of user struct */
- 1:
-
- CFRAME_SETUP(critsave)
-
- /* Call C trap code: */
- addi 3,1,8
- bl _C_LABEL(trap)
- .globl _C_LABEL(ctrapexit)
- _C_LABEL(ctrapexit):
- CFRAME_LEAVE(exitsave)
- rfci
- ba . /* Protect against prefetch */
-
.globl _C_LABEL(sctrap),_C_LABEL(scsize),_C_LABEL(sctrapexit)
_C_LABEL(sctrap):
--- 339,344 ----
***************
*** 513,568 ****
/*
- * critical I/O interrupt
- */
-
- #define CINTRENTER \
- /* Save non-volatile registers: */ \
- stwu 1,-IFRAMELEN(1); /* temporarily */ \
- stw 0,IFRAME_R0(1); \
- mfsprg 0,1; /* get original SP */ \
- stw 0,IFRAME_R1(1); /* and store it */ \
- stw 3,IFRAME_R3(1); \
- stw 4,IFRAME_R4(1); \
- stw 5,IFRAME_R5(1); \
- stw 6,IFRAME_R6(1); \
- stw 7,IFRAME_R7(1); \
- stw 8,IFRAME_R8(1); \
- stw 9,IFRAME_R9(1); \
- stw 10,IFRAME_R10(1); \
- stw 11,IFRAME_R11(1); \
- stw 12,IFRAME_R12(1); \
- stw 28,IFRAME_LR(1); /* saved LR */ \
- stw 29,IFRAME_CR(1); /* saved CR */ \
- stw 30,IFRAME_XER(1); /* saved XER */ \
- lmw 28,tempsave(0); /* restore r28-r31 */ \
- mfctr 6; \
- GET_CPUINFO(5); \
- lwz 5,CI_INTRDEPTH(5); \
- mfsrr2 4; \
- mfsrr3 3; \
- stw 6,IFRAME_CTR(1); \
- stw 5,IFRAME_INTR_DEPTH(1); \
- stw 4,IFRAME_SRR0(1); \
- stw 3,IFRAME_SRR1(1); \
- mfpid 0; /* get currect PID register */ \
- stw 0,IFRAME_PID(1); \
- li 0,KERNEL_PID; \
- mtpid 0; \
- /* interrupts are recoverable here, and enable translation */ \
- mfmsr 5; \
- ori 5,5,(PSL_IR|PSL_DR); \
- mtmsr 5; \
- isync
-
- .globl _C_LABEL(extcint_call)
- extcintr:
- CINTRENTER
- _C_LABEL(extcint_call):
- bl _C_LABEL(extcint_call) /* to be filled in later */
- b intr_exit
-
- /*
* External interrupt second level handler
*/
--- 379,384 ----
***************
*** 888,911 ****
icbi 0,9 /* and instruction caches */
blr
#endif /* IPKDB */
-
-
- /*
- * trap if an external ICE is connected
- */
- .globl _C_LABEL(jtagtrap)
- _C_LABEL(jtagtrap):
- #ifndef PPC_IBM405GP
- mfdcr 3, 0xf7
- #else
- mfdcr 3, DCR_CPC0_JTAGID
- #endif
- or. 3, 3, 3
- beq 1f
- mfspr 4, SPR_DBCR0
- lis 0,0x8000
- or 4,4,0
- mtspr SPR_DBCR0,0
- twi 2,3,0
- 1:
- blr
--- 704,706 ----
Index: trap.c
===================================================================
RCS file: /sw/cvs/NetBSD/usr/src/sys/arch/powerpc/ibm4xx/trap.c,v
retrieving revision 1.1.1.6
retrieving revision 1.4
diff -c -r1.1.1.6 -r1.4
*** trap.c 21 Oct 2003 19:28:42 -0000 1.1.1.6
--- trap.c 14 Jan 2004 23:20:35 -0000 1.4
***************
*** 77,82 ****
--- 77,83 ----
#include <sys/param.h>
#include <sys/proc.h>
+ #include <sys/ras.h>
#include <sys/reboot.h>
#include <sys/syscall.h>
#include <sys/systm.h>
***************
*** 107,112 ****
--- 108,118 ----
#include <powerpc/ibm4xx/pmap.h>
#include <powerpc/ibm4xx/tlb.h>
#include <powerpc/fpu/fpu_extern.h>
+ #include <powerpc/instr.h>
+
+ #ifdef DDB
+ void db_printf(char *fmt,...);
+ #endif
/* These definitions should probably be somewhere else XXX */
#define FIRSTARG 3 /* first argument is in reg 3 */
***************
*** 123,128 ****
--- 129,135 ----
#ifdef DEBUG
#define TDB_ALL 0x1
+ #define TDB_TR 0x2
int trapdebug = /* TDB_ALL */ 0;
#define DBPRINTF(x, y) if (trapdebug & (x)) printf y
#else
***************
*** 149,163 ****
type, frame->srr0, frame, &frame));
switch (type) {
case EXC_DEBUG|EXC_USER:
{
! int srr2, srr3;
! __asm __volatile("mfspr %0,0x3f0" :
! "=r" (rv), "=r" (srr2), "=r" (srr3) :);
! printf("debug reg is %x srr2 %x srr3 %x\n", rv, srr2,
! srr3);
! /* XXX fall through or break here?! */
}
/*
* DEBUG intr -- probably single-step.
--- 156,266 ----
type, frame->srr0, frame, &frame));
switch (type) {
+ case EXC_DEBUG:
+ {
+ uint srr0, srr1;
+ uint srr2, srr3;
+ uint dbsr;
+
+ /* HID0 */
+ __asm __volatile("mfspr %0,0x3f0;"
+ "mfsrr0 %1;"
+ "mfsrr1 %2;"
+ "mfsrr2 %3;"
+ "mfsrr3 %4" :
+ "=r"(rv), "=r"(srr0), "=r"(srr1),
+ "=r"(srr2), "=r"(srr3) :);
+ dbsr = mfspr(SPR_DBSR);
+ DBPRINTF(TDB_TR, ("KDBG ssr0:0x%x/0x%x@0x%x ssr1:0x%x/0x%x srr2:0x%x srr3:0x%x dbcr0:0x%x dbcr1:0x%x dbsr:0x%x\n",
+ (uint)frame->srr0, srr0, (uint)&frame->srr0,
+ (uint)frame->srr1, srr1,
+ srr2,
+ srr3,
+ (uint)mfspr(SPR_DBCR0),
+ (uint)mfspr(SPR_DBCR1),
+ dbsr));
+
+ mtspr(SPR_DBSR, 0xffffffff);
+ }
+ if ((frame->srr0 > EXC_RSVD) && (frame->srr0 < EXC_LAST)) {
+ /*
+ * single step into, say a tlb miss.
+ * turn off single step to return back
+ * into the kernel - will go on again on
+ * return to user.
+ * Note, however, this means the pc will
+ * trap at the instruction start not completion!
+ */
+ frame->srr1 &= ~PSL_SE;
+ DBPRINTF(TDB_TR, ("KDB srr1 = 0x%x\n",
+ (uint)frame->srr1));
+ }
+ #ifdef DDB
+ /*
+ * must be kernal mode single step (currently ddb uses
+ * trap instructions on 405)
+ */
+ else {
+ if (kdb_trap(type, frame))
+ goto done;
+ }
+ #endif
+ return;
+
case EXC_DEBUG|EXC_USER:
{
! uint srr0, srr1;
! uint srr2, srr3;
! uint dbsr;
! union instr instr;
!
! /* HID0 */
! __asm __volatile("mfspr %0,0x3f0;"
! "mfsrr0 %1;"
! "mfsrr1 %2;"
! "mfsrr2 %3;"
! "mfsrr3 %4" :
! "=r"(rv), "=r"(srr0), "=r"(srr1),
! "=r"(srr2), "=r"(srr3) :);
! dbsr = mfspr(SPR_DBSR);
! DBPRINTF(TDB_TR, ("DBG ssr0:0x%x/0x%x ssr1:0x%x/0x%x srr2:0x%x srr3:0x%x dbcr0:0x%x dbcr1:0x%x dbsr:0x%x\n",
! (uint)frame->srr0, srr0,
! (uint)frame->srr1, srr1,
! srr2,
! srr3,
! (uint)mfspr(SPR_DBCR0),
! (uint)mfspr(SPR_DBCR1), dbsr));
!
! mtspr(SPR_DBSR, 0xffffffff);
!
! /*
! * if we took a DEBUG trap on a tlbmiss
! * then we havn't executed this instruction
! * at all - try again.
! */
! if (frame->srr0 == srr0) {
! /*
! frame->srr1 &= ~PSL_SE;
! */
! srr2 = 0;
! srr3 = 0;
! __asm __volatile("mfspr %0,0x3f0;"
! "mtsrr2 %0;"
! "mtsrr3 %0;" : :
! "r"(srr2), "r"(srr3));
! if (copyin((void *) (frame->srr0), &instr.i_int,
! sizeof (instr.i_int))) {
! return;
! }
! if ((instr.i_any.i_opcd != OPC_TWI) &&
! ((instr.i_any.i_opcd != OPC_integer_31) ||
! (instr.i_x.i_xo != OPC31_TW))) {
! extern void jtagtrap(void);
! jtagtrap();
! return;
! }
! }
}
/*
* DEBUG intr -- probably single-step.
***************
*** 168,173 ****
--- 271,277 ----
ksi.ksi_signo = SIGTRAP;
ksi.ksi_trap = EXC_TRC;
ksi.ksi_addr = (void *)frame->srr0;
+ ksi.ksi_code = TRAP_TRACE;
KERNEL_PROC_LOCK(l);
trapsignal(l, &ksi);
KERNEL_PROC_UNLOCK(l);
***************
*** 252,261 ****
--- 356,369 ----
KERNEL_PROC_UNLOCK(l);
break;
}
+
+ DBPRINTF(TDB_ALL, ("DSI is segv\n"));
+
KSI_INIT_TRAP(&ksi);
ksi.ksi_signo = SIGSEGV;
ksi.ksi_trap = EXC_DSI;
ksi.ksi_addr = (void *)frame->dar;
+ ksi.ksi_code = SEGV_ACCERR;
if (rv == ENOMEM) {
printf("UVM: pid %d (%s) lid %d, uid %d killed: "
"out of swap\n",
***************
*** 288,297 ****
--- 396,409 ----
KERNEL_PROC_UNLOCK(l);
break;
}
+
+ DBPRINTF( TDB_ALL, ("ISI is segv\n"));
+
KSI_INIT_TRAP(&ksi);
ksi.ksi_signo = SIGSEGV;
ksi.ksi_trap = EXC_ISI;
ksi.ksi_addr = (void *)frame->srr0;
+ ksi.ksi_code = SEGV_MAPERR;
trapsignal(l, &ksi);
l->l_flag &= ~L_SA_PAGEFAULT;
KERNEL_PROC_UNLOCK(l);
***************
*** 319,324 ****
--- 431,437 ----
ksi.ksi_signo = SIGBUS;
ksi.ksi_trap = EXC_ALI;
ksi.ksi_addr = (void *)frame->dar;
+ ksi.ksi_code = BUS_ADRALN;
trapsignal(l, &ksi);
} else
frame->srr0 += 4;
***************
*** 332,337 ****
--- 445,469 ----
* let's try to see if it's FPU and can be emulated.
*/
uvmexp.traps ++;
+
+ if (frame->tf_xtra[TF_ESR] & (ESR_PTR)) {
+ DBPRINTF( TDB_ALL, ("PGM+USER - 0x%x\n",
+ frame->tf_xtra[TF_ESR]));
+ if (LIST_EMPTY(&p->p_raslist) ||
+ ras_lookup(p, (caddr_t)frame->srr0) == (caddr_t) -1) {
+ KSI_INIT_TRAP(&ksi);
+ ksi.ksi_signo = SIGTRAP;
+ ksi.ksi_trap = EXC_PGM;
+ ksi.ksi_addr = (void *)frame->srr0;
+ ksi.ksi_code = TRAP_BRKPT;
+ (*p->p_emul->e_trapsignal)(l, &ksi);
+ } else {
+ /* skip the trap instruction */
+ frame->srr0 += 4;
+ }
+ break;
+ }
+
if (!(l->l_addr->u_pcb.pcb_flags & PCB_FPU)) {
memset(&l->l_addr->u_pcb.pcb_fpu, 0,
sizeof l->l_addr->u_pcb.pcb_fpu);
***************
*** 344,349 ****
--- 476,488 ----
ksi.ksi_signo = rv;
ksi.ksi_trap = EXC_PGM;
ksi.ksi_addr = (void *)frame->srr0;
+ if (rv == SIGTRAP) {
+ ksi.ksi_code = TRAP_BRKPT;
+ DBPRINTF(TDB_TR, ("Bpt 0x%x \n",
+ (uint)frame->srr0));
+ } else {
+ ksi.ksi_code = 0;
+ }
KERNEL_PROC_LOCK(l);
trapsignal(l, &ksi);
KERNEL_PROC_UNLOCK(l);
***************
*** 370,379 ****
goto brain_damage;
default:
brain_damage:
- printf("trap type 0x%x at 0x%lx\n", type, frame->srr0);
#ifdef DDB
if (kdb_trap(type, frame))
goto done;
#endif
#ifdef TRAP_PANICWAIT
printf("Press a key to panic.\n");
--- 509,521 ----
goto brain_damage;
default:
brain_damage:
#ifdef DDB
+ db_printf("trap type 0x%x", type);
+ db_printf("at 0x%lx\n", frame->srr0);
if (kdb_trap(type, frame))
goto done;
+ #else
+ printf("trap type 0x%x at 0x%lx\n", type, frame->srr0);
#endif
#ifdef TRAP_PANICWAIT
printf("Press a key to panic.\n");
***************
*** 428,433 ****
--- 570,581 ----
"or %0,%0,%1;"
"mtspr 0x3f2,%0;" :
"=&r" (dbreg) : "r" (mask));
+ } else {
+ int dbreg, mask = ~0x08000000;
+ __asm __volatile("mfspr %0,0x3f2;"
+ "and %0,%0,%1;"
+ "mtspr 0x3f2,%0;" :
+ "=&r" (dbreg) : "r" (mask));
}
}
else if (!ctx) {
Index: ibm40x_machdep.c
===================================================================
RCS file: /sw/cvs/NetBSD/usr/src/sys/arch/powerpc/ibm4xx/ibm40x_machdep.c,v
retrieving revision 1.1.1.1
retrieving revision 1.3
diff -c -r1.1.1.1 -r1.3
*** ibm40x_machdep.c 30 Sep 2003 16:16:55 -0000 1.1.1.1
--- ibm40x_machdep.c 13 Jan 2004 03:15:50 -0000 1.3
***************
*** 139,144 ****
--- 139,148 ----
vaddr_t msgbuf_vaddr;
+ #ifdef trpz
+ static void ibm4xx_install_extcint(void (*handler)(void));
+ #endif
+
void
ibm4xx_init_board_data(void *info_block, u_int startkernel)
{
***************
*** 170,175 ****
--- 174,183 ----
extern int tlbdmiss4xx, tlbdm4size;
extern int pitfitwdog, pitfitwdogsize;
extern int debugtrap, debugsize;
+ #ifdef trpz
+ extern int cintr, cintrsize;
+ extern void ext_cintr(void);
+ #endif
extern int errata51handler, errata51size;
#ifdef DDB
extern int ddblow, ddbsize;
***************
*** 177,182 ****
--- 185,191 ----
#ifdef IPKDB
extern int ipkdblow, ipkdbsize;
#endif
+
uintptr_t exc;
struct cpu_info * const ci = curcpu();
***************
*** 200,211 ****
--- 209,237 ----
/*
* Set up trap vectors
*/
+ #ifdef DEBUG
+ /*
+ * clear vectors set up by boot firmwares.
+ */
+ memset((void *)EXC_RSVD, 0, EXC_LAST - EXC_RSVD);
+ #endif
+
for (exc = EXC_RSVD; exc <= EXC_LAST; exc += 0x100)
switch (exc) {
default:
memcpy((void *)exc, &defaulttrap, (size_t)&defaultsize);
break;
+ case EXC_RSVD:
+ memset((void *)exc, 0, 0x100);
+ case EXC_RST:
+ #ifdef trpz
+ memcpy((void *)exc, &cintr, (size_t)&cintrsize);
+ #else
+ memcpy((void *)exc, &defaulttrap, (size_t)&defaultsize);
+ #endif
+ break;
case EXC_EXI:
+ memset((void *)exc, 0, 0x100);
/*
* This one is (potentially) installed during autoconf
*/
***************
*** 261,267 ****
break;
}
! __syncicache((void *)EXC_RST, EXC_LAST - EXC_RST + 0x100);
mtspr(SPR_EVPR, 0); /* Set Exception vector base */
consinit();
--- 287,293 ----
break;
}
! __syncicache((void *)EXC_RSVD, EXC_LAST - EXC_RSVD + 0x100);
mtspr(SPR_EVPR, 0); /* Set Exception vector base */
consinit();
***************
*** 279,289 ****
if (handler)
ibm4xx_install_extint(handler);
/*
* Now enable translation (and machine checks/recoverable interrupts).
*/
! asm volatile ("mfmsr %0; ori %0,%0,%1; mtmsr %0; isync"
! : : "r"(0), "K"(PSL_IR|PSL_DR));
/* XXXX PSL_ME - With ME set kernel gets stuck... */
KASSERT(curcpu() == ci);
--- 305,319 ----
if (handler)
ibm4xx_install_extint(handler);
+ #ifdef trpz
+ ibm4xx_install_extcint(ext_cintr);
+ #endif
+
/*
* Now enable translation (and machine checks/recoverable interrupts).
*/
! asm volatile ("mfmsr %0; ori %0,%0,%1; oris %0,%0,%2@ha; mtmsr %0; isync"
! : : "r"(0), "K"(PSL_IR|PSL_DR|PSL_ME), "J"(PSL_CE));
/* XXXX PSL_ME - With ME set kernel gets stuck... */
KASSERT(curcpu() == ci);
***************
*** 309,314 ****
--- 339,366 ----
asm volatile ("mtmsr %0" :: "r"(msr));
}
+ #ifdef trpz
+ static void
+ ibm4xx_install_extcint(void (*handler)(void))
+ {
+ extern int cintr, cintrsize;
+ extern u_long extcint_call;
+ u_long offset = (u_long)handler - (u_long)&extcint_call;
+ int msr;
+
+ #ifdef DIAGNOSTIC
+ if (offset > 0x1ffffff)
+ panic("install_extint: too far away");
+ #endif
+ asm volatile ("mfmsr %0; wrteei 0" : "=r"(msr));
+ extcint_call = (extcint_call & 0xfc000003) | offset;
+ memcpy((void *)EXC_RST, &cintr, (size_t)&cintrsize);
+ __syncicache((void *)&extcint_call, sizeof extcint_call);
+ __syncicache((void *)EXC_RST, (int)&cintrsize);
+ asm volatile ("mtmsr %0" :: "r"(msr));
+ }
+ #endif
+
/*
* Machine dependent startup code.
*/
***************
*** 347,358 ****
initmsgbuf((caddr_t)msgbuf, round_page(MSGBUFSIZE));
#endif
! printf("%s", version);
if (model != NULL)
! printf("Model: %s\n", model);
format_bytes(pbuf, sizeof(pbuf), ctob(physmem));
! printf("total memory = %s\n", pbuf);
/*
* Find out how much space we need, allocate it,
--- 399,410 ----
initmsgbuf((caddr_t)msgbuf, round_page(MSGBUFSIZE));
#endif
! aprint_normal("%s", version);
if (model != NULL)
! aprint_normal("Model: %s\n", model);
format_bytes(pbuf, sizeof(pbuf), ctob(physmem));
! aprint_normal("total memory = %s\n", pbuf);
/*
* Find out how much space we need, allocate it,
***************
*** 423,431 ****
*/
format_bytes(pbuf, sizeof(pbuf), ptoa(uvmexp.free));
! printf("avail memory = %s\n", pbuf);
format_bytes(pbuf, sizeof(pbuf), bufpages * PAGE_SIZE);
! printf("using %u buffers containing %s of memory\n", nbuf, pbuf);
/*
* Set up the buffers.
--- 475,483 ----
*/
format_bytes(pbuf, sizeof(pbuf), ptoa(uvmexp.free));
! aprint_normal("avail memory = %s\n", pbuf);
format_bytes(pbuf, sizeof(pbuf), bufpages * PAGE_SIZE);
! aprint_normal("using %u buffers containing %s of memory\n", nbuf, pbuf);
/*
* Set up the buffers.
>Release-Note:
>Audit-Trail:
From: Rin Okuyama <rokuyama@rk.phys.keio.ac.jp>
To: gnats-bugs@NetBSD.org
Cc: port-powerpc@netbsd.org
Subject: Re: port-evbppc/24096 critical 405GP/EP interrupts non-functional/
gdb/ss fails
Date: Sat, 6 Aug 2016 07:58:27 +0900
As the original submitter reported 12 years ago (!), single-stepping
of gdb(1) does not work on powerpc/ibm4xx. This is because the debug
exception is a critical interrupt on ibm4xx, and the trap handler in
ibm4xx/trap_subr.S does not treat a critical interrupt appropriately.
The original submitter proposed a fix, but it is not satisfactory for
two reasons:
(1) Implementation of process_sstep() relies on debug mode of CPU.
(process_sstep() is called from MI ptrace(2) code when PT_STEP flag is
given. gdb(1) on powerpc uses this syscall to realize single-stepping.)
Unlike booke, debug mode of ibm4xx does not check whether it runs in
privileged mode or user mode, and in kernel memory space or process
memory space. Therefore, we cannot avoid single-steping into kernel
codes, as the original submitter commented in the patch.
(2) Nested interrupts are not fully supported. Although SPRG and stack
are separated for critical and normal interrupts, this is not sufficient
to treat multiply nested interrupts. To resolve this problem, we need to
rewrite the exception handler in a similar manner to booke/trap_subr.S.
In the attached patch below, I address problem (1). I have reimplemented
process_sstep() for ibm4xx: stop using debug mode and switch to software
single-stepping, that is, insert trap instructions by hand. This is
inspired by that of mips/trap.c. As the program counter of powerpc is not
accessible, we need two breakpoints in gerenal, at (i) next to the
current address, and (ii) the address to which it can branch into. The
code to find address (ii) was taken from booke_sstep() in
booke/booke_machdep.c. I also modified the trap handler to treat the trap
exception appropriately; save ESR register for EXC_PGM.
Before this patch, please apply patches attached to port-powerpc/51366,
port-powerpc/51367, and optionally port-powerpc/51368 in advance. Then,
with this patch, single-stepping of gdb(1) works fine on ibm4xx.
This patch also contains some small cleanups for the trap handler: (a)
remove duplicated codes, and (b) do not save unnecessary ESR and DEAR
registers for EXC_ISI. But problem (2) has not been addressed yet.
In addition, ipkdb(4) is no longer supported, as it relies on debug mode
of CPU. However it was apparently broken from before, as the trap handler
does not catch the debug exception in the privilege mode.
I will also try to address problem (2), though the nested interrupts are
less problematic as we no longer relies on critical debug exception.
Thanks,
Rin
diff -Naru powerpc.orig/ibm4xx/ibm4xx_machdep.c powerpc/ibm4xx/ibm4xx_machdep.c
--- powerpc.orig/ibm4xx/ibm4xx_machdep.c 2016-07-31 20:13:36.394696083 +0900
+++ powerpc/ibm4xx/ibm4xx_machdep.c 2016-08-05 03:26:36.572823073 +0900
@@ -82,6 +82,7 @@
#include <sys/proc.h>
#include <sys/cpu.h>
#include <sys/ksyms.h>
+#include <sys/ras.h>
#include <uvm/uvm_extern.h>
@@ -98,6 +99,7 @@
#include <ipkdb/ipkdb.h>
#endif
+#include <powerpc/frame.h>
#include <machine/powerpc.h>
#include <powerpc/pcb.h>
#include <machine/trap.h>
@@ -123,38 +125,34 @@
*/
extern const uint32_t defaulttrap[], defaultsize;
extern const uint32_t sctrap[], scsize;
-extern const uint32_t alitrap[], alisize;
-extern const uint32_t dsitrap[], dsisize;
-extern const uint32_t isitrap[], isisize;
-extern const uint32_t mchktrap[], mchksize;
+extern const uint32_t accesstrap[], accesssize;
+extern const uint32_t criticaltrap[], criticalsize;
extern const uint32_t tlbimiss4xx[], tlbim4size;
extern const uint32_t tlbdmiss4xx[], tlbdm4size;
extern const uint32_t pitfitwdog[], pitfitwdogsize;
-extern const uint32_t debugtrap[], debugsize;
extern const uint32_t errata51handler[], errata51size;
-#ifdef DDB
+#if defined(DDB)
extern const uint32_t ddblow[], ddbsize;
-#endif
-#ifdef IPKDB
+#elif defined(IPKDB)
extern const uint32_t ipkdblow[], ipkdbsize;
#endif
static const struct exc_info trap_table[] = {
{ EXC_SC, sctrap, (uintptr_t)&scsize },
- { EXC_ALI, alitrap, (uintptr_t)&alisize },
- { EXC_DSI, dsitrap, (uintptr_t)&dsisize },
- { EXC_ISI, isitrap, (uintptr_t)&isisize },
- { EXC_MCHK, mchktrap, (uintptr_t)&mchksize },
+ { EXC_ALI, accesstrap, (uintptr_t)&accesssize },
+ { EXC_DSI, accesstrap, (uintptr_t)&accesssize },
+ { EXC_MCHK, criticaltrap, (uintptr_t)&criticalsize },
{ EXC_ITMISS, tlbimiss4xx, (uintptr_t)&tlbim4size },
{ EXC_DTMISS, tlbdmiss4xx, (uintptr_t)&tlbdm4size },
{ EXC_PIT, pitfitwdog, (uintptr_t)&pitfitwdogsize },
- { EXC_DEBUG, debugtrap, (uintptr_t)&debugsize },
+ { EXC_DEBUG, criticaltrap, (uintptr_t)&criticalsize },
{ (EXC_DTMISS|EXC_ALI),
errata51handler, (uintptr_t)&errata51size },
-#ifdef DDB
+#if defined(DDB)
{ EXC_PGM, ddblow, (uintptr_t)&ddbsize },
-#endif
-#ifdef IPKDB
+#elif defined(IPKDB)
{ EXC_PGM, ipkdblow, (uintptr_t)&ipkdbsize },
+#else
+ { EXC_PGM, accesstrap, (uintptr_t)&accesssize },
#endif
};
@@ -199,6 +197,7 @@
}
for (size_t i = 0; i < __arraycount(trap_table); i++) {
+ KASSERT(trap_table[i].exc_size <= 0x100);
trap_copy(trap_table[i].exc_addr, trap_table[i].exc_vector,
trap_table[i].exc_size);
}
@@ -335,3 +334,98 @@
printf("dumpsys: TBD\n");
}
+
+/*
+ * ibm4xx_sstep:
+ *
+ * Insert or remove single-step breakpoints, inspired from mips/trap.c. As we
+ * cannot reference the PC, we need two breakpoints in general, at (SRR0 + 4)
+ * and the address to which the process can branch into.
+ */
+int
+ibm4xx_sstep(struct lwp *l, int step)
+{
+ const uint32_t ppc_bp = 0x7d821008; /* twge %r2, %r2 */
+ struct trapframe * const tf = l->l_md.md_utf;
+ struct proc * const p = l->l_proc;
+ vaddr_t va[2];
+ uint32_t instr;
+ int i, rv;
+
+ if (step) {
+ if (l->l_md.md_ss_addr[0] != 0)
+ return 0; /* XXX Should we reset breakpoints? */
+
+ va[0] = (vaddr_t)tf->tf_srr0;
+ va[1] = 0;
+
+ /*
+ * Find the address to which the process can branch into.
+ * Taken from booke_sstep() in booke/booke_machdep.c.
+ */
+ if ((rv = ifetch(p, (const void *)va[0], &instr)) != 0)
+ return rv;
+ if ((instr >> 28) == 4) {
+ if ((instr >> 26) == 0x12) {
+ const int32_t off =
+ (((int32_t)instr << 6) >> 6) & ~3;
+ va[1] = ((instr & 2) ? 0 : va[0]) + off;
+ } else if ((instr >> 26) == 0x10) {
+ const int16_t off = instr & ~3;
+ va[1] = ((instr & 2) ? 0 : va[0]) + off;
+ } else if ((instr & 0xfc00fffe) == 0x4c000420) {
+ va[1] = tf->tf_ctr;
+ } else if ((instr & 0xfc00fffe) == 0x4c000020) {
+ va[1] = tf->tf_lr;
+ }
+ }
+
+ va[0] += 4;
+ if (va[1] == va[0])
+ va[1] = 0;
+
+ for (i = 0; i < 2; i++) {
+ if (va[i] == 0)
+ return 0;
+ /*
+ * We can't single-step into a RAS.
+ */
+ if (p->p_raslist != NULL &&
+ ras_lookup(p, (void *)va[i]) != (void *)-1) {
+ rv = EFAULT;
+ goto err;
+ }
+ if ((rv = ifetch(p, (const void *)va[i], &instr)))
+ goto err;
+ l->l_md.md_ss_instr[i] = instr;
+ if ((rv = istore(p, &ppc_bp, (void *)va[i]))) {
+err: /* Recover as far as possible. */
+ if (i == 1 &&
+ istore(p, &l->l_md.md_ss_instr[0],
+ (void *)va[0]) == 0)
+ l->l_md.md_ss_addr[0] = 0;
+ return rv;
+ }
+ l->l_md.md_ss_addr[i] = va[i];
+ }
+ } else {
+ for (i = 0; i < 2; i++) {
+ va[i] = l->l_md.md_ss_addr[i];
+ if (va[i] == 0)
+ return 0;
+ if ((rv = ifetch(p, (const void *)va[i], &instr)))
+ return rv;
+ if (instr != ppc_bp)
+ goto done;
+ if (p->p_raslist != NULL &&
+ ras_lookup(p, (void *)va[i]) != (void *)-1)
+ return EFAULT;
+ if ((rv = istore(p, &l->l_md.md_ss_instr[i],
+ (void *)va[i])))
+ return rv;
+done:
+ l->l_md.md_ss_addr[i] = 0;
+ }
+ }
+ return 0;
+}
diff -Naru powerpc.orig/ibm4xx/trap.c powerpc/ibm4xx/trap.c
--- powerpc.orig/ibm4xx/trap.c 2016-07-31 20:13:36.393902571 +0900
+++ powerpc/ibm4xx/trap.c 2016-08-05 03:28:23.660737676 +0900
@@ -150,7 +150,14 @@
type, tf->tf_srr0, tf, &tf));
switch (type) {
+#ifdef IPKDB
+ case EXC_DEBUG:
+#error "IPKDB support has not been implemented yet."
+#endif
case EXC_DEBUG|EXC_USER:
+#ifdef DIAGNOSTIC
+ goto brain_damage;
+#else
{
int srr2, srr3;
@@ -163,8 +170,11 @@
/*
* DEBUG intr -- probably single-step.
*/
+ /* FALLTHROUGH */
+#endif
+
case EXC_TRC|EXC_USER:
- tf->tf_srr1 &= ~PSL_SE;
+// tf->tf_srr1 &= ~PSL_SE;
KSI_INIT_TRAP(&ksi);
ksi.ksi_signo = SIGTRAP;
ksi.ksi_trap = EXC_TRC;
@@ -172,10 +182,6 @@
trapsignal(l, &ksi);
break;
- /*
- * If we could not find and install appropriate TLB entry, fall through.
- */
-
case EXC_DSI:
/* FALLTHROUGH */
case EXC_DTMISS:
@@ -206,7 +212,7 @@
rv = uvm_fault(map, trunc_page(va), ftype);
pcb->pcb_onfault = fb;
if (rv == 0)
- goto done;
+ return;
if (fb != NULL) {
tf->tf_pid = KERNEL_PID;
tf->tf_srr0 = fb->fb_pc;
@@ -217,7 +223,7 @@
tf->tf_fixreg[3] = 1; /* Return TRUE */
memcpy(&tf->tf_fixreg[13], fb->fb_fixreg,
sizeof(fb->fb_fixreg));
- goto done;
+ return;
}
}
goto brain_damage;
@@ -290,12 +296,39 @@
break;
case EXC_PGM|EXC_USER:
+ curcpu()->ci_data.cpu_ntrap++;
+
+ /*
+ * Trap exception if the ESR_PTR bit is turned on.
+ * XXX According to comment in Linux kernel source, ESR is
+ * sometimes set incorrectly on 405GP (RevD).
+ */
+ if (tf->tf_esr & ESR_PTR) {
+ vaddr_t va;
+
+trap: va = (vaddr_t)tf->tf_srr0;
+
+ KSI_INIT_TRAP(&ksi);
+ /*
+ * Restore original instruction and clear BP.
+ */
+ if ((l->l_md.md_ss_addr[0] == va ||
+ l->l_md.md_ss_addr[1] == va) &&
+ ibm4xx_sstep(l, 0))
+ ksi.ksi_signo = SIGABRT;
+ else
+ ksi.ksi_signo = SIGTRAP;
+ ksi.ksi_trap = EXC_PGM;
+ ksi.ksi_addr = (void *)tf->tf_srr0;
+ trapsignal(l, &ksi);
+ break;
+ }
+
/*
* Illegal insn:
*
* let's try to see if its FPU and can be emulated.
*/
- curcpu()->ci_data.cpu_ntrap++;
pcb = lwp_getpcb(l);
if (__predict_false(!fpu_used_p(l))) {
@@ -306,6 +339,8 @@
if (fpu_emulate(tf, &pcb->pcb_fpu, &ksi)) {
if (ksi.ksi_signo == 0) /* was emulated */
break;
+ else if (ksi.ksi_signo == SIGTRAP)
+ goto trap; /* XXX address H/W bug */
} else {
ksi.ksi_signo = SIGILL;
ksi.ksi_code = ILL_ILLOPC;
@@ -331,16 +366,17 @@
tf->tf_cr = fb->fb_cr;
memcpy(&tf->tf_fixreg[13], fb->fb_fixreg,
sizeof(fb->fb_fixreg));
- goto done;
+ return;
}
}
goto brain_damage;
+
default:
- brain_damage:
+brain_damage:
printf("trap type 0x%x at 0x%lx\n", type, tf->tf_srr0);
#if defined(DDB) || defined(KGDB)
if (kdb_trap(type, tf))
- goto done;
+ return;
#endif
#ifdef TRAP_PANICWAIT
printf("Press a key to panic.\n");
@@ -351,8 +387,6 @@
/* Invoke MI userret code */
mi_userret(l);
- done:
- return;
}
int
@@ -367,6 +401,10 @@
ctx_alloc(__UNVOLATILE(pm));
}
ctx = pm->pm_ctx;
+#if 0
+/*
+ * XXX We do not use the PSL_SE (aka PSL_DE) bit for now.
+ */
if (srr1 & PSL_SE) {
int dbreg, mask = 0x48000000;
/*
@@ -381,6 +419,7 @@
"mtspr 0x3f2,%0;" :
"=&r" (dbreg) : "r" (mask));
}
+#endif
}
else if (!ctx) {
ctx = KERNEL_PID;
@@ -682,3 +721,117 @@
return -1;
}
+
+/*
+ * ifetch and istore:
+ * fetch/store instruction from/to given process
+ */
+
+static inline int istore_once(struct proc *, const void *, void *);
+
+int
+ifetch(struct proc *p, const void *udaddr, void *kaddr)
+{
+ struct pmap *pm = p->p_vmspace->vm_map.pmap;
+ int rv, msr, pid, tmp, ctx;
+ struct faultbuf env;
+
+ if ((rv = setfault(&env)))
+ goto out;
+
+ if (!(ctx = pm->pm_ctx)) {
+ /* No context -- assign it one */
+ ctx_alloc(pm);
+ ctx = pm->pm_ctx;
+ }
+
+ __asm volatile(
+ "mfmsr %[msr];" /* Save MSR */
+ "li %[pid],0x20;"
+ "andc %[pid],%[msr],%[pid]; mtmsr %[pid];" /* Disable IMMU */
+ "mfpid %[pid];" /* Save old PID */
+ "sync; isync;"
+
+ "mtpid %[ctx]; sync;" /* Set process PID */
+ "lswi %[tmp],%[udaddr],4;" /* Load user word */
+ "sync; isync;"
+ "mtpid %[pid];sync;" /* Restore PID */
+ "stswi %[tmp],%[kaddr],4;" /* Store kernel word */
+ "dcbf 0,%[kaddr];" /* flush cache */
+ "sync; isync;"
+
+ "mtmsr %[msr]; sync; isync;" /* Restore MSR */
+ : [msr] "=&r" (msr), [pid] "=&r" (pid), [tmp] "=&r" (tmp)
+ : [udaddr] "b" (udaddr), [ctx] "b" (ctx), [kaddr] "b" (kaddr));
+
+out:
+ curpcb->pcb_onfault = NULL;
+ return rv;
+}
+
+int
+istore(struct proc *p, const void *kaddr, void *udaddr)
+{
+ vaddr_t sa, ea;
+ int rv = 0;
+
+ if (istore_once(p, kaddr, udaddr) != 0) {
+ sa = trunc_page((uint32_t)udaddr);
+ ea = round_page((uint32_t)udaddr + 4 - 1);
+ rv = uvm_map_protect(&p->p_vmspace->vm_map, sa, ea, UVM_PROT_W,
+ false);
+ if (rv == 0) {
+ rv = istore_once(p, kaddr, udaddr);
+ (void)uvm_map_protect(&p->p_vmspace->vm_map, sa, ea,
+ UVM_PROT_RX, false);
+ }
+ }
+
+ return rv;
+}
+
+static inline int
+istore_once(struct proc *p, const void *kaddr, void *udaddr)
+{
+ struct pmap *pm = p->p_vmspace->vm_map.pmap;
+ int rv, msr, pid, tmp, ctx;
+ struct faultbuf env;
+
+ if (!(ctx = pm->pm_ctx)) {
+ /* No context -- assign it one */
+ ctx_alloc(pm);
+ ctx = pm->pm_ctx;
+ }
+
+ /* Lock before write */
+ if ((rv = uvm_vslock(p->p_vmspace, udaddr, 4, VM_PROT_WRITE)))
+ return rv;
+
+ if ((rv = setfault(&env)))
+ goto out;
+
+ __asm volatile(
+ "mfmsr %[msr];" /* Save MSR */
+ "li %[pid],0x20;"
+ "andc %[pid],%[msr],%[pid]; mtmsr %[pid];" /* Disable IMMU */
+ "mfpid %[pid];" /* Save old PID */
+ "sync; isync;"
+
+ "lswi %[tmp],%[kaddr],4;" /* Load kernel word */
+ "sync; isync;"
+ "mtpid %[ctx]; sync;" /* Set process PID */
+ "stswi %[tmp],%[udaddr],4;" /* Store user word */
+ "dcbf 0,%[udaddr];" /* flush cache */
+ "sync; isync;"
+
+ "mtpid %[pid]; mtmsr %[msr];" /* Restore PID and MSR */
+ "sync; isync;"
+ : [msr] "=&r" (msr), [pid] "=&r" (pid), [tmp] "=&r" (tmp)
+ : [udaddr] "b" (udaddr), [ctx] "b" (ctx), [kaddr] "b" (kaddr));
+
+out:
+ curpcb->pcb_onfault = NULL;
+ uvm_vsunlock(p->p_vmspace, udaddr, 4);
+
+ return rv;
+}
diff -Naru powerpc.orig/ibm4xx/trap_subr.S powerpc/ibm4xx/trap_subr.S
--- powerpc.orig/ibm4xx/trap_subr.S 2016-07-31 20:13:36.394877928 +0900
+++ powerpc/ibm4xx/trap_subr.S 2016-08-05 03:16:45.623851126 +0900
@@ -105,7 +105,7 @@
mfcr %r29; /* save CR */ \
mfdear %r30; \
mfesr %r31; \
- stmw %r30,(savearea+CPUSAVE_DEAR)(%r1); \
+ stmw %r30,(savearea+CPUSAVE_DEAR)(%r1); /* save esr/dear */ \
mfsrr0 %r30; \
mfsrr1 %r31; /* Test whether we already had PR set */ \
stmw %r30,(savearea+CPUSAVE_SRR0)(%r1); /* save srr0/srr1 */ \
@@ -172,18 +172,10 @@
addi %r1,%r1,USPACE-CALLFRAMELEN; /* stack is top of user struct */ \
1:
-/*
- * This code gets copied to all the trap vectors
- * (except ISI/DSI, ALI, the interrupts, and possibly the debugging
- * traps when using IPKDB).
- */
.text
STANDARD_EXC_HANDLER(default)
- ACCESS_EXC_HANDLER(ali)
- ACCESS_EXC_HANDLER(dsi)
- ACCESS_EXC_HANDLER(isi)
- STANDARD_EXC_HANDLER(debug)
- CRITICAL_EXC_HANDLER(mchk)
+ ACCESS_EXC_HANDLER(access)
+ CRITICAL_EXC_HANDLER(critical)
/*
* This one for the external interrupt handler.
@@ -215,6 +207,9 @@
stmw %r28,(CI_TEMPSAVE+CPUSAVE_R28)(%r1); /* free r28-r31 */
mflr %r28; /* save LR */
mfcr %r29; /* save CR */
+ mfdear %r30;
+ mfesr %r31;
+ stmw %r30,(CI_TEMPSAVE+CPUSAVE_DEAR)(%r1); /* save esr/dear */
mfsrr0 %r30;
mfsrr1 %r31;
stmw %r30,(CI_TEMPSAVE+CPUSAVE_SRR0)(%r1); /* save srr0/srr1 */
@@ -258,6 +253,9 @@
stmw %r28,(CI_TEMPSAVE+CPUSAVE_R28)(%r1); /* free r28-r31 */
mflr %r28; /* save LR */
mfcr %r29; /* save CR */
+ mfdear %r30;
+ mfesr %r31;
+ stmw %r30,(CI_TEMPSAVE+CPUSAVE_DEAR)(%r1); /* save esr/dear */
mfsrr0 %r30;
mfsrr1 %r31;
stmw %r30,(CI_TEMPSAVE+CPUSAVE_SRR0)(%r1); /* save srr0/srr1 */
@@ -299,7 +297,8 @@
/*
* FRAME_SETUP assumes:
* SPRG1 SP (r1)
- * savearea r28-r31,DEAR,ESR,SRR0,SRR1 (DEAR & ESR only for DSI traps)
+ * savearea r28-r31,DEAR,ESR,SRR0,SRR1
+ * (DEAR & ESR only for access traps)
* %r28 LR
* %r29 CR
* %r1 kernel stack
diff -Naru powerpc.orig/include/ibm4xx/cpu.h powerpc/include/ibm4xx/cpu.h
--- powerpc.orig/include/ibm4xx/cpu.h 2016-07-31 20:13:36.402511505 +0900
+++ powerpc/include/ibm4xx/cpu.h 2016-08-05 03:16:45.631312149 +0900
@@ -71,6 +71,8 @@
extern void ibm4xx_cpu_startup(const char *);
extern void ibm4xx_dumpsys(void);
extern void ibm4xx_install_extint(void (*)(void));
+struct lwp;
+extern int ibm4xx_sstep(struct lwp *, int);
/* export from ibm4xx/ibm4xx_autoconf.c */
extern void ibm4xx_device_register(device_t dev, void *aux);
@@ -78,6 +80,11 @@
/* export from ibm4xx/clock.c */
extern void calc_delayconst(void);
+/* export from ibm4xx/trap.c */
+struct proc;
+extern int ifetch(struct proc *, const void *, void *);
+extern int istore(struct proc *, const void *, void *);
+
/* export from ibm4xx/4xx_locore.S */
extern void ppc4xx_reset(void) __dead;
diff -Naru powerpc.orig/include/proc.h powerpc/include/proc.h
--- powerpc.orig/include/proc.h 2016-07-31 20:13:36.401155210 +0900
+++ powerpc/include/proc.h 2016-08-05 03:29:54.286382789 +0900
@@ -41,6 +41,10 @@
volatile int md_flags;
volatile int md_astpending;
struct trapframe *md_utf; /* user trampframe */
+#ifdef PPC_IBM4XX
+ vaddr_t md_ss_addr[2]; /* single-step breakpoints */
+ uint32_t md_ss_instr[2];
+#endif
};
struct trapframe;
@@ -51,10 +55,18 @@
#ifdef _KERNEL
#define LWP0_CPU_INFO &cpu_info[0]
+# ifndef PPC_IBM4XX
#define LWP0_MD_INITIALIZER { \
.md_flags = 0, \
.md_utf = (void *)0xdeadbeef, \
}
+# else
+#define LWP0_MD_INITIALIZER { \
+ .md_flags = 0, \
+ .md_utf = (void *)0xdeadbeef, \
+ .md_ss_addr[0] = 0, \
+ }
+# endif /* PPC_IBM4XX */
#endif /* _KERNEL */
#endif /* _POWERPC_PROC_H_ */
diff -Naru powerpc.orig/include/psl.h powerpc/include/psl.h
--- powerpc.orig/include/psl.h 2016-07-31 20:13:36.401260797 +0900
+++ powerpc/include/psl.h 2016-08-05 03:34:51.984565880 +0900
@@ -121,6 +121,13 @@
#endif
#define PSL_USERMASK 0xFFFF
#define PSL_USERMOD (0)
+#if 1
+/*
+ * We do not use the PSL_DE bit; there's no way to avoid single-stepping into
+ * kernel codes with PSL_DE. Instead, we use the software single-step.
+ */
+#undef PSL_SE
+#else
/*
* We also need to override the PSL_SE bit. 4xx have completely different
* debug register support. The SE bit is actually the DWE bit. We want to
@@ -128,6 +135,7 @@
*/
#undef PSL_SE
#define PSL_SE PSL_DE
+#endif
#endif /* PPC_OEA */
#define PSL_USERSRR1 ((PSL_USERSET|PSL_USERMOD) & PSL_USERMASK)
diff -Naru powerpc.orig/powerpc/process_machdep.c powerpc/powerpc/process_machdep.c
--- powerpc.orig/powerpc/process_machdep.c 2016-07-31 20:13:36.410664919 +0900
+++ powerpc/powerpc/process_machdep.c 2016-08-05 03:35:48.099934864 +0900
@@ -51,6 +51,10 @@
#include <powerpc/altivec.h> /* also for e500 SPE */
+#ifdef PPC_IBM4XX
+#include <powerpc/ibm4xx/cpu.h>
+#endif
+
int
process_read_regs(struct lwp *l, struct reg *regs)
{
@@ -135,6 +139,7 @@
int
process_sstep(struct lwp *l, int sstep)
{
+#ifndef PPC_IBM4XX
struct trapframe * const tf = l->l_md.md_utf;
if (sstep) {
@@ -145,6 +150,12 @@
l->l_md.md_flags &= ~PSL_SE;
}
return 0;
+#else
+/*
+ * We use the software single-stepping for ibm4xx.
+ */
+ return ibm4xx_sstep(l, sstep);
+#endif
}
State-Changed-From-To: open->closed
State-Changed-By: rin@NetBSD.org
State-Changed-When: Mon, 10 May 2021 02:06:15 +0000
State-Changed-Why:
Fixed differently; we've switched to software-based single-stepping for
ibm4xx and booke:
http://www.nerv.org/netbsd/?q=id:20210306T080819Z.c681fb84c2202bf081c8a86bd4b8e409f1717611
>Unformatted:
(Contact us)
$NetBSD: query-full-pr,v 1.46 2020/01/03 16:35:01 leot Exp $
$NetBSD: gnats_config.sh,v 1.9 2014/08/02 14:16:04 spz Exp $
Copyright © 1994-2020
The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.