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