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