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:

NetBSD Home
NetBSD PR Database Search

(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.