1 /* $NetBSD: db_machdep.c,v 1.61 2025/03/22 10:37:19 hans Exp $ */ 2 3 /* 4 * :set tabs=4 5 * 6 * Mach Operating System 7 * Copyright (c) 1991,1990 Carnegie Mellon University 8 * All Rights Reserved. 9 * 10 * Permission to use, copy, modify and distribute this software and its 11 * documentation is hereby granted, provided that both the copyright 12 * notice and this permission notice appear in all copies of the 13 * software, derivative works or modified versions, and any portions 14 * thereof, and that both notices appear in supporting documentation. 15 * 16 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 17 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 18 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 19 * 20 * Carnegie Mellon requests users of this software to return to 21 * 22 * Software Distribution Coordinator or Software.Distribution (at) CS.CMU.EDU 23 * School of Computer Science 24 * Carnegie Mellon University 25 * Pittsburgh PA 15213-3890 26 * 27 * any improvements or extensions that they make and grant Carnegie the 28 * rights to redistribute these changes. 29 * 30 * db_interface.c,v 2.4 1991/02/05 17:11:13 mrt (CMU) 31 * 32 * VAX enhancements by cmcmanis (at) mcmanis.com no rights reserved :-) 33 * 34 */ 35 36 /* 37 * Interface to new debugger. 38 * Taken from i386 port and modified for vax. 39 */ 40 41 #include <sys/cdefs.h> 42 __KERNEL_RCSID(0, "$NetBSD: db_machdep.c,v 1.61 2025/03/22 10:37:19 hans Exp $"); 43 44 #include "opt_multiprocessor.h" 45 46 #include <sys/param.h> 47 #include <sys/systm.h> /* just for boothowto --eichin */ 48 #include <sys/cpu.h> 49 #include <sys/device.h> 50 #include <sys/intr.h> 51 #include <sys/proc.h> 52 #include <sys/reboot.h> 53 54 #include <dev/cons.h> 55 56 #include <machine/db_machdep.h> 57 #include <machine/trap.h> 58 #include <machine/frame.h> 59 #include <machine/rpb.h> 60 #include <vax/vax/gencons.h> 61 62 #include <ddb/db_active.h> 63 #include <ddb/db_sym.h> 64 #include <ddb/db_command.h> 65 #include <ddb/db_output.h> 66 #include <ddb/db_extern.h> 67 #include <ddb/db_access.h> 68 #include <ddb/db_interface.h> 69 #include <ddb/db_variables.h> 70 #include <ddb/db_proc.h> 71 72 #include "ioconf.h" 73 74 db_regs_t ddb_regs; 75 76 void kdbprinttrap(int, int); 77 78 int db_active = 0; 79 80 static int splsave; /* IPL before entering debugger */ 81 82 #ifdef MULTIPROCESSOR 83 static struct cpu_info *stopcpu; 84 /* 85 * Only the master CPU is allowed to enter DDB, but the correct frames 86 * must still be there. Keep the state-machine here. 87 */ 88 static int 89 pause_cpus(void) 90 { 91 volatile struct cpu_info *ci = curcpu(); 92 93 if (stopcpu == NULL) { 94 stopcpu = curcpu(); 95 cpu_send_ipi(IPI_DEST_ALL, IPI_DDB); 96 } 97 if ((ci->ci_flags & CI_MASTERCPU) == 0) { 98 ci->ci_flags |= CI_STOPPED; 99 while (ci->ci_flags & CI_STOPPED) 100 ; 101 return 1; 102 } else 103 return 0; 104 } 105 106 static void 107 resume_cpus(void) 108 { 109 struct cpu_info *ci; 110 int i; 111 112 stopcpu = NULL; 113 for (i = 0; i < cpu_cd.cd_ndevs; i++) { 114 if ((ci = device_lookup_private(&cpu_cd, i)) == NULL) 115 continue; 116 ci->ci_flags &= ~CI_STOPPED; 117 } 118 } 119 #endif 120 /* 121 * VAX Call frame on the stack, this from 122 * "Computer Programming and Architecture, The VAX-11" 123 * Henry Levy & Richard Eckhouse Jr. 124 * ISBN 0-932376-07-X 125 */ 126 typedef struct __vax_frame { 127 u_int vax_cond; /* condition handler */ 128 u_int vax_psw:16; /* 16 bit processor status word */ 129 u_int vax_regs:12; /* Register save mask. */ 130 u_int vax_zero:1; /* Always zero */ 131 u_int vax_calls:1; /* True if CALLS, false if CALLG */ 132 u_int vax_spa:2; /* Stack pointer alignment */ 133 u_int *vax_ap; /* argument pointer */ 134 struct __vax_frame *vax_fp; /* frame pointer of previous frame */ 135 u_int vax_pc; /* program counter */ 136 u_int vax_args[1]; /* 0 or more arguments */ 137 } VAX_CALLFRAME; 138 139 /* 140 * DDB is called by either <ESC> - D on keyboard, via a TRACE or 141 * BPT trap or from kernel, normally as a result of a panic. 142 * If it is the result of a panic, set the ddb register frame to 143 * contain the registers when panic was called. (easy to debug). 144 */ 145 void 146 kdb_trap(struct trapframe *tf) 147 { 148 int s; 149 #ifdef MULTIPROCESSOR 150 struct cpu_info *ci = curcpu(); 151 #endif 152 153 switch (tf->tf_trap) { 154 case T_BPTFLT: /* breakpoint */ 155 case T_TRCTRAP: /* single_step */ 156 break; 157 158 /* XXX todo: should be migrated to use VAX_CALLFRAME at some point */ 159 case T_KDBTRAP: 160 #ifndef MULTIPROCESSOR /* No fancy panic stack conversion here */ 161 if (panicstr) { 162 struct callsframe *pf, *df; 163 164 df = (void *)tf->tf_fp; /* start of debug's calls */ 165 pf = (void *)df->ca_fp; /* start of panic's calls */ 166 memcpy(&ddb_regs.tf_r0, &pf->ca_argno, sizeof(int) * 12); 167 ddb_regs.tf_fp = pf->ca_fp; 168 ddb_regs.tf_pc = pf->ca_pc; 169 ddb_regs.tf_ap = pf->ca_ap; 170 ddb_regs.tf_sp = (unsigned)pf; 171 ddb_regs.tf_psl = tf->tf_psl & ~0x1fffe0; 172 ddb_regs.tf_psl |= pf->ca_maskpsw & 0xffe0; 173 ddb_regs.tf_psl |= (splsave << 16); 174 } 175 #endif 176 break; 177 178 default: 179 if ((boothowto & RB_KDB) == 0) 180 return; 181 182 kdbprinttrap(tf->tf_trap, tf->tf_code); 183 if (db_recover != 0) { 184 db_error("Faulted in DDB; continuing...\n"); 185 /*NOTREACHED*/ 186 } 187 } 188 189 #ifdef MULTIPROCESSOR 190 ci->ci_ddb_regs = tf; 191 if (pause_cpus()) 192 return; 193 #endif 194 #ifndef MULTIPROCESSOR 195 if (!panicstr) 196 memcpy(&ddb_regs, tf, sizeof(struct trapframe)); 197 #else 198 memcpy(&ddb_regs, stopcpu->ci_ddb_regs, sizeof(struct trapframe)); 199 printf("stopped on CPU %d\n", stopcpu->ci_cpuid); 200 #endif 201 202 /* XXX Should switch to interrupt stack here, if needed. */ 203 204 s = splhigh(); 205 db_active++; 206 cnpollc(true); 207 db_trap(tf->tf_trap, tf->tf_code); 208 cnpollc(false); 209 db_active--; 210 splx(s); 211 212 #ifndef MULTIPROCESSOR 213 if (!panicstr) 214 memcpy(tf, &ddb_regs, sizeof(struct trapframe)); 215 #else 216 memcpy(stopcpu->ci_ddb_regs, &ddb_regs, sizeof(struct trapframe)); 217 #endif 218 tf->tf_sp = mfpr(PR_USP); 219 #ifdef MULTIPROCESSOR 220 rpb.wait = 0; 221 resume_cpus(); 222 #endif 223 } 224 225 extern const char * const traptypes[]; 226 extern int no_traps; 227 228 /* 229 * Print trap reason. 230 */ 231 void 232 kdbprinttrap(int type, int code) 233 { 234 db_printf("kernel: "); 235 if (type >= no_traps || type < 0) 236 db_printf("type %d", type); 237 else 238 db_printf("%s", traptypes[type]); 239 db_printf(" trap, code=%x\n", code); 240 } 241 242 /* 243 * Check whether an address is accessible. 244 */ 245 bool 246 db_validate_address(vaddr_t addr) 247 { 248 struct proc *p = curproc; 249 struct pmap *pmap; 250 251 if (!p || !p->p_vmspace || !p->p_vmspace->vm_map.pmap || 252 addr >= VM_MIN_KERNEL_ADDRESS) 253 pmap = pmap_kernel(); 254 else 255 pmap = p->p_vmspace->vm_map.pmap; 256 257 return (pmap_extract(pmap, addr, NULL)); 258 } 259 260 /* 261 * Read bytes from kernel address space for debugger. 262 */ 263 void 264 db_read_bytes(vaddr_t addr, size_t size, char *data) 265 { 266 if (!db_validate_address(addr)) { 267 db_printf("address 0x%lx is inaccessible\n", addr); 268 db_error(NULL); 269 /*NOTREACHED*/ 270 } 271 272 memcpy(data, (void *)addr, size); 273 } 274 275 /* 276 * Write bytes to kernel address space for debugger. 277 */ 278 void 279 db_write_bytes(vaddr_t addr, size_t size, const char *data) 280 { 281 if (!db_validate_address(addr)) { 282 db_printf("address 0x%lx is inaccessible\n", addr); 283 db_error(NULL); 284 /*NOTREACHED*/ 285 } 286 287 memcpy((void *)addr, data, size); 288 } 289 290 void 291 Debugger(void) 292 { 293 splsave = splx(0xe); /* XXX WRONG (this can lower IPL) */ 294 setsoftddb(); /* beg for debugger */ 295 splx(splsave); 296 } 297 298 /* 299 * Machine register set. 300 */ 301 const struct db_variable db_regs[] = { 302 {"r0", &ddb_regs.tf_r0, FCN_NULL}, 303 {"r1", &ddb_regs.tf_r1, FCN_NULL}, 304 {"r2", &ddb_regs.tf_r2, FCN_NULL}, 305 {"r3", &ddb_regs.tf_r3, FCN_NULL}, 306 {"r4", &ddb_regs.tf_r4, FCN_NULL}, 307 {"r5", &ddb_regs.tf_r5, FCN_NULL}, 308 {"r6", &ddb_regs.tf_r6, FCN_NULL}, 309 {"r7", &ddb_regs.tf_r7, FCN_NULL}, 310 {"r8", &ddb_regs.tf_r8, FCN_NULL}, 311 {"r9", &ddb_regs.tf_r9, FCN_NULL}, 312 {"r10", &ddb_regs.tf_r10, FCN_NULL}, 313 {"r11", &ddb_regs.tf_r11, FCN_NULL}, 314 {"ap", &ddb_regs.tf_ap, FCN_NULL}, 315 {"fp", &ddb_regs.tf_fp, FCN_NULL}, 316 {"sp", &ddb_regs.tf_sp, FCN_NULL}, 317 {"pc", &ddb_regs.tf_pc, FCN_NULL}, 318 {"psl", &ddb_regs.tf_psl, FCN_NULL}, 319 }; 320 const struct db_variable * const db_eregs = db_regs + __arraycount(db_regs); 321 322 #define IN_USERLAND(x) (((u_int)(x) & 0x80000000) == 0) 323 324 /* 325 * Dump a stack traceback. Takes two arguments: 326 * fp - CALL FRAME pointer 327 * pr - printf-like function pointer for output 328 */ 329 static void 330 db_dump_stack(VAX_CALLFRAME *fp, void (*pr)(const char *, ...)) 331 { 332 u_int nargs, arg_base; 333 VAX_CALLFRAME *tmp_frame; 334 db_expr_t diff; 335 db_sym_t sym; 336 const char *symname; 337 extern int sret; 338 extern unsigned int etext; 339 340 (*pr)("Stack traceback:\n"); 341 if (IN_USERLAND(fp)) { 342 (*pr)("\t Process is executing in user space.\n"); 343 return; 344 } 345 346 if (!db_validate_address((vaddr_t)fp)) { 347 (*pr)("\t frame 0x%x inaccessible.\n", fp); 348 return; 349 } 350 351 while (!IN_USERLAND(fp->vax_fp) && 352 db_validate_address((vaddr_t)fp->vax_fp)) { 353 u_int pc = fp->vax_pc; 354 355 /* 356 * Figure out the arguments by using a bit of subtlety. 357 * As the argument pointer may have been used as a temporary 358 * by the callee ... recreate what it would have pointed to 359 * as follows: 360 * The vax_regs value is a 12 bit bitmask of the registers 361 * that were saved on the stack, corresponding to R0 to R11. 362 * By counting those bits, we get a value for arg_base so that 363 * args[arg_base] points to the longword that identifies the 364 * number of arguments. 365 * arg_base+1 - arg_base+n are the argument pointers/contents. 366 */ 367 368 /* 369 * If this was due to a trap/fault, pull the correct pc 370 * out of the trap frame. 371 */ 372 if (pc == (u_int) &sret && fp->vax_fp != 0) { 373 struct trapframe *tf; 374 375 /* Count saved register bits */ 376 arg_base = popcount(fp->vax_regs); 377 378 tf = (struct trapframe *) &fp->vax_args[arg_base + 2]; 379 if (!db_validate_address((vaddr_t)tf)) { 380 (*pr)("0x%lx: trap frame inaccessible.\n", tf); 381 return; 382 } 383 384 (*pr)("0x%lx: trap type=0x%lx code=0x%lx pc=0x%lx " 385 "psl=0x%lx\n", tf, tf->tf_trap, tf->tf_code, 386 tf->tf_pc, tf->tf_psl); 387 pc = tf->tf_pc; 388 } 389 390 diff = INT_MAX; 391 symname = NULL; 392 if (pc >= VM_MIN_KERNEL_ADDRESS && pc < (u_int) &etext) { 393 sym = db_search_symbol(pc, DB_STGY_ANY, &diff); 394 db_symbol_values(sym, &symname, 0); 395 } 396 if (symname != NULL) 397 (*pr)("0x%lx: %s+0x%lx(", fp, symname, diff); 398 else 399 (*pr)("0x%lx: %#x(", fp, pc); 400 401 /* First get the frame that called this function ... */ 402 tmp_frame = fp->vax_fp; 403 404 /* Count saved register bits */ 405 arg_base = popcount(tmp_frame->vax_regs); 406 407 /* number of arguments is then pointed to by vax_args[arg_base] */ 408 nargs = tmp_frame->vax_args[arg_base]; 409 if (nargs) { 410 nargs--; /* reduce by one for formatting niceties */ 411 arg_base++; /* skip past the actual number of arguments */ 412 while (nargs--) 413 (*pr)("%#x,", tmp_frame->vax_args[arg_base++]); 414 415 /* now print out the last arg with closing brace and \n */ 416 (*pr)("%#x)\n", tmp_frame->vax_args[arg_base]); 417 } else 418 (*pr)("void)\n"); 419 /* move to the next frame */ 420 fp = fp->vax_fp; 421 } 422 } 423 424 static void 425 db_trace_process(struct lwp *l, struct proc *p, void (*pr)(const char *, ...)) 426 { 427 struct pcb *pcb; 428 429 KASSERT(l != NULL); 430 KASSERT(p != NULL); 431 432 if (!db_validate_address((vaddr_t)l)) { 433 (*pr)("LWP at %p inaccessible\n", l); 434 return; 435 } 436 437 if (!db_validate_address((vaddr_t)p)) { 438 (*pr)("Process at %p inaccessible\n", p); 439 return; 440 } 441 442 pcb = lwp_getpcb(l); 443 if (!db_validate_address((vaddr_t)pcb)) { 444 (*pr)("PCB at %p inaccessible\n", pcb); 445 return; 446 } 447 448 (*pr)("Process %d.%d\n", p->p_pid, l->l_lid); 449 (*pr)("\t PCB contents:\n"); 450 (*pr)(" KSP = 0x%x\n", (unsigned int)(pcb->KSP)); 451 (*pr)(" ESP = 0x%x\n", (unsigned int)(pcb->ESP)); 452 (*pr)(" SSP = 0x%x\n", (unsigned int)(pcb->SSP)); 453 (*pr)(" USP = 0x%x\n", (unsigned int)(pcb->USP)); 454 (*pr)(" R[00] = 0x%08x R[06] = 0x%08x\n", 455 (unsigned int)(pcb->R[0]), (unsigned int)(pcb->R[6])); 456 (*pr)(" R[01] = 0x%08x R[07] = 0x%08x\n", 457 (unsigned int)(pcb->R[1]), (unsigned int)(pcb->R[7])); 458 (*pr)(" R[02] = 0x%08x R[08] = 0x%08x\n", 459 (unsigned int)(pcb->R[2]), (unsigned int)(pcb->R[8])); 460 (*pr)(" R[03] = 0x%08x R[09] = 0x%08x\n", 461 (unsigned int)(pcb->R[3]), (unsigned int)(pcb->R[9])); 462 (*pr)(" R[04] = 0x%08x R[10] = 0x%08x\n", 463 (unsigned int)(pcb->R[4]), (unsigned int)(pcb->R[10])); 464 (*pr)(" R[05] = 0x%08x R[11] = 0x%08x\n", 465 (unsigned int)(pcb->R[5]), (unsigned int)(pcb->R[11])); 466 (*pr)(" AP = 0x%x\n", (unsigned int)(pcb->AP)); 467 (*pr)(" FP = 0x%x\n", (unsigned int)(pcb->FP)); 468 (*pr)(" PC = 0x%x\n", (unsigned int)(pcb->PC)); 469 (*pr)(" PSL = 0x%x\n", (unsigned int)(pcb->PSL)); 470 (*pr)(" Trap frame pointer: 0x%x\n", l->l_md.md_utf); 471 472 db_dump_stack((VAX_CALLFRAME *)(pcb->FP), pr); 473 474 return; 475 } 476 477 /* 478 * Implement the trace command which has the form: 479 * 480 * trace <-- Trace panic (same as before) 481 * trace 0x88888 <-- Trace frame whose address is 888888 482 * trace/t <-- Trace current process (0 if no current proc) 483 * trace/t 0tnn <-- Trace process nn (0t for decimal) 484 */ 485 void 486 db_stack_trace_print( 487 db_expr_t addr, /* Address parameter */ 488 bool have_addr, /* True if addr is valid */ 489 db_expr_t count, /* Optional count */ 490 const char *modif, /* pointer to flag modifier 't' */ 491 void (*pr)(const char *, ...)) /* Print function */ 492 { 493 struct lwp *l = curlwp; 494 struct proc *p = l->l_proc; 495 int trace_proc; 496 int trace_lwp; 497 const char *s; 498 499 /* Check to see if we're tracing a process or lwp */ 500 trace_proc = 0; 501 s = modif; 502 do { 503 switch (*s) { 504 case 't': 505 trace_proc++; 506 break; 507 508 case 'a': 509 trace_lwp++; 510 break; 511 } 512 } while (*s++ && !(trace_proc || trace_lwp)); 513 514 /* 515 * If we're here because of a panic, we'll always have an address of a 516 * frame. 517 * 518 * If the user typed an address, it can be one of the following: 519 * - the address of a struct lwp 520 * - the address of a struct proc 521 * - a PID, hex or decimal 522 * - the address of a frame 523 */ 524 if (have_addr) { 525 if (trace_lwp) { 526 l = (struct lwp *)addr; 527 p = l->l_proc; 528 db_trace_process(l, p, pr); 529 return; 530 } else if (trace_proc) { 531 p = db_proc_find((int)addr); 532 533 /* 534 * Try to be helpful by looking at it as if it were 535 * decimal. 536 */ 537 if (p == NULL) { 538 u_int tpid = 0; 539 u_int foo = addr; 540 541 while (foo != 0) { 542 int digit = (foo >> 28) & 0xf; 543 if (digit > 9) { 544 tpid = -1; 545 break; 546 } 547 tpid = tpid * 10 + digit; 548 foo = foo << 4; 549 } 550 p = db_proc_find(tpid); 551 } 552 553 /* Not a PID. If accessible, assume it's an address. */ 554 if (p == NULL) { 555 if (db_validate_address(addr)) { 556 p = (struct proc *)addr; 557 } else { 558 (*pr)("\t No such process.\n"); 559 return; 560 } 561 } 562 563 db_trace_process(p->p_lwps.lh_first, p, pr); 564 return; 565 } else { 566 db_dump_stack((VAX_CALLFRAME *)addr, pr); 567 return; 568 } 569 } else { 570 /* We got no address. Grab stuff from ddb_regs. */ 571 if (panicstr) 572 db_dump_stack((VAX_CALLFRAME *)ddb_regs.tf_fp, pr); 573 else 574 (*pr)("\t trace what?\n"); 575 } 576 } 577 578 static int ddbescape = 0; 579 580 int 581 kdbrint(int tkn) 582 { 583 if (ddbescape && ((tkn & 0x7f) == 'D')) { 584 setsoftddb(); 585 ddbescape = 0; 586 return 1; 587 } 588 589 if ((ddbescape == 0) && ((tkn & 0x7f) == 27)) { 590 ddbescape = 1; 591 return 1; 592 } 593 594 if (ddbescape) { 595 ddbescape = 0; 596 return 2; 597 } 598 599 ddbescape = 0; 600 return 0; 601 } 602 603 #ifdef MULTIPROCESSOR 604 605 static void 606 db_mach_cpu(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif) 607 { 608 struct cpu_info *ci; 609 610 if ((addr < 0) || (addr >= cpu_cd.cd_ndevs)) 611 return db_printf("%ld: CPU out of range\n", addr); 612 if ((ci = device_lookup_private(&cpu_cd, addr)) == NULL) 613 return db_printf("%ld: CPU not configured\n", addr); 614 615 if ((ci != curcpu()) && ((ci->ci_flags & CI_STOPPED) == 0)) 616 return db_printf("CPU %ld not stopped???\n", addr); 617 618 memcpy(stopcpu->ci_ddb_regs, &ddb_regs, sizeof(struct trapframe)); 619 stopcpu = ci; 620 memcpy(&ddb_regs, stopcpu->ci_ddb_regs, sizeof(struct trapframe)); 621 db_printf("using CPU %ld", addr); 622 if (ci->ci_curlwp) 623 db_printf(" in proc %d.%d (%s)\n", 624 ci->ci_curlwp->l_proc->p_pid, 625 ci->ci_curlwp->l_lid, 626 ci->ci_curlwp->l_proc->p_comm); 627 } 628 #endif 629 630 const struct db_command db_machine_command_table[] = { 631 #ifdef MULTIPROCESSOR 632 { DDB_ADD_CMD("cpu", db_mach_cpu, 0, 633 "switch to another cpu", "cpu-no", NULL) }, 634 #endif 635 { DDB_END_CMD }, 636 }; 637