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