1 /* $NetBSD: db_interface.c,v 1.65 2002/06/14 17:12:05 eeh Exp $ */ 2 3 /* 4 * Copyright (c) 1996-2002 Eduardo Horvath. All rights reserved. 5 * Mach Operating System 6 * Copyright (c) 1991,1990 Carnegie Mellon University 7 * All Rights Reserved. 8 * 9 * Permission to use, copy, modify and distribute this software and its 10 * documentation is hereby granted, provided that both the copyright 11 * notice and this permission notice appear in all copies of the 12 * software, derivative works or modified versions, and any portions 13 * thereof, and that both notices appear in supporting documentation. 14 * 15 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 16 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 17 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 18 * 19 * Carnegie Mellon requests users of this software to return to 20 * 21 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 22 * School of Computer Science 23 * Carnegie Mellon University 24 * Pittsburgh PA 15213-3890 25 * 26 * any improvements or extensions that they make and grant Carnegie the 27 * rights to redistribute these changes. 28 * 29 * From: db_interface.c,v 2.4 1991/02/05 17:11:13 mrt (CMU) 30 */ 31 32 /* 33 * Interface to new debugger. 34 */ 35 #include "opt_ddb.h" 36 37 #include <sys/param.h> 38 #include <sys/proc.h> 39 #include <sys/user.h> 40 #include <sys/reboot.h> 41 #include <sys/systm.h> 42 43 #include <uvm/uvm_extern.h> 44 45 #include <dev/cons.h> 46 47 #include <machine/db_machdep.h> 48 #include <ddb/db_command.h> 49 #include <ddb/db_sym.h> 50 #include <ddb/db_variables.h> 51 #include <ddb/db_extern.h> 52 #include <ddb/db_access.h> 53 #include <ddb/db_output.h> 54 #include <ddb/db_interface.h> 55 56 #include <machine/instr.h> 57 #include <machine/cpu.h> 58 #include <machine/openfirm.h> 59 #include <machine/ctlreg.h> 60 #include <machine/pmap.h> 61 62 #include "fb.h" 63 #include "esp_sbus.h" 64 65 extern void OF_enter __P((void)); 66 67 extern struct traptrace { 68 unsigned short tl:3, /* Trap level */ 69 ns:4, /* PCB nsaved */ 70 tt:9; /* Trap type */ 71 unsigned short pid; /* PID */ 72 u_int tstate; /* tstate */ 73 u_int tsp; /* sp */ 74 u_int tpc; /* pc */ 75 u_int tfault; /* MMU tag access */ 76 } trap_trace[], trap_trace_end[]; 77 78 static int nil; 79 80 static int 81 db__char_value(const struct db_variable *var, db_expr_t *expr, int mode) 82 { 83 84 switch (mode) { 85 case DB_VAR_SET: 86 *var->valuep = *(char *)expr; 87 break; 88 case DB_VAR_GET: 89 *expr = *(char *)var->valuep; 90 break; 91 #ifdef DIAGNOSTIC 92 default: 93 printf("db__char_value: mode %d\n", mode); 94 break; 95 #endif 96 } 97 98 return 0; 99 } 100 101 #ifdef notdef_yet 102 static int 103 db__short_value(const struct db_variable *var, db_expr_t *expr, int mode) 104 { 105 106 switch (mode) { 107 case DB_VAR_SET: 108 *var->valuep = *(short *)expr; 109 break; 110 case DB_VAR_GET: 111 *expr = *(short *)var->valuep; 112 break; 113 #ifdef DIAGNOSTIC 114 default: 115 printf("db__short_value: mode %d\n", mode); 116 break; 117 #endif 118 } 119 120 return 0; 121 } 122 #endif 123 124 static int 125 db__int_value(const struct db_variable *var, db_expr_t *expr, int mode) 126 { 127 128 switch (mode) { 129 case DB_VAR_SET: 130 *var->valuep = *(int *)expr; 131 break; 132 case DB_VAR_GET: 133 *expr = *(int *)var->valuep; 134 break; 135 #ifdef DIAGNOSTIC 136 default: 137 printf("db__int_value: mode %d\n", mode); 138 break; 139 #endif 140 } 141 142 return 0; 143 } 144 145 const struct db_variable db_regs[] = { 146 { "tstate", (long *)&DDB_TF->tf_tstate, FCN_NULL, }, 147 { "pc", (long *)&DDB_TF->tf_pc, FCN_NULL, }, 148 { "npc", (long *)&DDB_TF->tf_npc, FCN_NULL, }, 149 { "ipl", (long *)&DDB_TF->tf_oldpil, db__char_value, }, 150 { "y", (long *)&DDB_TF->tf_y, db__int_value, }, 151 { "g0", (long *)&nil, FCN_NULL, }, 152 { "g1", (long *)&DDB_TF->tf_global[1], FCN_NULL, }, 153 { "g2", (long *)&DDB_TF->tf_global[2], FCN_NULL, }, 154 { "g3", (long *)&DDB_TF->tf_global[3], FCN_NULL, }, 155 { "g4", (long *)&DDB_TF->tf_global[4], FCN_NULL, }, 156 { "g5", (long *)&DDB_TF->tf_global[5], FCN_NULL, }, 157 { "g6", (long *)&DDB_TF->tf_global[6], FCN_NULL, }, 158 { "g7", (long *)&DDB_TF->tf_global[7], FCN_NULL, }, 159 { "o0", (long *)&DDB_TF->tf_out[0], FCN_NULL, }, 160 { "o1", (long *)&DDB_TF->tf_out[1], FCN_NULL, }, 161 { "o2", (long *)&DDB_TF->tf_out[2], FCN_NULL, }, 162 { "o3", (long *)&DDB_TF->tf_out[3], FCN_NULL, }, 163 { "o4", (long *)&DDB_TF->tf_out[4], FCN_NULL, }, 164 { "o5", (long *)&DDB_TF->tf_out[5], FCN_NULL, }, 165 { "o6", (long *)&DDB_TF->tf_out[6], FCN_NULL, }, 166 { "o7", (long *)&DDB_TF->tf_out[7], FCN_NULL, }, 167 { "l0", (long *)&DDB_FR->fr_local[0], FCN_NULL, }, 168 { "l1", (long *)&DDB_FR->fr_local[1], FCN_NULL, }, 169 { "l2", (long *)&DDB_FR->fr_local[2], FCN_NULL, }, 170 { "l3", (long *)&DDB_FR->fr_local[3], FCN_NULL, }, 171 { "l4", (long *)&DDB_FR->fr_local[4], FCN_NULL, }, 172 { "l5", (long *)&DDB_FR->fr_local[5], FCN_NULL, }, 173 { "l6", (long *)&DDB_FR->fr_local[6], FCN_NULL, }, 174 { "l7", (long *)&DDB_FR->fr_local[7], FCN_NULL, }, 175 { "i0", (long *)&DDB_FR->fr_arg[0], FCN_NULL, }, 176 { "i1", (long *)&DDB_FR->fr_arg[1], FCN_NULL, }, 177 { "i2", (long *)&DDB_FR->fr_arg[2], FCN_NULL, }, 178 { "i3", (long *)&DDB_FR->fr_arg[3], FCN_NULL, }, 179 { "i4", (long *)&DDB_FR->fr_arg[4], FCN_NULL, }, 180 { "i5", (long *)&DDB_FR->fr_arg[5], FCN_NULL, }, 181 { "i6", (long *)&DDB_FR->fr_arg[6], FCN_NULL, }, 182 { "i7", (long *)&DDB_FR->fr_arg[7], FCN_NULL, }, 183 { "f0", (long *)&DDB_FP->fs_regs[0], FCN_NULL, }, 184 { "f2", (long *)&DDB_FP->fs_regs[2], FCN_NULL, }, 185 { "f4", (long *)&DDB_FP->fs_regs[4], FCN_NULL, }, 186 { "f6", (long *)&DDB_FP->fs_regs[6], FCN_NULL, }, 187 { "f8", (long *)&DDB_FP->fs_regs[8], FCN_NULL, }, 188 { "f10", (long *)&DDB_FP->fs_regs[10], FCN_NULL, }, 189 { "f12", (long *)&DDB_FP->fs_regs[12], FCN_NULL, }, 190 { "f14", (long *)&DDB_FP->fs_regs[14], FCN_NULL, }, 191 { "f16", (long *)&DDB_FP->fs_regs[16], FCN_NULL, }, 192 { "f18", (long *)&DDB_FP->fs_regs[18], FCN_NULL, }, 193 { "f20", (long *)&DDB_FP->fs_regs[20], FCN_NULL, }, 194 { "f22", (long *)&DDB_FP->fs_regs[22], FCN_NULL, }, 195 { "f24", (long *)&DDB_FP->fs_regs[24], FCN_NULL, }, 196 { "f26", (long *)&DDB_FP->fs_regs[26], FCN_NULL, }, 197 { "f28", (long *)&DDB_FP->fs_regs[28], FCN_NULL, }, 198 { "f30", (long *)&DDB_FP->fs_regs[30], FCN_NULL, }, 199 { "f32", (long *)&DDB_FP->fs_regs[32], FCN_NULL, }, 200 { "f34", (long *)&DDB_FP->fs_regs[34], FCN_NULL, }, 201 { "f36", (long *)&DDB_FP->fs_regs[36], FCN_NULL, }, 202 { "f38", (long *)&DDB_FP->fs_regs[38], FCN_NULL, }, 203 { "f40", (long *)&DDB_FP->fs_regs[40], FCN_NULL, }, 204 { "f42", (long *)&DDB_FP->fs_regs[42], FCN_NULL, }, 205 { "f44", (long *)&DDB_FP->fs_regs[44], FCN_NULL, }, 206 { "f46", (long *)&DDB_FP->fs_regs[46], FCN_NULL, }, 207 { "f48", (long *)&DDB_FP->fs_regs[48], FCN_NULL, }, 208 { "f50", (long *)&DDB_FP->fs_regs[50], FCN_NULL, }, 209 { "f52", (long *)&DDB_FP->fs_regs[52], FCN_NULL, }, 210 { "f54", (long *)&DDB_FP->fs_regs[54], FCN_NULL, }, 211 { "f56", (long *)&DDB_FP->fs_regs[56], FCN_NULL, }, 212 { "f58", (long *)&DDB_FP->fs_regs[58], FCN_NULL, }, 213 { "f60", (long *)&DDB_FP->fs_regs[60], FCN_NULL, }, 214 { "f62", (long *)&DDB_FP->fs_regs[62], FCN_NULL, }, 215 { "fsr", (long *)&DDB_FP->fs_fsr, FCN_NULL, }, 216 { "gsr", (long *)&DDB_FP->fs_gsr, FCN_NULL, }, 217 218 }; 219 const struct db_variable * const db_eregs = db_regs + sizeof(db_regs)/sizeof(db_regs[0]); 220 221 int db_active = 0; 222 223 extern char *trap_type[]; 224 225 void kdb_kbd_trap __P((struct trapframe64 *)); 226 void db_prom_cmd __P((db_expr_t, int, db_expr_t, char *)); 227 void db_proc_cmd __P((db_expr_t, int, db_expr_t, char *)); 228 void db_ctx_cmd __P((db_expr_t, int, db_expr_t, char *)); 229 void db_dump_window __P((db_expr_t, int, db_expr_t, char *)); 230 void db_dump_stack __P((db_expr_t, int, db_expr_t, char *)); 231 void db_dump_trap __P((db_expr_t, int, db_expr_t, char *)); 232 void db_dump_fpstate __P((db_expr_t, int, db_expr_t, char *)); 233 void db_dump_ts __P((db_expr_t, int, db_expr_t, char *)); 234 void db_dump_pcb __P((db_expr_t, int, db_expr_t, char *)); 235 void db_dump_pv __P((db_expr_t, int, db_expr_t, char *)); 236 void db_setpcb __P((db_expr_t, int, db_expr_t, char *)); 237 void db_dump_dtlb __P((db_expr_t, int, db_expr_t, char *)); 238 void db_dump_dtsb __P((db_expr_t, int, db_expr_t, char *)); 239 void db_pmap_kernel __P((db_expr_t, int, db_expr_t, char *)); 240 void db_pload_cmd __P((db_expr_t, int, db_expr_t, char *)); 241 void db_pmap_cmd __P((db_expr_t, int, db_expr_t, char *)); 242 void db_lock __P((db_expr_t, int, db_expr_t, char *)); 243 void db_traptrace __P((db_expr_t, int, db_expr_t, char *)); 244 void db_dump_buf __P((db_expr_t, int, db_expr_t, char *)); 245 void db_dump_espcmd __P((db_expr_t, int, db_expr_t, char *)); 246 void db_watch __P((db_expr_t, int, db_expr_t, char *)); 247 void db_pm_extract __P((db_expr_t, int, db_expr_t, char *)); 248 249 static void db_dump_pmap __P((struct pmap*)); 250 static void db_print_trace_entry __P((struct traptrace *, int)); 251 252 253 /* 254 * Received keyboard interrupt sequence. 255 */ 256 void 257 kdb_kbd_trap(tf) 258 struct trapframe64 *tf; 259 { 260 if (db_active == 0 /* && (boothowto & RB_KDB) */) { 261 printf("\n\nkernel: keyboard interrupt tf=%p\n", tf); 262 kdb_trap(-1, tf); 263 } 264 } 265 266 /* 267 * kdb_trap - field a TRACE or BPT trap 268 */ 269 int 270 kdb_trap(type, tf) 271 int type; 272 register struct trapframe64 *tf; 273 { 274 int s, tl; 275 struct trapstate *ts = &ddb_regs.ddb_ts[0]; 276 extern int savetstate(struct trapstate *ts); 277 extern void restoretstate(int tl, struct trapstate *ts); 278 extern int trap_trace_dis; 279 extern int doing_shutdown; 280 281 trap_trace_dis++; 282 doing_shutdown++; 283 #if NFB > 0 284 fb_unblank(); 285 #endif 286 switch (type) { 287 case T_BREAKPOINT: /* breakpoint */ 288 printf("kdb breakpoint at %llx\n", 289 (unsigned long long)tf->tf_pc); 290 break; 291 case -1: /* keyboard interrupt */ 292 printf("kdb tf=%p\n", tf); 293 break; 294 default: 295 printf("kernel trap %x: %s\n", type, trap_type[type & 0x1ff]); 296 if (db_recover != 0) { 297 OF_enter(); 298 db_error("Faulted in DDB; continuing...\n"); 299 OF_enter(); 300 /*NOTREACHED*/ 301 } 302 db_recover = (label_t *)1; 303 } 304 305 /* Should switch to kdb`s own stack here. */ 306 write_all_windows(); 307 308 ddb_regs.ddb_tf = *tf; 309 if (fpproc) { 310 savefpstate(fpproc->p_md.md_fpstate); 311 ddb_regs.ddb_fpstate = *fpproc->p_md.md_fpstate; 312 loadfpstate(fpproc->p_md.md_fpstate); 313 } 314 /* We should do a proper copyin and xlate 64-bit stack frames, but... */ 315 /* if (tf->tf_tstate & TSTATE_PRIV) { */ 316 317 #if 0 318 /* make sure this is not causing ddb problems. */ 319 if (tf->tf_out[6] & 1) { 320 if ((unsigned)(tf->tf_out[6] + BIAS) > (unsigned)KERNBASE) 321 ddb_regs.ddb_fr = *(struct frame64 *)(tf->tf_out[6] + BIAS); 322 else 323 copyin((caddr_t)(tf->tf_out[6] + BIAS), &ddb_regs.ddb_fr, sizeof(struct frame64)); 324 } else { 325 struct frame32 tfr; 326 327 /* First get a local copy of the frame32 */ 328 if ((unsigned)(tf->tf_out[6]) > (unsigned)KERNBASE) 329 tfr = *(struct frame32 *)tf->tf_out[6]; 330 else 331 copyin((caddr_t)(tf->tf_out[6]), &tfr, sizeof(struct frame32)); 332 /* Now copy each field from the 32-bit value to the 64-bit value */ 333 for (i=0; i<8; i++) 334 ddb_regs.ddb_fr.fr_local[i] = tfr.fr_local[i]; 335 for (i=0; i<6; i++) 336 ddb_regs.ddb_fr.fr_arg[i] = tfr.fr_arg[i]; 337 ddb_regs.ddb_fr.fr_fp = (long)tfr.fr_fp; 338 ddb_regs.ddb_fr.fr_pc = tfr.fr_pc; 339 } 340 #endif 341 342 s = splhigh(); 343 db_active++; 344 cnpollc(TRUE); 345 /* Need to do spl stuff till cnpollc works */ 346 tl = ddb_regs.ddb_tl = savetstate(ts); 347 db_dump_ts(0, 0, 0, 0); 348 db_trap(type, 0/*code*/); 349 restoretstate(tl,ts); 350 cnpollc(FALSE); 351 db_active--; 352 splx(s); 353 354 if (fpproc) { 355 *fpproc->p_md.md_fpstate = ddb_regs.ddb_fpstate; 356 loadfpstate(fpproc->p_md.md_fpstate); 357 } 358 #if 0 359 /* We will not alter the machine's running state until we get everything else working */ 360 *(struct frame *)tf->tf_out[6] = ddb_regs.ddb_fr; 361 #endif 362 *tf = ddb_regs.ddb_tf; 363 trap_trace_dis--; 364 doing_shutdown--; 365 366 return (1); 367 } 368 369 /* 370 * Read bytes from kernel address space for debugger. 371 */ 372 void 373 db_read_bytes(addr, size, data) 374 vaddr_t addr; 375 register size_t size; 376 register char *data; 377 { 378 register char *src; 379 380 src = (char *)addr; 381 while (size-- > 0) { 382 if (src >= (char *)VM_MIN_KERNEL_ADDRESS) 383 *data++ = probeget((paddr_t)(u_long)src++, ASI_P, 1); 384 else 385 *data++ = fubyte(src++); 386 } 387 } 388 389 390 /* 391 * Write bytes to kernel address space for debugger. 392 */ 393 void 394 db_write_bytes(addr, size, data) 395 vaddr_t addr; 396 register size_t size; 397 register char *data; 398 { 399 register char *dst; 400 extern vaddr_t ktext; 401 extern paddr_t ktextp; 402 403 dst = (char *)addr; 404 while (size-- > 0) { 405 if ((dst >= (char *)VM_MIN_KERNEL_ADDRESS+0x400000)) 406 *dst = *data; 407 else if ((dst >= (char *)VM_MIN_KERNEL_ADDRESS) && 408 (dst < (char *)VM_MIN_KERNEL_ADDRESS+0x400000)) 409 /* Read Only mapping -- need to do a bypass access */ 410 stba((u_long)dst - ktext + ktextp, ASI_PHYS_CACHED, *data); 411 else 412 subyte(dst, *data); 413 dst++, data++; 414 } 415 416 } 417 418 void 419 Debugger() 420 { 421 /* We use the breakpoint to trap into DDB */ 422 asm("ta 1; nop"); 423 } 424 425 void 426 db_prom_cmd(addr, have_addr, count, modif) 427 db_expr_t addr; 428 int have_addr; 429 db_expr_t count; 430 char *modif; 431 { 432 OF_enter(); 433 } 434 435 void 436 db_dump_dtlb(addr, have_addr, count, modif) 437 db_expr_t addr; 438 int have_addr; 439 db_expr_t count; 440 char *modif; 441 { 442 extern void print_dtlb __P((void)); 443 444 if (have_addr) { 445 int i; 446 int64_t* p = (int64_t*)addr; 447 static int64_t buf[128]; 448 extern void dump_dtlb(int64_t *); 449 450 dump_dtlb(buf); 451 p = buf; 452 for (i=0; i<64;) { 453 #ifdef __arch64__ 454 db_printf("%2d:%16.16lx %16.16lx ", i++, p[0], p[1]); 455 p += 2; 456 db_printf("%2d:%16.16lx %16.16lx\n", i++, p[0], p[1]); 457 p += 2; 458 #else 459 db_printf("%2d:%16.16qx %16.16qx ", i++, p[0], p[1]); 460 p += 2; 461 db_printf("%2d:%16.16qx %16.16qx\n", i++, p[0], p[1]); 462 p += 2; 463 #endif 464 } 465 } else { 466 #ifdef DEBUG 467 print_dtlb(); 468 #endif 469 } 470 } 471 472 void 473 db_pload_cmd(addr, have_addr, count, modif) 474 db_expr_t addr; 475 int have_addr; 476 db_expr_t count; 477 char *modif; 478 { 479 static paddr_t oldaddr = -1; 480 int asi = ASI_PHYS_CACHED; 481 482 if (!have_addr) { 483 addr = oldaddr; 484 } 485 if (addr == -1) { 486 db_printf("no address\n"); 487 return; 488 } 489 addr &= ~0x7; /* align */ 490 { 491 register char c, *cp = modif; 492 while ((c = *cp++) != 0) 493 if (c == 'u') 494 asi = ASI_AIUS; 495 } 496 while (count--) { 497 if (db_print_position() == 0) { 498 /* Always print the address. */ 499 db_printf("%16.16lx:\t", addr); 500 } 501 oldaddr=addr; 502 db_printf("%8.8lx\n", (long)ldxa(addr, asi)); 503 addr += 8; 504 if (db_print_position() != 0) 505 db_end_line(); 506 } 507 } 508 509 int64_t pseg_get __P((struct pmap *, vaddr_t)); 510 511 void 512 db_dump_pmap(pm) 513 struct pmap* pm; 514 { 515 /* print all valid pages in the kernel pmap */ 516 long i, j, k, n; 517 paddr_t *pdir, *ptbl; 518 /* Almost the same as pmap_collect() */ 519 520 n = 0; 521 for (i=0; i<STSZ; i++) { 522 if((pdir = (paddr_t *)(u_long)ldxa((vaddr_t)&pm->pm_segs[i], ASI_PHYS_CACHED))) { 523 db_printf("pdir %ld at %lx:\n", i, (long)pdir); 524 for (k=0; k<PDSZ; k++) { 525 if ((ptbl = (paddr_t *)(u_long)ldxa((vaddr_t)&pdir[k], ASI_PHYS_CACHED))) { 526 db_printf("\tptable %ld:%ld at %lx:\n", i, k, (long)ptbl); 527 for (j=0; j<PTSZ; j++) { 528 int64_t data0, data1; 529 data0 = ldxa((vaddr_t)&ptbl[j], ASI_PHYS_CACHED); 530 j++; 531 data1 = ldxa((vaddr_t)&ptbl[j], ASI_PHYS_CACHED); 532 if (data0 || data1) { 533 db_printf("%llx: %llx\t", 534 (unsigned long long)(((u_int64_t)i<<STSHIFT)|(k<<PDSHIFT)|((j-1)<<PTSHIFT)), 535 (unsigned long long)(data0)); 536 db_printf("%llx: %llx\n", 537 (unsigned long long)(((u_int64_t)i<<STSHIFT)|(k<<PDSHIFT)|(j<<PTSHIFT)), 538 (unsigned long long)(data1)); 539 } 540 } 541 } 542 } 543 } 544 } 545 } 546 547 void 548 db_pmap_kernel(addr, have_addr, count, modif) 549 db_expr_t addr; 550 int have_addr; 551 db_expr_t count; 552 char *modif; 553 { 554 extern struct pmap kernel_pmap_; 555 int i, j, full = 0; 556 u_int64_t data; 557 558 { 559 register char c, *cp = modif; 560 while ((c = *cp++) != 0) 561 if (c == 'f') 562 full = 1; 563 } 564 if (have_addr) { 565 /* lookup an entry for this VA */ 566 567 if ((data = pseg_get(&kernel_pmap_, (vaddr_t)addr))) { 568 db_printf("pmap_kernel(%p)->pm_segs[%lx][%lx][%lx]=>%qx\n", 569 (void *)addr, (u_long)va_to_seg(addr), 570 (u_long)va_to_dir(addr), (u_long)va_to_pte(addr), 571 (unsigned long long)data); 572 } else { 573 db_printf("No mapping for %p\n", (void *)addr); 574 } 575 return; 576 } 577 578 db_printf("pmap_kernel(%p) psegs %p phys %llx\n", 579 &kernel_pmap_, kernel_pmap_.pm_segs, 580 (unsigned long long)kernel_pmap_.pm_physaddr); 581 if (full) { 582 db_dump_pmap(&kernel_pmap_); 583 } else { 584 for (j=i=0; i<STSZ; i++) { 585 long seg = (long)ldxa((vaddr_t)&kernel_pmap_.pm_segs[i], ASI_PHYS_CACHED); 586 if (seg) 587 db_printf("seg %d => %lx%c", i, seg, (j++%4)?'\t':'\n'); 588 } 589 } 590 } 591 592 void 593 db_pm_extract(addr, have_addr, count, modif) 594 db_expr_t addr; 595 int have_addr; 596 db_expr_t count; 597 char *modif; 598 { 599 if (have_addr) { 600 paddr_t pa; 601 602 if (pmap_extract(pmap_kernel(), addr, &pa)) 603 db_printf("pa = %llx\n", (long long)pa); 604 else 605 db_printf("%p not found\n", (void *)addr); 606 } else 607 db_printf("pmap_extract: no address\n"); 608 } 609 610 void 611 db_pmap_cmd(addr, have_addr, count, modif) 612 db_expr_t addr; 613 int have_addr; 614 db_expr_t count; 615 char *modif; 616 { 617 struct pmap* pm=NULL; 618 int i, j=0, full = 0; 619 620 { 621 register char c, *cp = modif; 622 if (modif) 623 while ((c = *cp++) != 0) 624 if (c == 'f') 625 full = 1; 626 } 627 if (curproc && curproc->p_vmspace) 628 pm = curproc->p_vmspace->vm_map.pmap; 629 if (have_addr) { 630 pm = (struct pmap*)addr; 631 } 632 633 db_printf("pmap %p: ctx %x refs %d physaddr %llx psegs %p\n", 634 pm, pm->pm_ctx, pm->pm_refs, 635 (unsigned long long)pm->pm_physaddr, pm->pm_segs); 636 637 if (full) { 638 db_dump_pmap(pm); 639 } else { 640 for (i=0; i<STSZ; i++) { 641 long seg = (long)ldxa((vaddr_t)&kernel_pmap_.pm_segs[i], ASI_PHYS_CACHED); 642 if (seg) 643 db_printf("seg %d => %lx%c", i, seg, (j++%4)?'\t':'\n'); 644 } 645 } 646 } 647 648 649 void 650 db_lock(addr, have_addr, count, modif) 651 db_expr_t addr; 652 int have_addr; 653 db_expr_t count; 654 char *modif; 655 { 656 #if 0 657 struct lock *l; 658 659 if (!have_addr) { 660 db_printf("What lock address?\n"); 661 return; 662 } 663 664 l = (struct lock *)addr; 665 db_printf("interlock=%x flags=%x\n waitcount=%x sharecount=%x " 666 "exclusivecount=%x\n wmesg=%s recurselevel=%x\n", 667 l->lk_interlock.lock_data, l->lk_flags, l->lk_waitcount, 668 l->lk_sharecount, l->lk_exclusivecount, l->lk_wmesg, 669 l->lk_recurselevel); 670 #else 671 db_printf("locks unsupported\n"); 672 #endif 673 } 674 675 void 676 db_dump_dtsb(addr, have_addr, count, modif) 677 db_expr_t addr; 678 int have_addr; 679 db_expr_t count; 680 char *modif; 681 { 682 extern pte_t *tsb; 683 extern int tsbsize; 684 #define TSBENTS (512<<tsbsize) 685 int i; 686 687 db_printf("TSB:\n"); 688 for (i=0; i<TSBENTS; i++) { 689 db_printf("%4d:%4d:%08x %08x:%08x ", i, 690 (int)((tsb[i].tag&TSB_TAG_G)?-1:TSB_TAG_CTX(tsb[i].tag)), 691 (int)((i<<13)|TSB_TAG_VA(tsb[i].tag)), 692 (int)(tsb[i].data>>32), (int)tsb[i].data); 693 i++; 694 db_printf("%4d:%4d:%08x %08x:%08x\n", i, 695 (int)((tsb[i].tag&TSB_TAG_G)?-1:TSB_TAG_CTX(tsb[i].tag)), 696 (int)((i<<13)|TSB_TAG_VA(tsb[i].tag)), 697 (int)(tsb[i].data>>32), (int)tsb[i].data); 698 } 699 } 700 701 void db_page_cmd __P((db_expr_t, int, db_expr_t, char *)); 702 void 703 db_page_cmd(addr, have_addr, count, modif) 704 db_expr_t addr; 705 int have_addr; 706 db_expr_t count; 707 char *modif; 708 { 709 710 if (!have_addr) { 711 db_printf("Need paddr for page\n"); 712 return; 713 } 714 715 db_printf("pa %llx pg %p\n", (unsigned long long)addr, 716 PHYS_TO_VM_PAGE(addr)); 717 } 718 719 720 void 721 db_proc_cmd(addr, have_addr, count, modif) 722 db_expr_t addr; 723 int have_addr; 724 db_expr_t count; 725 char *modif; 726 { 727 struct proc *p; 728 729 p = curproc; 730 if (have_addr) 731 p = (struct proc*) addr; 732 if (p == NULL) { 733 db_printf("no current process\n"); 734 return; 735 } 736 db_printf("process %p:", p); 737 db_printf("pid:%d vmspace:%p pmap:%p ctx:%x wchan:%p pri:%d upri:%d\n", 738 p->p_pid, p->p_vmspace, p->p_vmspace->vm_map.pmap, 739 p->p_vmspace->vm_map.pmap->pm_ctx, 740 p->p_wchan, p->p_priority, p->p_usrpri); 741 db_printf("thread @ %p = %p tf:%p ", &p->p_thread, p->p_thread, 742 p->p_md.md_tf); 743 db_printf("maxsaddr:%p ssiz:%dpg or %llxB\n", 744 p->p_vmspace->vm_maxsaddr, p->p_vmspace->vm_ssize, 745 (unsigned long long)ctob(p->p_vmspace->vm_ssize)); 746 db_printf("profile timer: %ld sec %ld usec\n", 747 p->p_stats->p_timer[ITIMER_PROF].it_value.tv_sec, 748 p->p_stats->p_timer[ITIMER_PROF].it_value.tv_usec); 749 db_printf("pcb: %p fpstate: %p\n", &p->p_addr->u_pcb, 750 p->p_md.md_fpstate); 751 return; 752 } 753 754 void 755 db_ctx_cmd(addr, have_addr, count, modif) 756 db_expr_t addr; 757 int have_addr; 758 db_expr_t count; 759 char *modif; 760 { 761 struct proc *p; 762 763 /* XXX LOCKING XXX */ 764 for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) { 765 if (p->p_stat) { 766 db_printf("process %p:", p); 767 db_printf("pid:%d pmap:%p ctx:%x tf:%p fpstate %p " 768 "lastcall:%s\n", 769 p->p_pid, p->p_vmspace->vm_map.pmap, 770 p->p_vmspace->vm_map.pmap->pm_ctx, 771 p->p_md.md_tf, p->p_md.md_fpstate, 772 (p->p_addr->u_pcb.lastcall)? 773 p->p_addr->u_pcb.lastcall : "Null"); 774 } 775 } 776 return; 777 } 778 779 void 780 db_dump_pcb(addr, have_addr, count, modif) 781 db_expr_t addr; 782 int have_addr; 783 db_expr_t count; 784 char *modif; 785 { 786 extern struct pcb *cpcb; 787 struct pcb *pcb; 788 int i; 789 790 pcb = cpcb; 791 if (have_addr) 792 pcb = (struct pcb*) addr; 793 794 db_printf("pcb@%p sp:%p pc:%p cwp:%d pil:%d nsaved:%x onfault:%p\nlastcall:%s\nfull windows:\n", 795 pcb, (void *)(long)pcb->pcb_sp, (void *)(long)pcb->pcb_pc, pcb->pcb_cwp, 796 pcb->pcb_pil, pcb->pcb_nsaved, (void *)pcb->pcb_onfault, 797 (pcb->lastcall)?pcb->lastcall:"Null"); 798 799 for (i=0; i<pcb->pcb_nsaved; i++) { 800 db_printf("win %d: at %llx local, in\n", i, 801 (unsigned long long)pcb->pcb_rw[i+1].rw_in[6]); 802 db_printf("%16llx %16llx %16llx %16llx\n", 803 (unsigned long long)pcb->pcb_rw[i].rw_local[0], 804 (unsigned long long)pcb->pcb_rw[i].rw_local[1], 805 (unsigned long long)pcb->pcb_rw[i].rw_local[2], 806 (unsigned long long)pcb->pcb_rw[i].rw_local[3]); 807 db_printf("%16llx %16llx %16llx %16llx\n", 808 (unsigned long long)pcb->pcb_rw[i].rw_local[4], 809 (unsigned long long)pcb->pcb_rw[i].rw_local[5], 810 (unsigned long long)pcb->pcb_rw[i].rw_local[6], 811 (unsigned long long)pcb->pcb_rw[i].rw_local[7]); 812 db_printf("%16llx %16llx %16llx %16llx\n", 813 (unsigned long long)pcb->pcb_rw[i].rw_in[0], 814 (unsigned long long)pcb->pcb_rw[i].rw_in[1], 815 (unsigned long long)pcb->pcb_rw[i].rw_in[2], 816 (unsigned long long)pcb->pcb_rw[i].rw_in[3]); 817 db_printf("%16llx %16llx %16llx %16llx\n", 818 (unsigned long long)pcb->pcb_rw[i].rw_in[4], 819 (unsigned long long)pcb->pcb_rw[i].rw_in[5], 820 (unsigned long long)pcb->pcb_rw[i].rw_in[6], 821 (unsigned long long)pcb->pcb_rw[i].rw_in[7]); 822 } 823 } 824 825 826 void 827 db_setpcb(addr, have_addr, count, modif) 828 db_expr_t addr; 829 int have_addr; 830 db_expr_t count; 831 char *modif; 832 { 833 struct proc *p, *pp; 834 835 extern struct pcb *cpcb; 836 837 if (!have_addr) { 838 db_printf("What PID do you want to map in?\n"); 839 return; 840 } 841 842 for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) { 843 pp = p->p_pptr; 844 if (p->p_stat && p->p_pid == addr) { 845 curproc = p; 846 cpcb = (struct pcb*)p->p_addr; 847 if (p->p_vmspace->vm_map.pmap->pm_ctx) { 848 switchtoctx(p->p_vmspace->vm_map.pmap->pm_ctx); 849 return; 850 } 851 db_printf("PID %ld has a null context.\n", addr); 852 return; 853 } 854 } 855 db_printf("PID %ld not found.\n", addr); 856 } 857 858 static void 859 db_print_trace_entry(te, i) 860 struct traptrace *te; 861 int i; 862 { 863 db_printf("%d:%d p:%d tt:%x:%llx:%llx %llx:%llx ", i, 864 (int)te->tl, (int)te->pid, 865 (int)te->tt, (unsigned long long)te->tstate, 866 (unsigned long long)te->tfault, (unsigned long long)te->tsp, 867 (unsigned long long)te->tpc); 868 db_printsym((u_long)te->tpc, DB_STGY_PROC, db_printf); 869 db_printf(": "); 870 if ((te->tpc && !(te->tpc&0x3)) && 871 curproc && 872 (curproc->p_pid == te->pid)) { 873 db_disasm((u_long)te->tpc, 0); 874 } else db_printf("\n"); 875 } 876 877 void 878 db_traptrace(addr, have_addr, count, modif) 879 db_expr_t addr; 880 int have_addr; 881 db_expr_t count; 882 char *modif; 883 { 884 int i, start = 0, full = 0, reverse = 0; 885 struct traptrace *end; 886 887 start = 0; 888 end = &trap_trace_end[0]; 889 890 { 891 register char c, *cp = modif; 892 if (modif) 893 while ((c = *cp++) != 0) { 894 if (c == 'f') 895 full = 1; 896 if (c == 'r') 897 reverse = 1; 898 } 899 } 900 901 if (have_addr) { 902 start = addr / (sizeof (struct traptrace)); 903 if (&trap_trace[start] > &trap_trace_end[0]) { 904 db_printf("Address out of range.\n"); 905 return; 906 } 907 if (!full) end = &trap_trace[start+1]; 908 } 909 910 db_printf("#:tl p:pid tt:tt:tstate:tfault sp:pc\n"); 911 if (reverse) { 912 if (full && start) 913 for (i=start; --i;) { 914 db_print_trace_entry(&trap_trace[i], i); 915 } 916 i = (end - &trap_trace[0]); 917 while(--i > start) { 918 db_print_trace_entry(&trap_trace[i], i); 919 } 920 } else { 921 for (i=start; &trap_trace[i] < end ; i++) { 922 db_print_trace_entry(&trap_trace[i], i); 923 } 924 if (full && start) 925 for (i=0; i < start ; i++) { 926 db_print_trace_entry(&trap_trace[i], i); 927 } 928 } 929 } 930 931 /* 932 * Use physical or virtul watchpoint registers -- ugh 933 * 934 * UltraSPARC I and II have both a virtual and physical 935 * watchpoint register. They are controlled by the LSU 936 * control register. 937 */ 938 void 939 db_watch(addr, have_addr, count, modif) 940 db_expr_t addr; 941 int have_addr; 942 db_expr_t count; 943 char *modif; 944 { 945 int phys = 0; 946 int read = 0; 947 int width = 8; /* Default to 8 bytes */ 948 int64_t mask = 0xff; 949 950 #define WATCH_VR (1L<<22) 951 #define WATCH_VW (1L<<21) 952 #define WATCH_PR (1L<<24) 953 #define WATCH_PW (1L<<23) 954 #define WATCH_PM_SHIFT 33 955 #define WATCH_PM (((u_int64_t)0xffffL)<<WATCH_PM_SHIFT) 956 #define WATCH_VM_SHIFT 25 957 #define WATCH_VM (((u_int64_t)0xffffL)<<WATCH_VM_SHIFT) 958 959 { 960 register char c, *cp = modif; 961 if (modif) 962 while ((c = *cp++) != 0) 963 switch (c) { 964 case 'p': 965 /* Physical watchpoint */ 966 phys = 1; 967 break; 968 case 'r': 969 /* Trap reads too */ 970 read = 1; 971 break; 972 case 'b': 973 width = 1; 974 mask = 0x1 << (addr & 0x7); 975 break; 976 case 'h': 977 width = 2; 978 mask = 0x3 << (addr & 0x6); 979 break; 980 case 'l': 981 width = 4; 982 mask = 0x7 << (addr & 0x4); 983 break; 984 case 'L': 985 width = 8; 986 mask = 0xf; 987 break; 988 default: 989 break; 990 } 991 } 992 993 if (have_addr) { 994 /* turn on the watchpoint */ 995 int64_t tmp = ldxa(0, ASI_MCCR); 996 997 if (phys) { 998 tmp &= ~WATCH_PM; 999 tmp |= WATCH_PW | (mask << WATCH_PM_SHIFT); 1000 if (read) tmp |= WATCH_PR; 1001 1002 stxa(PHYSICAL_WATCHPOINT, ASI_DMMU, addr); 1003 db_printf("Setting physical watchpoint to %llx-%llx\n", 1004 (long long)addr, (long long)addr + width); 1005 } else { 1006 tmp &= ~WATCH_VM; 1007 tmp |= WATCH_VW | (mask << WATCH_VM_SHIFT); 1008 if (read) tmp |= WATCH_VR; 1009 1010 stxa(VIRTUAL_WATCHPOINT, ASI_DMMU, addr); 1011 db_printf("Setting virtual watchpoint to %llx-%llx\n", 1012 (long long)addr, (long long)addr + width); 1013 } 1014 stxa(0, ASI_MCCR, tmp); 1015 } else { 1016 /* turn off the watchpoint */ 1017 int64_t tmp = ldxa(0, ASI_MCCR); 1018 if (phys) { 1019 tmp &= ~(WATCH_PM|WATCH_PR|WATCH_PW); 1020 db_printf("Disabling physical watchpoint\n"); 1021 } else { 1022 tmp &= ~(WATCH_VM|WATCH_VR|WATCH_VW); 1023 db_printf("Disabling virtual watchpoint\n"); 1024 } 1025 stxa(0, ASI_MCCR, tmp); 1026 } 1027 } 1028 1029 1030 #include <uvm/uvm.h> 1031 1032 void db_uvmhistdump __P((db_expr_t, int, db_expr_t, char *)); 1033 extern void uvmhist_dump __P((struct uvm_history *)); 1034 extern struct uvm_history_head uvm_histories; 1035 1036 void 1037 db_uvmhistdump(addr, have_addr, count, modif) 1038 db_expr_t addr; 1039 int have_addr; 1040 db_expr_t count; 1041 char *modif; 1042 { 1043 1044 uvmhist_dump(uvm_histories.lh_first); 1045 } 1046 1047 #if NESP_SBUS 1048 extern void db_esp(db_expr_t, int, db_expr_t, char*); 1049 #endif 1050 1051 const struct db_command db_machine_command_table[] = { 1052 { "ctx", db_ctx_cmd, 0, 0 }, 1053 { "dtlb", db_dump_dtlb, 0, 0 }, 1054 { "dtsb", db_dump_dtsb, 0, 0 }, 1055 #if NESP_SBUS 1056 { "esp", db_esp, 0, 0 }, 1057 #endif 1058 { "extract", db_pm_extract, 0, 0 }, 1059 { "fpstate", db_dump_fpstate,0, 0 }, 1060 { "kmap", db_pmap_kernel, 0, 0 }, 1061 { "lock", db_lock, 0, 0 }, 1062 { "pcb", db_dump_pcb, 0, 0 }, 1063 { "pctx", db_setpcb, 0, 0 }, 1064 { "page", db_page_cmd, 0, 0 }, 1065 { "phys", db_pload_cmd, 0, 0 }, 1066 { "pmap", db_pmap_cmd, 0, 0 }, 1067 { "proc", db_proc_cmd, 0, 0 }, 1068 { "prom", db_prom_cmd, 0, 0 }, 1069 { "pv", db_dump_pv, 0, 0 }, 1070 { "stack", db_dump_stack, 0, 0 }, 1071 { "tf", db_dump_trap, 0, 0 }, 1072 { "ts", db_dump_ts, 0, 0 }, 1073 { "traptrace", db_traptrace, 0, 0 }, 1074 { "uvmdump", db_uvmhistdump, 0, 0 }, 1075 { "watch", db_watch, 0, 0 }, 1076 { "window", db_dump_window, 0, 0 }, 1077 { (char *)0, } 1078 }; 1079 1080 /* 1081 * support for SOFTWARE_SSTEP: 1082 * return the next pc if the given branch is taken. 1083 * 1084 * note: in the case of conditional branches with annul, 1085 * this actually returns the next pc in the "not taken" path, 1086 * but in that case next_instr_address() will return the 1087 * next pc in the "taken" path. so even tho the breakpoints 1088 * are backwards, everything will still work, and the logic is 1089 * much simpler this way. 1090 */ 1091 db_addr_t 1092 db_branch_taken(inst, pc, regs) 1093 int inst; 1094 db_addr_t pc; 1095 db_regs_t *regs; 1096 { 1097 union instr insn; 1098 db_addr_t npc = ddb_regs.ddb_tf.tf_npc; 1099 1100 insn.i_int = inst; 1101 1102 /* 1103 * if this is not an annulled conditional branch, the next pc is "npc". 1104 */ 1105 1106 if (insn.i_any.i_op != IOP_OP2 || insn.i_branch.i_annul != 1) 1107 return npc; 1108 1109 switch (insn.i_op2.i_op2) { 1110 case IOP2_Bicc: 1111 case IOP2_FBfcc: 1112 case IOP2_BPcc: 1113 case IOP2_FBPfcc: 1114 case IOP2_CBccc: 1115 /* branch on some condition-code */ 1116 switch (insn.i_branch.i_cond) 1117 { 1118 case Icc_A: /* always */ 1119 return pc + ((inst << 10) >> 8); 1120 1121 default: /* all other conditions */ 1122 return npc + 4; 1123 } 1124 1125 case IOP2_BPr: 1126 /* branch on register, always conditional */ 1127 return npc + 4; 1128 1129 default: 1130 /* not a branch */ 1131 panic("branch_taken() on non-branch"); 1132 } 1133 } 1134 1135 boolean_t 1136 db_inst_branch(inst) 1137 int inst; 1138 { 1139 union instr insn; 1140 1141 insn.i_int = inst; 1142 1143 if (insn.i_any.i_op != IOP_OP2) 1144 return FALSE; 1145 1146 switch (insn.i_op2.i_op2) { 1147 case IOP2_BPcc: 1148 case IOP2_Bicc: 1149 case IOP2_BPr: 1150 case IOP2_FBPfcc: 1151 case IOP2_FBfcc: 1152 case IOP2_CBccc: 1153 return TRUE; 1154 1155 default: 1156 return FALSE; 1157 } 1158 } 1159 1160 1161 boolean_t 1162 db_inst_call(inst) 1163 int inst; 1164 { 1165 union instr insn; 1166 1167 insn.i_int = inst; 1168 1169 switch (insn.i_any.i_op) { 1170 case IOP_CALL: 1171 return TRUE; 1172 1173 case IOP_reg: 1174 return (insn.i_op3.i_op3 == IOP3_JMPL) && !db_inst_return(inst); 1175 1176 default: 1177 return FALSE; 1178 } 1179 } 1180 1181 1182 boolean_t 1183 db_inst_unconditional_flow_transfer(inst) 1184 int inst; 1185 { 1186 union instr insn; 1187 1188 insn.i_int = inst; 1189 1190 if (db_inst_call(inst)) 1191 return TRUE; 1192 1193 if (insn.i_any.i_op != IOP_OP2) 1194 return FALSE; 1195 1196 switch (insn.i_op2.i_op2) 1197 { 1198 case IOP2_BPcc: 1199 case IOP2_Bicc: 1200 case IOP2_FBPfcc: 1201 case IOP2_FBfcc: 1202 case IOP2_CBccc: 1203 return insn.i_branch.i_cond == Icc_A; 1204 1205 default: 1206 return FALSE; 1207 } 1208 } 1209 1210 1211 boolean_t 1212 db_inst_return(inst) 1213 int inst; 1214 { 1215 return (inst == I_JMPLri(I_G0, I_O7, 8) || /* ret */ 1216 inst == I_JMPLri(I_G0, I_I7, 8)); /* retl */ 1217 } 1218 1219 boolean_t 1220 db_inst_trap_return(inst) 1221 int inst; 1222 { 1223 union instr insn; 1224 1225 insn.i_int = inst; 1226 1227 return (insn.i_any.i_op == IOP_reg && 1228 insn.i_op3.i_op3 == IOP3_RETT); 1229 } 1230 1231 1232 int 1233 db_inst_load(inst) 1234 int inst; 1235 { 1236 union instr insn; 1237 1238 insn.i_int = inst; 1239 1240 if (insn.i_any.i_op != IOP_mem) 1241 return 0; 1242 1243 switch (insn.i_op3.i_op3) { 1244 case IOP3_LD: 1245 case IOP3_LDUB: 1246 case IOP3_LDUH: 1247 case IOP3_LDD: 1248 case IOP3_LDSB: 1249 case IOP3_LDSH: 1250 case IOP3_LDSTUB: 1251 case IOP3_SWAP: 1252 case IOP3_LDA: 1253 case IOP3_LDUBA: 1254 case IOP3_LDUHA: 1255 case IOP3_LDDA: 1256 case IOP3_LDSBA: 1257 case IOP3_LDSHA: 1258 case IOP3_LDSTUBA: 1259 case IOP3_SWAPA: 1260 case IOP3_LDF: 1261 case IOP3_LDFSR: 1262 case IOP3_LDDF: 1263 case IOP3_LFC: 1264 case IOP3_LDCSR: 1265 case IOP3_LDDC: 1266 return 1; 1267 1268 default: 1269 return 0; 1270 } 1271 } 1272 1273 int 1274 db_inst_store(inst) 1275 int inst; 1276 { 1277 union instr insn; 1278 1279 insn.i_int = inst; 1280 1281 if (insn.i_any.i_op != IOP_mem) 1282 return 0; 1283 1284 switch (insn.i_op3.i_op3) { 1285 case IOP3_ST: 1286 case IOP3_STB: 1287 case IOP3_STH: 1288 case IOP3_STD: 1289 case IOP3_LDSTUB: 1290 case IOP3_SWAP: 1291 case IOP3_STA: 1292 case IOP3_STBA: 1293 case IOP3_STHA: 1294 case IOP3_STDA: 1295 case IOP3_LDSTUBA: 1296 case IOP3_SWAPA: 1297 case IOP3_STF: 1298 case IOP3_STFSR: 1299 case IOP3_STDFQ: 1300 case IOP3_STDF: 1301 case IOP3_STC: 1302 case IOP3_STCSR: 1303 case IOP3_STDCQ: 1304 case IOP3_STDC: 1305 return 1; 1306 1307 default: 1308 return 0; 1309 } 1310 } 1311