db_interface.c revision 1.67
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 50db_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 66static void kdb_printtrap(u_int, int); 67 68static void db_tlbdump_cmd(db_expr_t, bool, db_expr_t, const char *); 69#ifdef SH4 70static __noinline void 71__db_get_itlb_sh4(uint32_t, uint32_t *, uint32_t *, uint32_t *); 72static __noinline void 73__db_get_utlb_sh4(uint32_t, uint32_t *, uint32_t *, uint32_t *); 74#endif 75 76static char *__db_procname_by_asid(int); 77static void __db_tlbdump_pfn(uint32_t); 78#ifdef SH4 79static void __db_tlbdump_page_size_sh4(uint32_t); 80#endif 81 82static void db_cachedump_cmd(db_expr_t, bool, db_expr_t, const char *); 83#ifdef SH3 84static __noinline void __db_cachedump_sh3(vaddr_t); 85#endif 86#ifdef SH4 87static __noinline void __db_cachedump_sh4(vaddr_t); 88#endif 89 90static void db_frame_cmd(db_expr_t, bool, db_expr_t, const char *); 91static void __db_print_symbol(db_expr_t); 92static void __db_print_tfstack(struct trapframe *, struct trapframe *); 93 94static void db_reset_cmd(db_expr_t, bool, db_expr_t, const char *); 95 96#ifdef KSTACK_DEBUG 97static void db_stackcheck_cmd(db_expr_t, bool, db_expr_t, const char *); 98#endif 99 100 101const 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 126int db_active; 127 128 129static void 130kdb_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 144int 145kdb_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 186void 187cpu_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 205bool 206inst_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 215bool 216inst_return(int inst) 217{ 218#if _BYTE_ORDER == BIG_ENDIAN 219 inst >>= 16; 220#endif 221 return (inst & M_RTS) == I_RTS; 222} 223 224bool 225inst_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 233void 234db_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 254void 255db_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 */ 268static void 269db_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 406static __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 416static __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 427static 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 435static 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 450static 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 */ 473static void 474db_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 491static __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 533static __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 581static void 582db_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 619static 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 660static 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 */ 677static void 678db_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 724static void 725db_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