The branch main has been updated by jhibbits: URL: https://cgit.FreeBSD.org/src/commit/?id=5aeedaf7204a97b88f04d6a1890dfd1ff02d6101
commit 5aeedaf7204a97b88f04d6a1890dfd1ff02d6101 Author: Justin Hibbits <[email protected]> AuthorDate: 2026-09-05 04:03:11 +0000 Commit: Justin Hibbits <[email protected]> CommitDate: 2026-09-05 04:11:57 +0000 powerpc/ddb: Dump more state in `show pcpu` Add a new CPU-family `show pcpu` handler, cpu_db_show_mdpcpu() to dump CPU-specific PCPU data. Only Book-E is populated for now, but AIM may be populated later. These new field prints: save areas, TLB miss nesting, the new critical stack pointer. All of them have been very useful for debugging very esoteric bugs, so make them easier to see from DDB, instead of having to rummage through hex dumps. --- sys/powerpc/aim/aim_machdep.c | 7 ++++++ sys/powerpc/booke/booke_machdep.c | 48 ++++++++++++++++++++++++++++++++++++++ sys/powerpc/include/md_var.h | 5 ++++ sys/powerpc/powerpc/db_interface.c | 7 ++++++ 4 files changed, 67 insertions(+) diff --git a/sys/powerpc/aim/aim_machdep.c b/sys/powerpc/aim/aim_machdep.c index 814c679ff47e..2dbd087c8f4e 100644 --- a/sys/powerpc/aim/aim_machdep.c +++ b/sys/powerpc/aim/aim_machdep.c @@ -541,6 +541,13 @@ memcpy(pcpu->pc_aim.slb, PCPU_GET(aim.slb), sizeof(pcpu->pc_aim.slb)); #endif } +#ifdef DDB +void +cpu_db_show_mdpcpu(struct pcpu *pc) +{ +} +#endif + /* Return 0 on handled success, otherwise signal number. */ int cpu_machine_check(struct thread *td, struct trapframe *frame, int *ucode) diff --git a/sys/powerpc/booke/booke_machdep.c b/sys/powerpc/booke/booke_machdep.c index 99b14bc9e974..58b847766d46 100644 --- a/sys/powerpc/booke/booke_machdep.c +++ b/sys/powerpc/booke/booke_machdep.c @@ -426,6 +426,54 @@ cpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t sz) #endif } +#ifdef DDB +/* + * Dump an exception save area. In a nested save, R31 holds the DEAR of the + * outer exception. + */ +static void +db_show_booke_save(const char *name, register_t *sv) +{ + + db_printf("%s r30 %#jx r31 %#jx dear %#jx esr %#jx\n", name, + (uintmax_t)sv[CPUSAVE_R30], (uintmax_t)sv[CPUSAVE_R31], + (uintmax_t)sv[CPUSAVE_BOOKE_DEAR], + (uintmax_t)sv[CPUSAVE_BOOKE_ESR]); + db_printf("%s srr0 %#jx srr1 %#jx\n", name, + (uintmax_t)sv[CPUSAVE_SRR0], (uintmax_t)sv[CPUSAVE_SRR1]); +} + +void +cpu_db_show_mdpcpu(struct pcpu *pc) +{ + register_t *tlbsave; + int i; + + db_printf("tid_next = %d tlb_level = %#jx critstack = %p\n", + pc->pc_booke.tid_next, (uintmax_t)pc->pc_booke.tlb_level, + pc->pc_booke.critstack); + db_show_booke_save("tempsave", pc->pc_tempsave); + db_show_booke_save("disisave", pc->pc_disisave); + db_show_booke_save("critsave", pc->pc_booke.critsave); + /* + * In critsave, CPUSAVE_SRR0-1 hold the interrupt's own CSRR0-1 (DSRR0-1 + * for the enhanced-debug vector); the non-critical SRR0-1 that were + * live at the time are kept separately. + */ + db_printf("critsave held srr0 %#jx srr1 %#jx\n", + (uintmax_t)pc->pc_booke.critsave[BOOKE_CRITSAVE_SRR0], + (uintmax_t)pc->pc_booke.critsave[BOOKE_CRITSAVE_SRR1]); + db_show_booke_save("mchksave", pc->pc_booke.mchksave); + for (i = 0; i < BOOKE_TLB_MAXNEST && + i < (int)pc->pc_booke.tlb_level; i++) { + tlbsave = &pc->pc_booke.tlbsave[i * BOOKE_TLB_SAVELEN]; + db_printf("tlbsave%d srr0 %#jx srr1 %#jx\n", i, + (uintmax_t)tlbsave[TLBSAVE_BOOKE_SRR0], + (uintmax_t)tlbsave[TLBSAVE_BOOKE_SRR1]); + } +} +#endif /* DDB */ + /* Shutdown the CPU as much as possible. */ void cpu_halt(void) diff --git a/sys/powerpc/include/md_var.h b/sys/powerpc/include/md_var.h index e995f0a91b63..b51d779fbd0f 100644 --- a/sys/powerpc/include/md_var.h +++ b/sys/powerpc/include/md_var.h @@ -68,4 +68,9 @@ void cpu_setup(u_int); struct trapframe; void powerpc_interrupt(struct trapframe *); +/* Platform half of DDB 'show pcpu' (db_show_mdpcpu) */ +struct pcpu; +void cpu_db_show_mdpcpu(struct pcpu *); + + #endif /* !_MACHINE_MD_VAR_H_ */ diff --git a/sys/powerpc/powerpc/db_interface.c b/sys/powerpc/powerpc/db_interface.c index 158578d7a27d..f0da39ba93ec 100644 --- a/sys/powerpc/powerpc/db_interface.c +++ b/sys/powerpc/powerpc/db_interface.c @@ -86,8 +86,15 @@ db_write_bytes(vm_offset_t addr, size_t size, char *data) void db_show_mdpcpu(struct pcpu *pc) { + struct thread *td; db_printf("PPC: hwref = %#zx\n", pc->pc_hwref); db_printf("PPC: ipimask = %#x\n", pc->pc_ipimask); db_printf("PPC: flags = %#x\n", pc->pc_flags); + td = pc->pc_curthread; + if (td != NULL) + db_printf("PPC: spinlocks = %d saved_msr = %#jx\n", + td->td_md.md_spinlock_count, + (uintmax_t)td->td_md.md_saved_msr); + cpu_db_show_mdpcpu(pc); }
