# HG changeset patch # User Taylor R Campbell # Date 1759237896 0 # Tue Sep 30 13:11:36 2025 +0000 # Branch trunk # Node ID e2d8f31f7802ff9eea5abe327987470c09e162c6 # Parent 84d93e4dac07509dd1eb2f240eda797025d702bb # EXP-Topic riastradh-pr58010-crashmachcpu WIP: crash(8): Add support for `mach cpu N' on x86. PR bin/58010: crash(8) doesn't support `mach cpu N' to examine registers/stack of other CPUs diff -r 84d93e4dac07 -r e2d8f31f7802 usr.sbin/crash/Makefile --- a/usr.sbin/crash/Makefile Sat Sep 06 07:16:28 2025 +0000 +++ b/usr.sbin/crash/Makefile Tue Sep 30 13:11:36 2025 +0000 @@ -51,7 +51,10 @@ S= ${.CURDIR}/../../sys CPPFLAGS+= -I${.CURDIR} -I${.OBJDIR} -I${S} -fno-strict-aliasing CPPFLAGS+= -DDDB_VERBOSE_HELP -DDB_MAX_LINE=10000000 -D_KMEMUSER + +.if ${MACHINE} != "amd64" && ${MACHINE} != "i386" CPPFLAGS+= -UDB_MACHINE_COMMANDS +.endif # XXX .if ${MACHINE} == "evbppc" diff -r 84d93e4dac07 -r e2d8f31f7802 usr.sbin/crash/arch/x86.c --- a/usr.sbin/crash/arch/x86.c Sat Sep 06 07:16:28 2025 +0000 +++ b/usr.sbin/crash/arch/x86.c Tue Sep 30 13:11:36 2025 +0000 @@ -41,6 +41,7 @@ #include #include +#include #include #include #include @@ -53,6 +54,9 @@ vaddr_t vm_min_kernel_address = VM_MIN_K static struct nlist nl[] = { { .n_name = "_dumppcb" }, + { .n_name = "cpu_infos" }, + { .n_name = "cpu_info_primary" }, + { .n_name = "ncpu" }, #ifdef VM_MIN_KERNEL_ADDRESS_DEFAULT { .n_name = "vm_min_kernel_address" }, #endif @@ -60,6 +64,9 @@ static struct nlist nl[] = { }; struct pcb pcb; +struct cpu_info **cpu_infos; +struct cpu_info *cpu_info_primary_p; +int ncpu; void db_mach_init(kvm_t *kd) @@ -72,8 +79,17 @@ db_mach_init(kvm_t *kd) sizeof(pcb)) { errx(EXIT_FAILURE, "cannot read dumppcb: %s", kvm_geterr(kd)); } + if ((size_t)kvm_read(kd, nl[1].n_value, &cpu_infos, sizeof(cpu_infos)) + != sizeof(cpu_infos)) { + errx(EXIT_FAILURE, "cannot read cpu_infos: %s", kvm_geterr(kd)); + } + cpu_info_primary_p = (void *)(uintptr_t)nl[2].n_value; + if ((size_t)kvm_read(kd, nl[3].n_value, &ncpu, sizeof(ncpu)) != + sizeof(ncpu)) { + errx(EXIT_FAILURE, "cannot read ncpu: %s", kvm_geterr(kd)); + } #ifdef VM_MIN_KERNEL_ADDRESS_DEFAULT - if ((size_t)kvm_read(kd, nl[1].n_value, &vm_min_kernel_address, + if ((size_t)kvm_read(kd, nl[4].n_value, &vm_min_kernel_address, sizeof(vm_min_kernel_address)) != sizeof(vm_min_kernel_address)) { errx(EXIT_FAILURE, "cannot read vm_min_kernel_address: %s", kvm_geterr(kd)); @@ -85,3 +101,71 @@ db_mach_init(kvm_t *kd) printf("Backtrace from time of crash is available.\n"); } } + +void db_mach_cpu(db_expr_t, bool, db_expr_t, const char *); + +const struct db_command db_machine_command_table[] = { + { DDB_ADD_CMD("cpu", db_mach_cpu, 0, + "switch to another cpu", "cpu-no", NULL) }, + { DDB_END_CMD }, +}; + +static struct cpu_info * +cpu_lookup(unsigned i) +{ + struct cpu_info *ci; + + if (cpu_infos == NULL) { + if (i != 0) + return NULL; + return cpu_info_primary_p; + } + if (ncpu < 0 || i >= (unsigned)ncpu) + return NULL; + db_read_bytes((db_addr_t)(uintptr_t)&cpu_infos[i], + sizeof(ci), (char *)&ci); + return ci; +} + +void +db_mach_cpu(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif) +{ + struct cpu_info *ci; + db_regs_t *regs; + +#if 0 + if (!have_addr) { + cpu_debug_dump(); + return; + } +#endif + + if (addr < 0) { + db_printf("%ld: CPU out of range\n", addr); + return; + } + ci = cpu_lookup(addr); + if (ci == NULL) { + db_printf("CPU %ld not configured\n", addr); + return; + } +#if 0 + if (ci != curcpu()) { + if (!(ci->ci_flags & CPUF_PAUSE)) { + db_printf("CPU %ld not paused\n", addr); + return; + } + } +#endif + db_read_bytes((db_addr_t)(uintptr_t)&ci->ci_ddb_regs, + sizeof(regs), (char *)®s); + if (regs == NULL) { + db_printf("CPU %ld has no saved regs\n", addr); + return; + } + db_printf("using CPU %ld", addr); + db_read_bytes((db_addr_t)(uintptr_t)®s->tf_sp, + sizeof(ddb_regs.tf_sp), (char *)&ddb_regs.tf_sp); + db_read_bytes((db_addr_t)(uintptr_t)®s->tf_bp, + sizeof(ddb_regs.tf_bp), (char *)&ddb_regs.tf_bp); +}