Port-powerpc archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: port-evbppc/24096 critical 405GP/EP interrupts non-functional/ gdb/ss fails



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
 }


Home | Main Index | Thread Index | Old Index