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