1 /* $NetBSD: db_machdep.c,v 1.33 2002/05/13 20:30:13 matt 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@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@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 #include "opt_ddb.h" 41 #include "opt_multiprocessor.h" 42 43 #include <sys/param.h> 44 #include <sys/proc.h> 45 #include <sys/user.h> 46 #include <sys/reboot.h> 47 #include <sys/systm.h> /* just for boothowto --eichin */ 48 49 #include <uvm/uvm_extern.h> 50 51 #include <dev/cons.h> 52 53 #include <machine/cpu.h> 54 #include <machine/db_machdep.h> 55 #include <machine/trap.h> 56 #include <machine/frame.h> 57 #include <machine/pcb.h> 58 #include <machine/intr.h> 59 #include <machine/rpb.h> 60 #include <vax/vax/gencons.h> 61 62 #include <ddb/db_sym.h> 63 #include <ddb/db_command.h> 64 #include <ddb/db_output.h> 65 #include <ddb/db_extern.h> 66 #include <ddb/db_access.h> 67 #include <ddb/db_interface.h> 68 #include <ddb/db_variables.h> 69 70 #include "ioconf.h" 71 72 db_regs_t ddb_regs; 73 74 void kdbprinttrap(int, int); 75 76 int db_active = 0; 77 78 extern int qdpolling; 79 static int splsave; /* IPL before entering debugger */ 80 81 #ifdef MULTIPROCESSOR 82 static struct cpu_info *stopcpu; 83 /* 84 * Only the master CPU is allowed to enter DDB, but the correct frames 85 * must still be there. Keep the state-machine here. 86 */ 87 static int 88 pause_cpus(void) 89 { 90 volatile struct cpu_info *ci = curcpu(); 91 92 if (stopcpu == NULL) { 93 stopcpu = curcpu(); 94 cpu_send_ipi(IPI_DEST_ALL, IPI_DDB); 95 } 96 if ((ci->ci_flags & CI_MASTERCPU) == 0) { 97 ci->ci_flags |= CI_STOPPED; 98 while (ci->ci_flags & CI_STOPPED) 99 ; 100 return 1; 101 } else 102 return 0; 103 } 104 105 static void 106 resume_cpus(void) 107 { 108 struct cpu_mp_softc *sc; 109 struct cpu_info *ci; 110 int i; 111 112 stopcpu = NULL; 113 for (i = 0; i < cpu_cd.cd_ndevs; i++) { 114 if ((sc = cpu_cd.cd_devs[i]) == NULL) 115 continue; 116 ci = &sc->sc_ci; 117 ci->ci_flags &= ~CI_STOPPED; 118 } 119 } 120 #endif 121 /* 122 * VAX Call frame on the stack, this from 123 * "Computer Programming and Architecture, The VAX-11" 124 * Henry Levy & Richard Eckhouse Jr. 125 * ISBN 0-932376-07-X 126 */ 127 typedef struct __vax_frame { 128 u_int vax_cond; /* condition handler */ 129 u_int vax_psw:16; /* 16 bit processor status word */ 130 u_int vax_regs:12; /* Register save mask. */ 131 u_int vax_zero:1; /* Always zero */ 132 u_int vax_calls:1; /* True if CALLS, false if CALLG */ 133 u_int vax_spa:2; /* Stack pointer alignment */ 134 u_int *vax_ap; /* argument pointer */ 135 struct __vax_frame *vax_fp; /* frame pointer of previous frame */ 136 u_int vax_pc; /* program counter */ 137 u_int vax_args[1]; /* 0 or more arguments */ 138 } VAX_CALLFRAME; 139 140 /* 141 * DDB is called by either <ESC> - D on keyboard, via a TRACE or 142 * BPT trap or from kernel, normally as a result of a panic. 143 * If it is the result of a panic, set the ddb register frame to 144 * contain the registers when panic was called. (easy to debug). 145 */ 146 void 147 kdb_trap(struct trapframe *frame) 148 { 149 int s; 150 #ifdef MULTIPROCESSOR 151 struct cpu_info *ci = curcpu(); 152 #endif 153 154 switch (frame->trap) { 155 case T_BPTFLT: /* breakpoint */ 156 case T_TRCTRAP: /* single_step */ 157 break; 158 159 /* XXX todo: should be migrated to use VAX_CALLFRAME at some point */ 160 case T_KDBTRAP: 161 #ifndef MULTIPROCESSOR /* No fancy panic stack conversion here */ 162 if (panicstr) { 163 struct callsframe *pf, *df; 164 165 df = (void *)frame->fp; /* start of debug's calls */ 166 pf = (void *)df->ca_fp; /* start of panic's calls */ 167 bcopy(&pf->ca_argno, &ddb_regs.r0, sizeof(int) * 12); 168 ddb_regs.fp = pf->ca_fp; 169 ddb_regs.pc = pf->ca_pc; 170 ddb_regs.ap = pf->ca_ap; 171 ddb_regs.sp = (unsigned)pf; 172 ddb_regs.psl = frame->psl & ~0x1fffe0; 173 ddb_regs.psl |= pf->ca_maskpsw & 0xffe0; 174 ddb_regs.psl |= (splsave << 16); 175 } 176 #endif 177 break; 178 179 default: 180 if ((boothowto & RB_KDB) == 0) 181 return; 182 183 kdbprinttrap(frame->trap, frame->code); 184 if (db_recover != 0) { 185 db_error("Faulted in DDB; continuing...\n"); 186 /*NOTREACHED*/ 187 } 188 } 189 190 #ifdef MULTIPROCESSOR 191 ci->ci_ddb_regs = frame; 192 if (pause_cpus()) 193 return; 194 #endif 195 #ifndef MULTIPROCESSOR 196 if (!panicstr) 197 bcopy(frame, &ddb_regs, sizeof(struct trapframe)); 198 #else 199 bcopy(stopcpu->ci_ddb_regs, &ddb_regs, sizeof(struct trapframe)); 200 printf("stopped on cpu %d\n", stopcpu->ci_cpuid); 201 #endif 202 203 /* XXX Should switch to interrupt stack here, if needed. */ 204 205 s = splhigh(); 206 db_active++; 207 cnpollc(TRUE); 208 db_trap(frame->trap, frame->code); 209 cnpollc(FALSE); 210 db_active--; 211 splx(s); 212 213 #ifndef MULTIPROCESSOR 214 if (!panicstr) 215 bcopy(&ddb_regs, frame, sizeof(struct trapframe)); 216 #else 217 bcopy(&ddb_regs, stopcpu->ci_ddb_regs, sizeof(struct trapframe)); 218 #endif 219 frame->sp = mfpr(PR_USP); 220 #ifdef MULTIPROCESSOR 221 rpb.wait = 0; 222 resume_cpus(); 223 #endif 224 } 225 226 extern char *traptypes[]; 227 extern int no_traps; 228 229 /* 230 * Print trap reason. 231 */ 232 void 233 kdbprinttrap(type, code) 234 int type, code; 235 { 236 db_printf("kernel: "); 237 if (type >= no_traps || type < 0) 238 db_printf("type %d", type); 239 else 240 db_printf("%s", traptypes[type]); 241 db_printf(" trap, code=%x\n", code); 242 } 243 244 /* 245 * Read bytes from kernel address space for debugger. 246 */ 247 void 248 db_read_bytes(addr, size, data) 249 vaddr_t addr; 250 register size_t size; 251 register char *data; 252 { 253 254 memcpy(data, (caddr_t)addr, size); 255 } 256 257 /* 258 * Write bytes to kernel address space for debugger. 259 */ 260 void 261 db_write_bytes(addr, size, data) 262 vaddr_t addr; 263 register size_t size; 264 register char *data; 265 { 266 267 memcpy((caddr_t)addr, data, size); 268 } 269 270 void 271 Debugger() 272 { 273 splsave = splx(0xe); /* XXX WRONG (this can lower IPL) */ 274 setsoftddb(); /* beg for debugger */ 275 splx(splsave); 276 } 277 278 /* 279 * Machine register set. 280 */ 281 const struct db_variable db_regs[] = { 282 {"r0", &ddb_regs.r0, FCN_NULL}, 283 {"r1", &ddb_regs.r1, FCN_NULL}, 284 {"r2", &ddb_regs.r2, FCN_NULL}, 285 {"r3", &ddb_regs.r3, FCN_NULL}, 286 {"r4", &ddb_regs.r4, FCN_NULL}, 287 {"r5", &ddb_regs.r5, FCN_NULL}, 288 {"r6", &ddb_regs.r6, FCN_NULL}, 289 {"r7", &ddb_regs.r7, FCN_NULL}, 290 {"r8", &ddb_regs.r8, FCN_NULL}, 291 {"r9", &ddb_regs.r9, FCN_NULL}, 292 {"r10", &ddb_regs.r10, FCN_NULL}, 293 {"r11", &ddb_regs.r11, FCN_NULL}, 294 {"ap", &ddb_regs.ap, FCN_NULL}, 295 {"fp", &ddb_regs.fp, FCN_NULL}, 296 {"sp", &ddb_regs.sp, FCN_NULL}, 297 {"pc", &ddb_regs.pc, FCN_NULL}, 298 {"psl", &ddb_regs.psl, FCN_NULL}, 299 }; 300 const struct db_variable * const db_eregs = db_regs + sizeof(db_regs)/sizeof(db_regs[0]); 301 302 #define IN_USERLAND(x) (((u_int)(x) & 0x80000000) == 0) 303 304 /* 305 * Dump a stack traceback. Takes two arguments: 306 * fp - CALL FRAME pointer 307 * stackbase - Lowest stack value 308 */ 309 static void 310 db_dump_stack(VAX_CALLFRAME *fp, u_int stackbase, 311 void (*pr)(const char *, ...)) { 312 u_int nargs, arg_base, regs; 313 VAX_CALLFRAME *tmp_frame; 314 db_expr_t diff; 315 db_sym_t sym; 316 char *symname; 317 extern int sret, etext; 318 319 (*pr)("Stack traceback : \n"); 320 if (IN_USERLAND(fp)) { 321 (*pr)(" Process is executing in user space.\n"); 322 return; 323 } 324 325 #if 0 326 while (((u_int)(fp->vax_fp) > stackbase - 0x100) && 327 ((u_int)(fp->vax_fp) < (stackbase + USPACE))) { 328 #endif 329 while (!IN_USERLAND(fp->vax_fp)) { 330 u_int pc = fp->vax_pc; 331 332 /* 333 * Figure out the arguments by using a bit of subtlety. 334 * As the argument pointer may have been used as a temporary 335 * by the callee ... recreate what it would have pointed to 336 * as follows: 337 * The vax_regs value has a 12 bit bitmask of the registers 338 * that were saved on the stack. 339 * Store that in 'regs' and then for every bit that is 340 * on (indicates the register contents are on the stack) 341 * increment the argument base (arg_base) by one. 342 * When that is done, args[arg_base] points to the longword 343 * that identifies the number of arguments. 344 * arg_base+1 - arg_base+n are the argument pointers/contents. 345 */ 346 347 348 /* If this was due to a trap/fault, pull the correct pc 349 * out of the trap frame. */ 350 if (pc == (u_int) &sret && fp->vax_fp != 0) { 351 struct trapframe *tf; 352 /* Isolate the saved register bits, and count them */ 353 regs = fp->vax_regs; 354 for (arg_base = 0; regs != 0; regs >>= 1) { 355 if (regs & 1) 356 arg_base++; 357 } 358 tf = (struct trapframe *) &fp->vax_args[arg_base + 2]; 359 (*pr)("0x%lx: trap type=0x%lx code=0x%lx pc=0x%lx psl=0x%lx\n", 360 tf, tf->trap, tf->code, tf->pc, tf->psl); 361 pc = tf->pc; 362 } 363 364 diff = INT_MAX; 365 symname = NULL; 366 if (pc >= 0x80000000 && pc < (u_int) &etext) { 367 sym = db_search_symbol(pc, DB_STGY_ANY, &diff); 368 db_symbol_values(sym, &symname, 0); 369 } 370 if (symname != NULL) 371 (*pr)("0x%lx: %s+0x%lx(", fp, symname, diff); 372 else 373 (*pr)("0x%lx: %#x(", fp, pc); 374 375 /* First get the frame that called this function ... */ 376 tmp_frame = fp->vax_fp; 377 378 /* Isolate the saved register bits, and count them */ 379 regs = tmp_frame->vax_regs; 380 for (arg_base = 0; regs != 0; regs >>= 1) { 381 if (regs & 1) 382 arg_base++; 383 } 384 385 /* number of arguments is then pointed to by vax_args[arg_base] */ 386 nargs = tmp_frame->vax_args[arg_base]; 387 if (nargs) { 388 nargs--; /* reduce by one for formatting niceties */ 389 arg_base++; /* skip past the actual number of arguments */ 390 while (nargs--) 391 (*pr)("%#x,", tmp_frame->vax_args[arg_base++]); 392 393 /* now print out the last arg with closing brace and \n */ 394 (*pr)("%#x)\n", tmp_frame->vax_args[arg_base]); 395 } else 396 (*pr)("void)\n"); 397 /* move to the next frame */ 398 fp = fp->vax_fp; 399 } 400 } 401 402 /* 403 * Implement the trace command which has the form: 404 * 405 * trace <-- Trace panic (same as before) 406 * trace 0x88888 <-- Trace frame whose address is 888888 407 * trace/t <-- Trace current process (0 if no current proc) 408 * trace/t 0tnn <-- Trace process nn (0t for decimal) 409 */ 410 void 411 db_stack_trace_print(addr, have_addr, count, modif, pr) 412 db_expr_t addr; /* Address parameter */ 413 boolean_t have_addr; /* True if addr is valid */ 414 db_expr_t count; /* Optional count */ 415 char *modif; /* pointer to flag modifier 't' */ 416 void (*pr) __P((const char *, ...)); /* Print function */ 417 { 418 extern vaddr_t proc0paddr; 419 struct proc *p = curproc; 420 struct user *uarea; 421 int trace_proc; 422 pid_t curpid; 423 char *s; 424 425 /* Check to see if we're tracing a process */ 426 trace_proc = 0; 427 s = modif; 428 while (!trace_proc && *s) { 429 if (*s++ == 't') 430 trace_proc++; /* why yes we are */ 431 } 432 433 /* Trace a panic */ 434 if (panicstr) { 435 (*pr)("panic: %s\n", panicstr); 436 /* xxx ? where did we panic and whose stack are we using? */ 437 #ifdef MULTIPROCESSOR 438 db_dump_stack((VAX_CALLFRAME *)(ddb_regs.fp), ddb_regs.ap, pr); 439 #else 440 db_dump_stack((VAX_CALLFRAME *)(ddb_regs.sp), ddb_regs.ap, pr); 441 #endif 442 return; 443 } 444 445 /* 446 * If user typed an address its either a PID, or a Frame 447 * if no address then either current proc or panic 448 */ 449 if (have_addr) { 450 if (trace_proc) { 451 p = pfind((int)addr); 452 /* Try to be helpful by looking at it as if it were decimal */ 453 if (p == NULL) { 454 u_int tpid = 0; 455 u_int foo = addr; 456 457 while (foo != 0) { 458 int digit = (foo >> 28) & 0xf; 459 if (digit > 9) { 460 (*pr)(" No such process.\n"); 461 return; 462 } 463 tpid = tpid * 10 + digit; 464 foo = foo << 4; 465 } 466 p = pfind(tpid); 467 if (p == NULL) { 468 (*pr)(" No such process.\n"); 469 return; 470 } 471 } 472 } else { 473 db_dump_stack((VAX_CALLFRAME *)addr, 0, pr); 474 return; 475 } 476 } else { 477 if (trace_proc) { 478 p = curproc; 479 if (p == NULL) { 480 (*pr)("trace: no current process! (ignored)\n"); 481 return; 482 } 483 } else { 484 if (! panicstr) { 485 (*pr)("Not a panic, no active process, ignored.\n"); 486 return; 487 } 488 } 489 } 490 if (p == NULL) { 491 uarea = (struct user *)proc0paddr; 492 curpid = 0; 493 } else { 494 uarea = p->p_addr; 495 curpid = p->p_pid; 496 } 497 (*pr)("Process %d\n", curpid); 498 (*pr)(" PCB contents:\n"); 499 (*pr)(" KSP = 0x%x\n", (unsigned int)(uarea->u_pcb.KSP)); 500 (*pr)(" ESP = 0x%x\n", (unsigned int)(uarea->u_pcb.ESP)); 501 (*pr)(" SSP = 0x%x\n", (unsigned int)(uarea->u_pcb.SSP)); 502 (*pr)(" USP = 0x%x\n", (unsigned int)(uarea->u_pcb.USP)); 503 (*pr)(" R[00] = 0x%08x R[06] = 0x%08x\n", 504 (unsigned int)(uarea->u_pcb.R[0]), (unsigned int)(uarea->u_pcb.R[6])); 505 (*pr)(" R[01] = 0x%08x R[07] = 0x%08x\n", 506 (unsigned int)(uarea->u_pcb.R[1]), (unsigned int)(uarea->u_pcb.R[7])); 507 (*pr)(" R[02] = 0x%08x R[08] = 0x%08x\n", 508 (unsigned int)(uarea->u_pcb.R[2]), (unsigned int)(uarea->u_pcb.R[8])); 509 (*pr)(" R[03] = 0x%08x R[09] = 0x%08x\n", 510 (unsigned int)(uarea->u_pcb.R[3]), (unsigned int)(uarea->u_pcb.R[9])); 511 (*pr)(" R[04] = 0x%08x R[10] = 0x%08x\n", 512 (unsigned int)(uarea->u_pcb.R[4]), (unsigned int)(uarea->u_pcb.R[10])); 513 (*pr)(" R[05] = 0x%08x R[11] = 0x%08x\n", 514 (unsigned int)(uarea->u_pcb.R[5]), (unsigned int)(uarea->u_pcb.R[11])); 515 (*pr)(" AP = 0x%x\n", (unsigned int)(uarea->u_pcb.AP)); 516 (*pr)(" FP = 0x%x\n", (unsigned int)(uarea->u_pcb.FP)); 517 (*pr)(" PC = 0x%x\n", (unsigned int)(uarea->u_pcb.PC)); 518 (*pr)(" PSL = 0x%x\n", (unsigned int)(uarea->u_pcb.PSL)); 519 (*pr)(" Trap frame pointer: 0x%x\n", 520 (unsigned int)(uarea->u_pcb.framep)); 521 db_dump_stack((VAX_CALLFRAME *)(uarea->u_pcb.FP), 522 (u_int) uarea->u_pcb.KSP, pr); 523 return; 524 #if 0 525 while (((u_int)(cur_frame->vax_fp) > stackbase) && 526 ((u_int)(cur_frame->vax_fp) < (stackbase + USPACE))) { 527 u_int nargs; 528 VAX_CALLFRAME *tmp_frame; 529 530 diff = INT_MAX; 531 symname = NULL; 532 sym = db_search_symbol(cur_frame->vax_pc, DB_STGY_ANY, &diff); 533 db_symbol_values(sym, &symname, 0); 534 (*pr)("%s+0x%lx(", symname, diff); 535 536 /* 537 * Figure out the arguments by using a bit of subterfuge 538 * since the argument pointer may have been used as a temporary 539 * by the callee ... recreate what it would have pointed to 540 * as follows: 541 * The vax_regs value has a 12 bit bitmask of the registers 542 * that were saved on the stack. 543 * Store that in 'regs' and then for every bit that is 544 * on (indicates the register contents are on the stack) 545 * increment the argument base (arg_base) by one. 546 * When that is done, args[arg_base] points to the longword 547 * that identifies the number of arguments. 548 * arg_base+1 - arg_base+n are the argument pointers/contents. 549 */ 550 551 /* First get the frame that called this function ... */ 552 tmp_frame = cur_frame->vax_fp; 553 554 /* Isolate the saved register bits, and count them */ 555 regs = tmp_frame->vax_regs; 556 for (arg_base = 0; regs != 0; regs >>= 1) { 557 if (regs & 1) 558 arg_base++; 559 } 560 561 /* number of arguments is then pointed to by vax_args[arg_base] */ 562 nargs = tmp_frame->vax_args[arg_base]; 563 if (nargs) { 564 nargs--; /* reduce by one for formatting niceties */ 565 arg_base++; /* skip past the actual number of arguments */ 566 while (nargs--) 567 (*pr)("0x%x,", tmp_frame->vax_args[arg_base++]); 568 569 /* now print out the last arg with closing brace and \n */ 570 (*pr)("0x%x)\n", tmp_frame->vax_args[++arg_base]); 571 } else 572 (*pr)("void)\n"); 573 /* move to the next frame */ 574 cur_frame = cur_frame->vax_fp; 575 } 576 577 /* 578 * DEAD CODE, previous panic tracing code. 579 */ 580 if (! have_addr) { 581 printf("Trace default\n"); 582 if (panicstr) { 583 cf = (int *)ddb_regs.sp; 584 } else { 585 printf("Don't know what to do without panic\n"); 586 return; 587 } 588 if (p) 589 paddr = (u_int)p->p_addr; 590 else 591 paddr = proc0paddr; 592 593 stackbase = (ddb_regs.psl & PSL_IS ? istack : paddr); 594 } 595 #endif 596 } 597 598 static int ddbescape = 0; 599 600 int 601 kdbrint(tkn) 602 int tkn; 603 { 604 605 if (ddbescape && ((tkn & 0x7f) == 'D')) { 606 setsoftddb(); 607 ddbescape = 0; 608 return 1; 609 } 610 611 if ((ddbescape == 0) && ((tkn & 0x7f) == 27)) { 612 ddbescape = 1; 613 return 1; 614 } 615 616 if (ddbescape) { 617 ddbescape = 0; 618 return 2; 619 } 620 621 ddbescape = 0; 622 return 0; 623 } 624 625 #ifdef MULTIPROCESSOR 626 627 static void 628 db_mach_cpu(db_expr_t addr, int have_addr, db_expr_t count, char *modif) 629 { 630 struct cpu_mp_softc *sc; 631 struct cpu_info *ci; 632 633 if ((addr < 0) || (addr >= cpu_cd.cd_ndevs)) 634 return db_printf("%ld: cpu out of range\n", addr); 635 if ((sc = cpu_cd.cd_devs[addr]) == NULL) 636 return db_printf("%ld: cpu not configured\n", addr); 637 638 ci = &sc->sc_ci; 639 if ((ci != curcpu()) && ((ci->ci_flags & CI_STOPPED) == 0)) 640 return db_printf("cpu %ld not stopped???\n", addr); 641 642 bcopy(&ddb_regs, stopcpu->ci_ddb_regs, sizeof(struct trapframe)); 643 stopcpu = ci; 644 bcopy(stopcpu->ci_ddb_regs, &ddb_regs, sizeof(struct trapframe)); 645 db_printf("using cpu %ld", addr); 646 if (ci->ci_curproc) 647 db_printf(" in proc %d (%s)\n", ci->ci_curproc->p_pid, 648 ci->ci_curproc->p_comm); 649 } 650 #endif 651 652 const struct db_command db_machine_command_table[] = { 653 #ifdef MULTIPROCESSOR 654 { "cpu", db_mach_cpu, 0, 0 }, 655 #endif 656 { NULL }, 657 }; 658