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