Index: sys/arch/powerpc/booke/trap.c =================================================================== RCS file: /home/netbsd/src/sys/arch/powerpc/booke/trap.c,v retrieving revision 1.36 diff -p -u -r1.36 trap.c --- sys/arch/powerpc/booke/trap.c 6 Jan 2021 08:04:57 -0000 1.36 +++ sys/arch/powerpc/booke/trap.c 6 Feb 2021 12:00:02 -0000 @@ -47,6 +47,7 @@ __KERNEL_RCSID(1, "$NetBSD: trap.c,v 1.3 #include #include #include +#include #include #include #include @@ -461,11 +462,31 @@ pgm_exception(struct trapframe *tf, ksig ci->ci_ev_pgm.ev_count++; + KSI_INIT_TRAP(ksi); + if (tf->tf_esr & ESR_PTR) { - struct proc *p = curlwp->l_proc; - if (p->p_raslist != NULL - && ras_lookup(p, (void *)tf->tf_srr0) != (void *) -1) { - tf->tf_srr0 += 4; + struct lwp * const l = curlwp; + struct proc * const p = curlwp->l_proc; + vaddr_t va = (vaddr_t)tf->tf_srr0; + int error; + + /* + * Restore original instruction and clear BP. + */ + if (p->p_md.md_ss_addr[0] == va || + p->p_md.md_ss_addr[1] == va) { + error = ppc_sstep(l, 0); + if (error != 0) { + vm_signal(error, EXC_PGM /* XXX */, va, ksi); + return error; + } + ksi->ksi_code = TRAP_TRACE; + } else + ksi->ksi_code = TRAP_BRKPT; + + if (p->p_raslist != NULL && + ras_lookup(p, (void *)va) != (void *)-1) { + tf->tf_srr0 += (ksi->ksi_code == TRAP_TRACE) ? 0 : 4; return 0; } } @@ -494,7 +515,6 @@ pgm_exception(struct trapframe *tf, ksig } } - KSI_INIT_TRAP(ksi); ksi->ksi_signo = SIGILL; ksi->ksi_trap = EXC_PGM; if (tf->tf_esr & ESR_PIL) { @@ -503,7 +523,6 @@ pgm_exception(struct trapframe *tf, ksig ksi->ksi_code = ILL_PRVOPC; } else if (tf->tf_esr & ESR_PTR) { ksi->ksi_signo = SIGTRAP; - ksi->ksi_code = TRAP_BRKPT; } else { ksi->ksi_code = 0; } @@ -511,6 +530,7 @@ pgm_exception(struct trapframe *tf, ksig return rv; } +#if 0 static int debug_exception(struct trapframe *tf, ksiginfo_t *ksi) { @@ -545,6 +565,7 @@ debug_exception(struct trapframe *tf, ks ksi->ksi_code = TRAP_TRACE; return rv; } +#endif static int ali_exception(struct trapframe *tf, ksiginfo_t *ksi) @@ -752,6 +773,7 @@ trap(enum ppc_booke_exceptions trap_code switch (trap_code) { case T_CRITIAL_INPUT: case T_EXTERNAL_INPUT: + case T_DEBUG: case T_DECREMENTER: case T_FIXED_INTERVAL: case T_WATCHDOG: @@ -791,6 +813,7 @@ trap(enum ppc_booke_exceptions trap_code case T_INSTRUCTION_TLB_ERROR: rv = itlb_exception(tf, &ksi); break; +#if 0 case T_DEBUG: #ifdef DDB if (!usertrap && ddb_exception(tf)) @@ -798,6 +821,7 @@ trap(enum ppc_booke_exceptions trap_code #endif rv = debug_exception(tf, &ksi); break; +#endif case T_EMBEDDED_FP_DATA: rv = embedded_fp_data_exception(tf, &ksi); break; Index: sys/arch/powerpc/ibm4xx/ibm4xx_machdep.c =================================================================== RCS file: /home/netbsd/src/sys/arch/powerpc/ibm4xx/ibm4xx_machdep.c,v retrieving revision 1.34 diff -p -u -r1.34 ibm4xx_machdep.c --- sys/arch/powerpc/ibm4xx/ibm4xx_machdep.c 18 Jan 2021 02:43:27 -0000 1.34 +++ sys/arch/powerpc/ibm4xx/ibm4xx_machdep.c 6 Feb 2021 12:00:02 -0000 @@ -148,6 +154,8 @@ static const struct exc_info trap_table[ errata51handler, (uintptr_t)&errata51size }, #if defined(DDB) { EXC_PGM, ddblow, (uintptr_t)&ddbsize }, +#else + { EXC_PGM, accesstrap, (uintptr_t)&accesssize }, #endif }; Index: sys/arch/powerpc/ibm4xx/trap.c =================================================================== RCS file: /home/netbsd/src/sys/arch/powerpc/ibm4xx/trap.c,v retrieving revision 1.85 diff -p -u -r1.85 trap.c --- sys/arch/powerpc/ibm4xx/trap.c 15 Jul 2020 09:10:14 -0000 1.85 +++ sys/arch/powerpc/ibm4xx/trap.c 6 Feb 2021 12:00:02 -0000 @@ -81,6 +81,7 @@ __KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.8 #include #include #include +#include #include #include #include @@ -157,20 +158,10 @@ trap(struct trapframe *tf) switch (type) { case EXC_DEBUG|EXC_USER: - { - int srr2, srr3; + /* We don't use hardware breakpoints for userland. */ + goto brain_damage; - __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. - */ case EXC_TRC|EXC_USER: - tf->tf_srr1 &= ~PSL_SE; KSI_INIT_TRAP(&ksi); ksi.ksi_signo = SIGTRAP; ksi.ksi_trap = EXC_TRC; @@ -317,13 +308,26 @@ isi: ksi.ksi_addr = (void *)tf->tf_srr0; if (tf->tf_esr & ESR_PTR) { + vaddr_t va; sigtrap: + va = (vaddr_t)tf->tf_srr0; + /* + * Restore original instruction and clear BP. + */ + if (p->p_md.md_ss_addr[0] == va || + p->p_md.md_ss_addr[1] == va) { + rv = ppc_sstep(l, 0); + if (rv != 0) + goto vm_signal; + ksi.ksi_code = TRAP_TRACE; + } else + ksi.ksi_code = TRAP_BRKPT; if (p->p_raslist != NULL && - ras_lookup(p, (void *)tf->tf_srr0) != (void *) -1) { - tf->tf_srr1 += 4; + ras_lookup(p, (void *)va) != (void *)-1) { + tf->tf_srr0 += (ksi.ksi_code == TRAP_TRACE) ? + 0 : 4; break; } - ksi.ksi_code = TRAP_BRKPT; ksi.ksi_signo = SIGTRAP; } else if (tf->tf_esr & ESR_PPR) { uint32_t opcode; @@ -411,20 +415,6 @@ ctx_setup(int ctx, int srr1) ctx_alloc(__UNVOLATILE(pm)); } ctx = pm->pm_ctx; - if (srr1 & PSL_SE) { - int dbreg, mask = 0x48000000; - /* - * Set the Internal Debug and - * Instruction Completion bits of - * the DBCR0 register. - * - * XXX this is also used by jtag debuggers... - */ - __asm volatile("mfspr %0,0x3f2;" - "or %0,%0,%1;" - "mtspr 0x3f2,%0;" : - "=&r" (dbreg) : "r" (mask)); - } } else if (!ctx) { ctx = KERNEL_PID; Index: sys/arch/powerpc/include/proc.h =================================================================== RCS file: /home/netbsd/src/sys/arch/powerpc/include/proc.h,v retrieving revision 1.13 diff -p -u -r1.13 proc.h --- sys/arch/powerpc/include/proc.h 23 Aug 2013 06:19:46 -0000 1.13 +++ sys/arch/powerpc/include/proc.h 6 Feb 2021 12:00:02 -0000 @@ -34,6 +34,11 @@ #ifndef _POWERPC_PROC_H_ #define _POWERPC_PROC_H_ +#ifdef _KERNEL_OPT +#include "opt_modular.h" +#include "opt_ppcarch.h" +#endif + /* * Machine-dependent part of the lwp structure */ @@ -47,6 +52,11 @@ struct trapframe; struct mdproc { void (*md_syscall)(struct trapframe *); +#if defined(PPC_BOOKE) || defined(PPC_IBM4XX) || \ + defined(MODULAR) || defined(_MODULE) + vaddr_t md_ss_addr[2]; + uint32_t md_ss_insn[2]; +#endif }; #ifdef _KERNEL Index: sys/arch/powerpc/include/psl.h =================================================================== RCS file: /home/netbsd/src/sys/arch/powerpc/include/psl.h,v retrieving revision 1.21 diff -p -u -r1.21 psl.h --- sys/arch/powerpc/include/psl.h 6 Jul 2020 09:34:17 -0000 1.21 +++ sys/arch/powerpc/include/psl.h 6 Feb 2021 12:00:02 -0000 @@ -111,7 +111,7 @@ extern register_t cpu_psluserset, cpu_ps #define PSL_USERMOD cpu_pslusermod #define PSL_USERMASK cpu_pslusermask #elif defined(PPC_BOOKE) -#define PSL_USERSET (PSL_EE | PSL_PR | PSL_IS | PSL_DS | PSL_ME | PSL_CE | PSL_DE) +#define PSL_USERSET (PSL_EE | PSL_PR | PSL_IS | PSL_DS | PSL_ME | PSL_CE) #define PSL_USERMASK (PSL_SPV | PSL_CE | 0xFFFF) #define PSL_USERMOD (0) #else /* PPC_IBM4XX */ @@ -122,14 +122,7 @@ extern register_t cpu_psluserset, cpu_ps #endif #define PSL_USERMASK 0xFFFF #define PSL_USERMOD (0) -/* - * 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 - * set the DE bit to enable the debug regs instead of the DWE bit. - */ -#undef PSL_SE -#define PSL_SE PSL_DE -#endif /* PPC_OEA */ +#endif #define PSL_USERSRR1 ((PSL_USERSET|PSL_USERMOD) & PSL_USERMASK) #define PSL_USEROK_P(psl) (((psl) & ~PSL_USERMOD) == PSL_USERSET) Index: sys/arch/powerpc/include/ptrace.h =================================================================== RCS file: /home/netbsd/src/sys/arch/powerpc/include/ptrace.h,v retrieving revision 1.18 diff -p -u -r1.18 ptrace.h --- sys/arch/powerpc/include/ptrace.h 15 Oct 2020 17:37:35 -0000 1.18 +++ sys/arch/powerpc/include/ptrace.h 6 Feb 2021 12:00:02 -0000 @@ -69,6 +69,10 @@ int procfs_machdep_dovecregs(struct lwp int procfs_machdep_validvecregs(struct lwp *, struct mount *); #endif /* ALTIVEC || PPC_HAVE_SPE */ + +#if defined(PPC_BOOKE) || defined(PPC_IBM4XX) +int ppc_sstep(struct lwp *, int); +#endif /* PPC_BOOKE || PPC_IBM4XX */ #endif /* _KERNEL */ #define PTRACE_ILLEGAL_ASM __asm __volatile (".long 0" : : : "memory") Index: sys/arch/powerpc/powerpc/locore_subr.S =================================================================== RCS file: /home/netbsd/src/sys/arch/powerpc/powerpc/locore_subr.S,v retrieving revision 1.63 diff -p -u -r1.63 locore_subr.S --- sys/arch/powerpc/powerpc/locore_subr.S 6 Jul 2020 11:06:52 -0000 1.63 +++ sys/arch/powerpc/powerpc/locore_subr.S 6 Feb 2021 12:00:02 -0000 @@ -175,9 +175,6 @@ ENTRY(cpu_switchto) mfmsr %r0 andis. %r0,%r0,PSL_CE@h tweqi %r0,0 - mfmsr %r0 - andi. %r0,%r0,PSL_DE@l - tweqi %r0,0 #endif #if defined (PPC_OEA) || defined (PPC_OEA64_BRIDGE) @@ -510,8 +507,6 @@ _ENTRY(cpu_lwp_bootstrap) ori %r30, %r30, 0xbeeffeed@l andis. %r0,%r31,PSL_CE@h tweqi %r0,0 - andi. %r0,%r31,PSL_DE@l - tweqi %r0,0 #endif li %r4, 1 /* make sure userret gets called */ stint %r4, L_MD_ASTPENDING(%r13) Index: sys/arch/powerpc/powerpc/powerpc_machdep.c =================================================================== RCS file: /home/netbsd/src/sys/arch/powerpc/powerpc/powerpc_machdep.c,v retrieving revision 1.80 diff -p -u -r1.80 powerpc_machdep.c --- sys/arch/powerpc/powerpc/powerpc_machdep.c 15 Jul 2020 08:58:52 -0000 1.80 +++ sys/arch/powerpc/powerpc/powerpc_machdep.c 6 Feb 2021 12:00:02 -0000 @@ -160,6 +160,11 @@ setregs(struct lwp *l, struct exec_packa tf->tf_vrsave = 0; #endif pcb->pcb_flags = PSL_FE_DFLT; + +#if defined(PPC_BOOKE) || defined(PPC_IBM4XX) + p->p_md.md_ss_addr[0] = p->p_md.md_ss_addr[1] = 0; + p->p_md.md_ss_insn[0] = p->p_md.md_ss_insn[1] = 0; +#endif } /* Index: sys/arch/powerpc/powerpc/process_machdep.c =================================================================== RCS file: /home/netbsd/src/sys/arch/powerpc/powerpc/process_machdep.c,v retrieving revision 1.41 diff -p -u -r1.41 process_machdep.c --- sys/arch/powerpc/powerpc/process_machdep.c 15 Oct 2020 18:57:16 -0000 1.41 +++ sys/arch/powerpc/powerpc/process_machdep.c 26 Feb 2021 08:32:29 -0000 @@ -36,6 +36,7 @@ __KERNEL_RCSID(0, "$NetBSD: process_mach #ifdef _KERNEL_OPT #include "opt_altivec.h" +#include "opt_ppcarch.h" #endif #include @@ -132,6 +133,7 @@ process_set_pc(struct lwp *l, void *addr int process_sstep(struct lwp *l, int sstep) { +#if !defined(PPC_BOOKE) && !defined(PPC_IBM4XX) struct trapframe * const tf = l->l_md.md_utf; if (sstep) { @@ -142,6 +144,12 @@ process_sstep(struct lwp *l, int sstep) l->l_md.md_flags &= ~PSL_SE; } return 0; +#else +/* + * We use the software single-stepping for booke/ibm4xx. + */ + return ppc_sstep(l, sstep); +#endif } @@ -274,3 +282,127 @@ process_machdep_validvecregs(struct proc #endif } #endif /* __HAVE_PTRACE_MACHDEP */ + +#if defined(PPC_BOOKE) || defined(PPC_IBM4XX) +/* + * ppc_ifetch and ppc_istore: + * fetch/store instructions from/to given process (therefore, we cannot use + * ufetch/ustore(9) here). + */ + +static int +ppc_ifetch(struct lwp *l, vaddr_t va, uint32_t *insn) +{ + struct uio uio; + struct iovec iov; + + iov.iov_base = insn; + iov.iov_len = sizeof(*insn); + uio.uio_iov = &iov; + uio.uio_iovcnt = 1; + uio.uio_offset = (off_t)va; + uio.uio_resid = sizeof(*insn); + uio.uio_rw = UIO_READ; + UIO_SETUP_SYSSPACE(&uio); + + return process_domem(curlwp, l, &uio); +} + +static int +ppc_istore(struct lwp *l, vaddr_t va, uint32_t insn) +{ + struct uio uio; + struct iovec iov; + + iov.iov_base = &insn; + iov.iov_len = sizeof(insn); + uio.uio_iov = &iov; + uio.uio_iovcnt = 1; + uio.uio_offset = (off_t)va; + uio.uio_resid = sizeof(insn); + uio.uio_rw = UIO_WRITE; + UIO_SETUP_SYSSPACE(&uio); + + return process_domem(curlwp, l, &uio); +} + +/* + * Insert or remove single-step breakpoints: + * We need two breakpoints, in general, at (SRR0 + 4) and the address to + * which the process can branch into. + */ + +int +ppc_sstep(struct lwp *l, int step) +{ + struct trapframe * const tf = l->l_md.md_utf; + struct proc * const p = l->l_proc; + const uint32_t trap = 0x7d821008; /* twge %r2, %r2 */ + uint32_t insn; + vaddr_t va[2]; + int i, rv; + + if (step) { + if (p->p_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. + */ + if ((rv = ppc_ifetch(l, va[0], &insn)) != 0) + return rv; + if ((insn >> 28) == 4) { + if ((insn >> 26) == 0x12) { + const int32_t off = + ((int32_t)(insn << 6) >> 6) & ~3; + va[1] = ((insn & 2) ? 0 : va[0]) + off; + } else if ((insn >> 26) == 0x10) { + const int16_t off = (int16_t)insn & ~3; + va[1] = ((insn & 2) ? 0 : va[0]) + off; + } else if ((insn & 0xfc00fffe) == 0x4c000420) + va[1] = tf->tf_ctr; + else if ((insn & 0xfc00fffe) == 0x4c000020) + va[1] = tf->tf_lr; + } + va[0] += sizeof(insn); + if (va[1] == va[0]) + va[1] = 0; + + for (i = 0; i < 2; i++) { + if (va[i] == 0) + return 0; + if ((rv = ppc_ifetch(l, va[i], &insn)) != 0) + goto error; + p->p_md.md_ss_insn[i] = insn; + if ((rv = ppc_istore(l, va[i], trap)) != 0) { +error: /* Recover as far as possible. */ + if (i == 1 && ppc_istore(l, va[0], + p->p_md.md_ss_insn[0]) == 0) + p->p_md.md_ss_addr[0] = 0; + return rv; + } + p->p_md.md_ss_addr[i] = va[i]; + } + } else { + for (i = 0; i < 2; i++) { + va[i] = p->p_md.md_ss_addr[i]; + if (va[i] == 0) + return 0; + if ((rv = ppc_ifetch(l, va[i], &insn)) != 0) + return rv; + if (insn != trap) { + panic("%s: ss_insn[%d] = 0x%x != trap", + __func__, i, insn); + } + if ((rv = ppc_istore(l, va[i], p->p_md.md_ss_insn[i])) + != 0) + return rv; + p->p_md.md_ss_addr[i] = 0; + } + } + return 0; +} +#endif /* PPC_BOOKE || PPC_IBM4XX */