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