xref: /netbsd-src/sys/arch/sh3/sh3/db_interface.c (revision dbfa10e52a5827a2b548912aaaea11468b4c7f47)
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
kdb_printtrap(u_int type,int code)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
kdb_trap(int type,int code,db_regs_t * regs)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
cpu_Debugger(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
inst_call(int inst)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
inst_return(int inst)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
inst_trap_return(int inst)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
db_set_single_step(db_regs_t * regs)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
db_clear_single_step(db_regs_t * regs)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
db_tlbdump_cmd(db_expr_t addr,bool have_addr,db_expr_t count,const char * modif)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
__db_get_itlb_sh4(uint32_t e,uint32_t * paa,uint32_t * pda1,uint32_t * pda2)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
__db_get_utlb_sh4(uint32_t e,uint32_t * paa,uint32_t * pda1,uint32_t * pda2)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
__db_tlbdump_pfn(uint32_t r)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 *
__db_procname_by_asid(int asid)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
__db_tlbdump_page_size_sh4(uint32_t r)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
db_cachedump_cmd(db_expr_t addr,bool have_addr,db_expr_t count,const char * modif)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
__db_cachedump_sh3(vaddr_t va_start)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
__db_cachedump_sh4(vaddr_t va)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
db_frame_cmd(db_expr_t addr,bool have_addr,db_expr_t count,const char * modif)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
__db_print_tfstack(struct trapframe * tf,struct trapframe * tfbot)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
__db_print_symbol(db_expr_t value)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
db_stackcheck_cmd(db_expr_t addr,bool have_addr,db_expr_t count,const char * modif)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
db_reset_cmd(db_expr_t addr,bool have_addr,db_expr_t count,const char * modif)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