Home | History | Annotate | Line # | Download | only in sh3
      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