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