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