1 /* $NetBSD: db_interface.c,v 1.19 2002/05/13 20:30:10 matt Exp $ */ 2 3 /*- 4 * Copyright (C) 2002 UCHIYAMA Yasushi. All rights reserved. 5 * Copyright (c) 2000 Tsubai Masanari. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. The name of the author may not be used to endorse or promote products 16 * derived from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 #include "opt_ddb.h" 31 #include "opt_kgdb.h" 32 #include "opt_kstack_debug.h" 33 34 #include <sys/param.h> 35 #include <sys/systm.h> 36 #include <sys/user.h> 37 38 #include <uvm/uvm_extern.h> 39 40 #include <dev/cons.h> 41 42 #include <machine/db_machdep.h> 43 #include <ddb/db_run.h> 44 #include <ddb/db_sym.h> 45 46 #include <sh3/ubcreg.h> 47 48 extern char *exp_type[]; 49 extern int exp_types; 50 51 #ifndef KGDB 52 #include <sh3/cache.h> 53 #include <sh3/cache_sh3.h> 54 #include <sh3/cache_sh4.h> 55 #include <sh3/mmu.h> 56 #include <sh3/mmu_sh3.h> 57 #include <sh3/mmu_sh4.h> 58 59 #include <ddb/db_command.h> 60 #include <ddb/db_extern.h> 61 #include <ddb/db_output.h> 62 #include <ddb/db_run.h> 63 #include <ddb/ddbvar.h> 64 65 void kdb_printtrap(u_int, int); 66 67 void db_tlbdump_cmd(db_expr_t, int, db_expr_t, char *); 68 void __db_tlbdump_page_size_sh4(u_int32_t); 69 void __db_tlbdump_pfn(u_int32_t); 70 void db_cachedump_cmd(db_expr_t, int, db_expr_t, char *); 71 72 void __db_cachedump_sh3(vaddr_t); 73 void __db_cachedump_sh4(vaddr_t); 74 75 void db_stackcheck_cmd(db_expr_t, int, db_expr_t, char *); 76 void db_frame_cmd(db_expr_t, int, db_expr_t, char *); 77 void __db_print_symbol(db_expr_t); 78 char *__db_procname_by_asid(int); 79 80 const struct db_command db_machine_command_table[] = { 81 { "tlb", db_tlbdump_cmd, 0, 0 }, 82 { "cache", db_cachedump_cmd, 0, 0 }, 83 { "frame", db_frame_cmd, 0, 0 }, 84 #ifdef KSTACK_DEBUG 85 { "stack", db_stackcheck_cmd, 0, 0 }, 86 #endif 87 { 0 } 88 }; 89 90 int db_active; 91 92 void 93 kdb_printtrap(u_int type, int code) 94 { 95 int i; 96 i = type >> 5; 97 98 db_printf("%s mode trap: ", type & 1 ? "user" : "kernel"); 99 if (i >= exp_types) 100 db_printf("type 0x%03x", type & ~1); 101 else 102 db_printf("%s", exp_type[i]); 103 104 db_printf(" code = 0x%x\n", code); 105 } 106 107 int 108 kdb_trap(int type, int code, db_regs_t *regs) 109 { 110 int s; 111 112 switch (type) { 113 case EXPEVT_TRAPA: /* trapa instruction */ 114 case EXPEVT_BREAK: /* UBC */ 115 case -1: /* keyboard interrupt */ 116 break; 117 default: 118 if (!db_onpanic && db_recover == 0) 119 return 0; 120 121 kdb_printtrap(type, code); 122 if (db_recover != 0) { 123 db_error("Faulted in DDB; continuing...\n"); 124 /*NOTREACHED*/ 125 } 126 } 127 128 /* XXX Should switch to kdb's own stack here. */ 129 130 ddb_regs = *regs; 131 132 s = splhigh(); 133 db_active++; 134 cnpollc(TRUE); 135 db_trap(type, code); 136 cnpollc(FALSE); 137 db_active--; 138 splx(s); 139 140 *regs = ddb_regs; 141 142 return 1; 143 } 144 145 void 146 cpu_Debugger() 147 { 148 149 __asm__ __volatile__("trapa %0" :: "i"(_SH_TRA_BREAK)); 150 } 151 #endif /* !KGDB */ 152 153 #define M_BSR 0xf000 154 #define I_BSR 0xb000 155 #define M_BSRF 0xf0ff 156 #define I_BSRF 0x0003 157 #define M_JSR 0xf0ff 158 #define I_JSR 0x400b 159 #define M_RTS 0xffff 160 #define I_RTS 0x000b 161 #define M_RTE 0xffff 162 #define I_RTE 0x002b 163 164 boolean_t 165 inst_call(int inst) 166 { 167 #if _BYTE_ORDER == BIG_ENDIAN 168 inst >>= 16; 169 #endif 170 return (inst & M_BSR) == I_BSR || (inst & M_BSRF) == I_BSRF || 171 (inst & M_JSR) == I_JSR; 172 } 173 174 boolean_t 175 inst_return(int inst) 176 { 177 #if _BYTE_ORDER == BIG_ENDIAN 178 inst >>= 16; 179 #endif 180 return (inst & M_RTS) == I_RTS; 181 } 182 183 boolean_t 184 inst_trap_return(int inst) 185 { 186 #if _BYTE_ORDER == BIG_ENDIAN 187 inst >>= 16; 188 #endif 189 return (inst & M_RTE) == I_RTE; 190 } 191 192 void 193 db_set_single_step(db_regs_t *regs) 194 { 195 196 _reg_write_2(SH_(BBRA), 0); /* disable break */ 197 _reg_write_4(SH_(BARA), 0); /* break address */ 198 _reg_write_1(SH_(BASRA), 0); /* break ASID */ 199 _reg_write_1(SH_(BAMRA), 0x07); /* break always */ 200 _reg_write_2(SH_(BRCR), 0x400); /* break after each execution */ 201 202 regs->tf_ubc = 0x0014; /* will be written to BBRA */ 203 } 204 205 void 206 db_clear_single_step(db_regs_t *regs) 207 { 208 209 regs->tf_ubc = 0; 210 } 211 212 #ifndef KGDB 213 /* 214 * MMU 215 */ 216 #define ON(x, c) ((x) & (c) ? '|' : '.') 217 void 218 db_tlbdump_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif) 219 { 220 static const char *pr[] = { "_r", "_w", "rr", "ww" }; 221 static const char title[] = 222 " VPN ASID PFN AREA VDCGWtPR SZ"; 223 static const char title2[] = 224 " U/K U/K"; 225 u_int32_t r, e; 226 int i; 227 #ifdef SH3 228 if (CPU_IS_SH3) { 229 /* MMU configuration. */ 230 r = _reg_read_4(SH3_MMUCR); 231 db_printf("%s-mode, %s virtual storage mode\n", 232 r & SH3_MMUCR_IX 233 ? "ASID + VPN" : "VPN only", 234 r & SH3_MMUCR_SV ? "single" : "multiple"); 235 i = _reg_read_4(SH3_PTEH) & SH3_PTEH_ASID_MASK; 236 db_printf("ASID=%d (%s)", i, __db_procname_by_asid(i)); 237 238 db_printf("---TLB DUMP---\n%s\n%s\n", title, title2); 239 for (i = 0; i < SH3_MMU_WAY; i++) { 240 db_printf(" [way %d]\n", i); 241 for (e = 0; e < SH3_MMU_ENTRY; e++) { 242 u_int32_t a; 243 /* address/data array common offset. */ 244 a = (e << SH3_MMU_VPN_SHIFT) | 245 (i << SH3_MMU_WAY_SHIFT); 246 247 r = _reg_read_4(SH3_MMUAA | a); 248 if (r == 0) { 249 db_printf("---------- - --- ----------" 250 " - ----x -- --\n"); 251 } else { 252 vaddr_t va; 253 int asid; 254 asid = r & SH3_MMUAA_D_ASID_MASK; 255 r &= SH3_MMUAA_D_VPN_MASK_1K; 256 va = r | (e << SH3_MMU_VPN_SHIFT); 257 db_printf("0x%08lx %c %3d", va, 258 (int)va < 0 ? 'K' : 'U', asid); 259 260 r = _reg_read_4(SH3_MMUDA | a); 261 __db_tlbdump_pfn(r); 262 263 db_printf(" %c%c%c%cx %s %2dK\n", 264 ON(r, SH3_MMUDA_D_V), 265 ON(r, SH3_MMUDA_D_D), 266 ON(r, SH3_MMUDA_D_C), 267 ON(r, SH3_MMUDA_D_SH), 268 pr[(r & SH3_MMUDA_D_PR_MASK) >> 269 SH3_MMUDA_D_PR_SHIFT], 270 r & SH3_MMUDA_D_SZ ? 4 : 1); 271 } 272 } 273 } 274 } 275 #endif /* SH3 */ 276 #ifdef SH4 277 if (CPU_IS_SH4) { 278 /* MMU configuration */ 279 r = _reg_read_4(SH4_MMUCR); 280 db_printf("%s virtual storage mode, SQ access: (kernel%s)\n", 281 r & SH3_MMUCR_SV ? "single" : "multiple", 282 r & SH4_MMUCR_SQMD ? "" : "/user"); 283 db_printf("random counter limit=%d\n", (r & SH4_MMUCR_URB_MASK) >> 284 SH4_MMUCR_URB_SHIFT); 285 i = _reg_read_4(SH4_PTEH) & SH4_PTEH_ASID_MASK; 286 db_printf("ASID=%d (%s)", i, __db_procname_by_asid(i)); 287 288 /* Dump ITLB */ 289 db_printf("---ITLB DUMP ---\n%s TC SA\n%s\n", title, title2); 290 for (i = 0; i < 4; i++) { 291 e = i << SH4_ITLB_E_SHIFT; 292 r = _reg_read_4(SH4_ITLB_AA | e); 293 db_printf("0x%08x %3d", 294 r & SH4_ITLB_AA_VPN_MASK, 295 r & SH4_ITLB_AA_ASID_MASK); 296 r = _reg_read_4(SH4_ITLB_DA1 | e); 297 __db_tlbdump_pfn(r); 298 db_printf(" %c_%c%c_ %s ", 299 ON(r, SH4_ITLB_DA1_V), 300 ON(r, SH4_ITLB_DA1_C), 301 ON(r, SH4_ITLB_DA1_SH), 302 pr[(r & SH4_ITLB_DA1_PR) >> 303 SH4_UTLB_DA1_PR_SHIFT]); 304 __db_tlbdump_page_size_sh4(r); 305 r = _reg_read_4(SH4_ITLB_DA2 | e); 306 db_printf(" %c %d\n", 307 ON(r, SH4_ITLB_DA2_TC), 308 r & SH4_ITLB_DA2_SA_MASK); 309 } 310 /* Dump UTLB */ 311 db_printf("---UTLB DUMP---\n%s TC SA\n%s\n", title, title2); 312 for (i = 0; i < 64; i++) { 313 e = i << SH4_UTLB_E_SHIFT; 314 r = _reg_read_4(SH4_UTLB_AA | e); 315 db_printf("0x%08x %3d", 316 r & SH4_UTLB_AA_VPN_MASK, 317 r & SH4_UTLB_AA_ASID_MASK); 318 r = _reg_read_4(SH4_UTLB_DA1 | e); 319 __db_tlbdump_pfn(r); 320 db_printf(" %c%c%c%c%c %s ", 321 ON(r, SH4_UTLB_DA1_V), 322 ON(r, SH4_UTLB_DA1_D), 323 ON(r, SH4_UTLB_DA1_C), 324 ON(r, SH4_UTLB_DA1_SH), 325 ON(r, SH4_UTLB_DA1_WT), 326 pr[(r & SH4_UTLB_DA1_PR_MASK) >> 327 SH4_UTLB_DA1_PR_SHIFT] 328 ); 329 __db_tlbdump_page_size_sh4(r); 330 r = _reg_read_4(SH4_UTLB_DA2 | e); 331 db_printf(" %c %d\n", 332 ON(r, SH4_UTLB_DA2_TC), 333 r & SH4_UTLB_DA2_SA_MASK); 334 } 335 } 336 #endif /* SH4 */ 337 } 338 339 void 340 __db_tlbdump_pfn(u_int32_t r) 341 { 342 u_int32_t pa = (r & SH3_MMUDA_D_PPN_MASK); 343 344 db_printf(" 0x%08x %d", pa, (pa >> 26) & 7); 345 } 346 347 char * 348 __db_procname_by_asid(int asid) 349 { 350 static char notfound[] = "---"; 351 struct proc *p; 352 353 LIST_FOREACH(p, &allproc, p_list) { 354 if (p->p_vmspace->vm_map.pmap->pm_asid == asid) 355 return (p->p_comm); 356 } 357 358 return (notfound); 359 } 360 361 #ifdef SH4 362 void 363 __db_tlbdump_page_size_sh4(u_int32_t r) 364 { 365 switch (r & SH4_PTEL_SZ_MASK) { 366 case SH4_PTEL_SZ_1K: 367 db_printf(" 1K"); 368 break; 369 case SH4_PTEL_SZ_4K: 370 db_printf(" 4K"); 371 break; 372 case SH4_PTEL_SZ_64K: 373 db_printf("64K"); 374 break; 375 case SH4_PTEL_SZ_1M: 376 db_printf(" 1M"); 377 break; 378 } 379 } 380 #endif /* SH4 */ 381 382 /* 383 * CACHE 384 */ 385 void 386 db_cachedump_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif) 387 { 388 #ifdef SH3 389 if (CPU_IS_SH3) 390 __db_cachedump_sh3(have_addr ? addr : 0); 391 #endif 392 #ifdef SH4 393 if (CPU_IS_SH4) 394 __db_cachedump_sh4(have_addr ? addr : 0); 395 #endif 396 } 397 398 #ifdef SH3 399 void 400 __db_cachedump_sh3(vaddr_t va_start) 401 { 402 u_int32_t r; 403 vaddr_t va, va_end, cca; 404 int entry, way; 405 406 RUN_P2; 407 /* disable cache */ 408 _reg_write_4(SH3_CCR, 409 _reg_read_4(SH3_CCR) & ~SH3_CCR_CE); 410 411 if (va_start) { 412 va = va_start & ~(sh_cache_line_size - 1); 413 va_end = va + sh_cache_line_size; 414 } else { 415 va = 0; 416 va_end = sh_cache_way_size; 417 } 418 419 db_printf("%d-way, way-size=%dB, way-shift=%d, entry-mask=%08x, " 420 "line-size=%dB \n", sh_cache_ways, sh_cache_way_size, 421 sh_cache_way_shift, sh_cache_entry_mask, sh_cache_line_size); 422 db_printf("Entry Way 0 UV Way 1 UV Way 2 UV Way 3 UV\n"); 423 for (; va < va_end; va += sh_cache_line_size) { 424 entry = va & sh_cache_entry_mask; 425 cca = SH3_CCA | entry; 426 db_printf(" %3d ", entry >> CCA_ENTRY_SHIFT); 427 for (way = 0; way < sh_cache_ways; way++) { 428 r = _reg_read_4(cca | (way << sh_cache_way_shift)); 429 db_printf("%08x %c%c ", r & CCA_TAGADDR_MASK, 430 ON(r, CCA_U), ON(r, CCA_V)); 431 } 432 db_printf("\n"); 433 } 434 435 /* enable cache */ 436 _reg_write_4(SH3_CCR, _reg_read_4(SH3_CCR) | SH3_CCR_CE); 437 sh_icache_sync_all(); 438 439 RUN_P1; 440 } 441 #endif /* SH3 */ 442 443 #ifdef SH4 444 void 445 __db_cachedump_sh4(vaddr_t va) 446 { 447 u_int32_t r, e; 448 int i, istart, iend; 449 450 RUN_P2; /* must access from P2 */ 451 452 /* disable I/D-cache */ 453 _reg_write_4(SH4_CCR, 454 _reg_read_4(SH4_CCR) & ~(SH4_CCR_ICE | SH4_CCR_OCE)); 455 456 if (va) { 457 istart = ((va & CCIA_ENTRY_MASK) >> CCIA_ENTRY_SHIFT) & ~3; 458 iend = istart + 4; 459 } else { 460 istart = 0; 461 iend = SH4_ICACHE_SIZE / SH4_CACHE_LINESZ; 462 } 463 464 db_printf("[I-cache]\n"); 465 db_printf(" Entry V V V V\n"); 466 for (i = istart; i < iend; i++) { 467 if ((i & 3) == 0) 468 db_printf("\n[%3d-%3d] ", i, i + 3); 469 r = _reg_read_4(SH4_CCIA | (i << CCIA_ENTRY_SHIFT)); 470 db_printf("%08x _%c ", r & CCIA_TAGADDR_MASK, ON(r, CCIA_V)); 471 } 472 473 db_printf("\n[D-cache]\n"); 474 db_printf(" Entry UV UV UV UV\n"); 475 for (i = istart; i < iend; i++) { 476 if ((i & 3) == 0) 477 db_printf("\n[%3d-%3d] ", i, i + 3); 478 e = (i << CCDA_ENTRY_SHIFT); 479 r = _reg_read_4(SH4_CCDA | e); 480 db_printf("%08x %c%c ", r & CCDA_TAGADDR_MASK, ON(r, CCDA_U), 481 ON(r, CCDA_V)); 482 483 } 484 db_printf("\n"); 485 486 _reg_write_4(SH4_CCR, 487 _reg_read_4(SH4_CCR) | SH4_CCR_ICE | SH4_CCR_OCE); 488 sh_icache_sync_all(); 489 490 RUN_P1; 491 } 492 #endif /* SH4 */ 493 #undef ON 494 495 void 496 db_frame_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif) 497 { 498 struct switchframe *sf = &curpcb->pcb_sf; 499 struct trapframe *tf, *tftop; 500 501 /* Print switch frame */ 502 db_printf("[switch frame]\n"); 503 #define SF(x) db_printf("sf_" #x "\t\t0x%08x\t", sf->sf_ ## x); \ 504 __db_print_symbol(sf->sf_ ## x) 505 SF(sr); 506 SF(r15); 507 SF(r14); 508 SF(r13); 509 SF(r12); 510 SF(r11); 511 SF(r10); 512 SF(r9); 513 SF(r8); 514 SF(pr); 515 #undef SF 516 db_printf("sf_r6_bank\t0x%08x\n", sf->sf_r6_bank); 517 db_printf("sf_r7_bank\t0x%08x\n", sf->sf_r7_bank); 518 519 tftop = (struct trapframe *)((vaddr_t)curpcb + NBPG); 520 521 /* Print trap frame stack */ 522 db_printf("[trap frame]\n"); 523 __asm__ __volatile__("stc r6_bank, %0" :: "r"(tf)); 524 for (; tf != tftop; tf++) { 525 db_printf("-- %p-%p --\n", tf, tf + 1); 526 db_printf("tf_expevt\t0x%08x\n", tf->tf_expevt); 527 #define TF(x) db_printf("tf_" #x "\t\t0x%08x\t", tf->tf_ ## x); \ 528 __db_print_symbol(tf->tf_ ## x) 529 TF(ubc); 530 TF(spc); 531 TF(ssr); 532 TF(macl); 533 TF(mach); 534 TF(pr); 535 TF(r13); 536 TF(r12); 537 TF(r11); 538 TF(r10); 539 TF(r9); 540 TF(r8); 541 TF(r7); 542 TF(r6); 543 TF(r5); 544 TF(r4); 545 TF(r3); 546 TF(r2); 547 TF(r1); 548 TF(r0); 549 TF(r15); 550 TF(r14); 551 #undef TF 552 } 553 } 554 555 void 556 __db_print_symbol(db_expr_t value) 557 { 558 char *name; 559 db_expr_t offset; 560 561 db_find_xtrn_sym_and_offset((db_addr_t)value, &name, &offset); 562 563 if (name != 0 && offset <= db_maxoff && offset != value) 564 db_print_loc_and_inst(value); 565 else 566 db_printf("\n"); 567 568 } 569 570 #ifdef KSTACK_DEBUG 571 /* 572 * Stack overflow check 573 */ 574 void 575 db_stackcheck_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif) 576 { 577 struct proc *p; 578 struct user *u; 579 struct pcb *pcb; 580 u_int32_t *t32; 581 u_int8_t *t8; 582 int i, j; 583 #define MAX_STACK (USPACE - NBPG) 584 #define MAX_FRAME (NBPG - sizeof(struct user)) 585 db_printf("stack max: %d byte, frame max %d byte," 586 " sizeof(struct trapframe) %d byte\n", MAX_STACK, MAX_FRAME, 587 sizeof(struct trapframe)); 588 db_printf("PID stack top max used frame top max used" 589 " nest\n"); 590 LIST_FOREACH(p, &allproc, p_list) { 591 u = p->p_addr; 592 pcb = &u->u_pcb; 593 /* stack */ 594 t32 = (u_int32_t *)(pcb->pcb_sf.sf_r7_bank - MAX_STACK); 595 for (i = 0; *t32++ == 0xa5a5a5a5; i++) 596 ; 597 i = MAX_STACK - i * sizeof(int); 598 599 /* frame */ 600 t8 = (u_int8_t *)((vaddr_t)pcb + NBPG - MAX_FRAME); 601 for (j = 0; *t8++ == 0x5a; j++) 602 ; 603 j = MAX_FRAME - j; 604 605 db_printf("%-6d 0x%08x %6d (%3d%%) 0x%08lx %6d (%3d%%) %d %s\n", 606 p->p_pid, 607 pcb->pcb_sf.sf_r7_bank, i, i * 100 / MAX_STACK, 608 (vaddr_t)pcb + NBPG, j, j * 100 / MAX_FRAME, 609 j / sizeof(struct trapframe), 610 p->p_comm); 611 } 612 #undef MAX_STACK 613 #undef MAX_FRAME 614 } 615 #endif /* KSTACK_DEBUG */ 616 #endif /* !KGDB */ 617