1 /* $NetBSD: db_interface.c,v 1.7 2026/05/22 06:15:01 skrll Exp $ */ 2 3 /* 4 * Mach Operating System 5 * Copyright (c) 1991,1990 Carnegie Mellon University 6 * All Rights Reserved. 7 * 8 * Permission to use, copy, modify and distribute this software and its 9 * documentation is hereby granted, provided that both the copyright 10 * notice and this permission notice appear in all copies of the 11 * software, derivative works or modified versions, and any portions 12 * thereof, and that both notices appear in supporting documentation. 13 * 14 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 15 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 16 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 17 * 18 * Carnegie Mellon requests users of this software to return to 19 * 20 * Software Distribution Coordinator or Software.Distribution (at) CS.CMU.EDU 21 * School of Computer Science 22 * Carnegie Mellon University 23 * Pittsburgh PA 15213-3890 24 * 25 * any improvements or extensions that they make and grant Carnegie Mellon 26 * the rights to redistribute these changes. 27 */ 28 29 #include <sys/cdefs.h> 30 __KERNEL_RCSID(0, "$NetBSD: db_interface.c,v 1.7 2026/05/22 06:15:01 skrll Exp $"); 31 32 #ifdef _KERNEL_OPT 33 #include "opt_multiprocessor.h" 34 #include "opt_kgdb.h" 35 #endif 36 37 #define __PMAP_PRIVATE 38 39 #include <sys/types.h> 40 #include <sys/param.h> 41 42 #include <sys/atomic.h> 43 #include <sys/cpu.h> 44 #include <sys/proc.h> 45 #include <sys/reboot.h> 46 #include <sys/systm.h> 47 48 #include <uvm/uvm_extern.h> 49 50 #include <dev/cons.h> 51 52 #include <machine/db_machdep.h> 53 54 #include <ddb/db_access.h> 55 #include <ddb/db_active.h> 56 #include <ddb/db_user.h> 57 #ifndef KGDB 58 #include <ddb/db_command.h> 59 #include <ddb/db_output.h> 60 #include <ddb/db_sym.h> 61 #include <ddb/db_extern.h> 62 #include <ddb/db_interface.h> 63 #include <ddb/db_lex.h> 64 #include <ddb/db_run.h> /* for db_continue_cmd() proto */ 65 #endif 66 67 #define NOCPU ~0 68 volatile u_int ddb_cpu = NOCPU; 69 70 int db_active = 0; 71 72 #ifdef _KERNEL 73 db_regs_t ddb_regs; 74 75 #ifdef MULTIPROCESSOR 76 static void db_mach_cpu_cmd(db_expr_t, bool, db_expr_t, const char *); 77 #endif 78 static void db_mach_reset_cmd(db_expr_t, bool, db_expr_t, const char *); 79 80 void db_cpuinfo_cmd(db_expr_t, bool, db_expr_t, const char *); 81 void db_tlbdump_cmd(db_expr_t, bool, db_expr_t, const char *); 82 void db_kvtophys_cmd(db_expr_t, bool, db_expr_t, const char *); 83 84 paddr_t kvtophys(vaddr_t); 85 #endif 86 87 88 const struct db_command db_machine_command_table[] = { 89 #ifdef _KERNEL 90 #ifdef MULTIPROCESSOR 91 { DDB_ADD_CMD("cpu", db_mach_cpu_cmd, 0, 92 "switch to another cpu", "cpu#", NULL) }, 93 #endif 94 { DDB_ADD_CMD("cpuinfo", db_cpuinfo_cmd, 0, 95 "Displays the cpuinfo", 96 NULL, NULL) 97 }, 98 { DDB_ADD_CMD("kvtop", db_kvtophys_cmd, 0, 99 "Print the physical address for a given kernel virtual address", 100 "address", 101 " address:\tvirtual address to look up") }, 102 { DDB_ADD_CMD("reset", db_mach_reset_cmd, CS_NOREPEAT, 103 "Initiate hardware reset", 104 NULL, NULL) }, 105 { DDB_ADD_CMD("tlb", db_tlbdump_cmd, 0, 106 "Print out TLB entries. (only works with options DEBUG)", 107 NULL, NULL) }, 108 #endif 109 { DDB_END_CMD }, 110 }; 111 112 #ifdef _KERNEL 113 114 #ifndef KGDB 115 int 116 kdb_trap(int type, db_regs_t *regs) 117 { 118 switch (type) { 119 case CAUSE_BREAKPOINT: /* breakpoint */ 120 printf("kernel: breakpoint\n"); 121 break; 122 case -1: /* keyboard interrupt */ 123 printf("kernel: kdbint trap\n"); 124 break; 125 default: 126 printf("kernel: cause %d\n", type); 127 if (db_recover != 0) { 128 db_error("Faulted in DDB; continuing...\n"); 129 /*NOTREACHED*/ 130 } 131 break; 132 } 133 134 const int s = splhigh(); 135 struct cpu_info * const ci = curcpu(); 136 137 #if defined(MULTIPROCESSOR) 138 bool first_in_ddb = false; 139 const u_int cpu_me = cpu_index(ci); 140 const u_int old_ddb_cpu = atomic_cas_uint(&ddb_cpu, NOCPU, cpu_me); 141 if (old_ddb_cpu == NOCPU) { 142 first_in_ddb = true; 143 cpu_pause_others(); 144 } else { 145 if (old_ddb_cpu != cpu_me) { 146 KASSERT(cpu_is_paused(cpu_me)); 147 cpu_pause(); 148 splx(s); 149 return 1; 150 } 151 } 152 KASSERT(!cpu_is_paused(cpu_me)); 153 #endif 154 155 ddb_regs = *regs; 156 ci->ci_ddb_regs = &ddb_regs; 157 db_active++; 158 cnpollc(true); 159 db_trap(type, 0 /*code*/); 160 cnpollc(false); 161 db_active--; 162 ci->ci_ddb_regs = NULL; 163 *regs = ddb_regs; 164 165 #if defined(MULTIPROCESSOR) 166 if (atomic_cas_uint(&ddb_cpu, cpu_me, NOCPU) == cpu_me) { 167 cpu_resume_others(); 168 } else { 169 cpu_resume(ddb_cpu); 170 if (first_in_ddb) 171 cpu_pause(); 172 } 173 #endif 174 175 splx(s); 176 return 1; 177 } 178 #endif /* !KGDB */ 179 180 181 #ifndef KGDB 182 void 183 db_tlbdump_cmd(db_expr_t addr, bool have_addr, db_expr_t count, 184 const char *modif) 185 { 186 } 187 188 void 189 db_kvtophys_cmd(db_expr_t addr, bool have_addr, db_expr_t count, 190 const char *modif) 191 { 192 193 if (!have_addr) 194 return; 195 } 196 197 198 static void 199 show_cpuinfo(struct cpu_info *kci) 200 { 201 struct cpu_info cpuinfobuf; 202 cpuid_t cpuid; 203 int i; 204 205 db_read_bytes((db_addr_t)kci, sizeof(cpuinfobuf), (char *)&cpuinfobuf); 206 207 struct cpu_info *ci = &cpuinfobuf; 208 cpuid = ci->ci_cpuid; 209 db_printf("cpu_info=%p, cpu_name=%s\n", kci, ci->ci_cpuname); 210 db_printf("%p cpu[%lu].ci_cpuid = %lu\n", 211 &ci->ci_cpuid, cpuid, ci->ci_cpuid); 212 db_printf("%p cpu[%lu].ci_curlwp = %p\n", 213 &ci->ci_curlwp, cpuid, ci->ci_curlwp); 214 for (i = 0; i < SOFTINT_COUNT; i++) { 215 db_printf("%p cpu[%lu].ci_softlwps[%d] = %p\n", 216 &ci->ci_softlwps[i], cpuid, i, ci->ci_softlwps[i]); 217 } 218 db_printf("%p cpu[%lu].ci_want_resched = %d\n", 219 &ci->ci_want_resched, cpuid, ci->ci_want_resched); 220 db_printf("%p cpu[%lu].ci_cpl = %d\n", 221 &ci->ci_cpl, cpuid, ci->ci_cpl); 222 db_printf("%p cpu[%lu].ci_softints = 0x%08x\n", 223 &ci->ci_softints, cpuid, ci->ci_softints); 224 db_printf("%p cpu[%lu].ci_intr_depth = %u\n", 225 &ci->ci_intr_depth, cpuid, ci->ci_intr_depth); 226 db_printf("%p cpu[%lu].ci_lastintr = %" PRIu64 "\n", 227 &ci->ci_lastintr, cpuid, ci->ci_lastintr); 228 db_printf("%p cpu[%lu].ci_lastintr_scheduled = %" PRIu64 "\n", 229 &ci->ci_lastintr_scheduled, cpuid, ci->ci_lastintr_scheduled); 230 } 231 232 void 233 db_cpuinfo_cmd(db_expr_t addr, bool have_addr, db_expr_t count, 234 const char *modif) 235 { 236 #ifdef MULTIPROCESSOR 237 CPU_INFO_ITERATOR cii; 238 struct cpu_info *ci; 239 bool showall = false; 240 241 if (modif != NULL) { 242 for (; *modif != '\0'; modif++) { 243 switch (*modif) { 244 case 'a': 245 showall = true; 246 break; 247 } 248 } 249 } 250 251 if (showall) { 252 for (CPU_INFO_FOREACH(cii, ci)) { 253 show_cpuinfo(ci); 254 } 255 } else 256 #endif /* MULTIPROCESSOR */ 257 show_cpuinfo(curcpu()); 258 } 259 260 261 static void 262 db_mach_reset_cmd(db_expr_t addr, bool have_addr, db_expr_t count, 263 const char *modif) 264 { 265 } 266 267 #endif /* !KGDB */ 268 269 #ifdef MULTIPROCESSOR 270 271 bool 272 ddb_running_on_this_cpu_p(void) 273 { 274 return ddb_cpu == cpu_index(curcpu()); 275 } 276 277 bool 278 ddb_running_on_any_cpu_p(void) 279 { 280 return ddb_cpu != NOCPU; 281 } 282 283 void 284 db_resume_others(void) 285 { 286 u_int cpu_me = cpu_index(curcpu()); 287 288 if (atomic_cas_uint(&ddb_cpu, cpu_me, NOCPU) == cpu_me) 289 cpu_resume_others(); 290 } 291 292 static void 293 db_mach_cpu_cmd(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif) 294 { 295 CPU_INFO_ITERATOR cii; 296 struct cpu_info *ci; 297 298 if (!have_addr) { 299 cpu_debug_dump(); 300 return; 301 } 302 for (CPU_INFO_FOREACH(cii, ci)) { 303 if (cpu_index(ci) == addr) 304 break; 305 } 306 if (ci == NULL) { 307 db_printf("CPU %ld not configured\n", (long)addr); 308 return; 309 } 310 if (ci != curcpu()) { 311 if (!cpu_is_paused(cpu_index(ci))) { 312 db_printf("CPU %ld not paused\n", (long)addr); 313 return; 314 } 315 (void)atomic_cas_uint(&ddb_cpu, cpu_index(curcpu()), cpu_index(ci)); 316 db_continue_cmd(0, false, 0, ""); 317 } 318 } 319 #endif /* MULTIPROCESSOR */ 320 321 #endif /* _KERNEL */ 322