db_interface.c revision 99730
1/*	$FreeBSD: head/sys/powerpc/powerpc/db_interface.c 99730 2002-07-10 12:21:54Z benno $ */
2/*	$NetBSD: db_interface.c,v 1.20 2002/05/13 20:30:09 matt Exp $ */
3/*	$OpenBSD: db_interface.c,v 1.2 1996/12/28 06:21:50 rahnds Exp $	*/
4
5#define USERACC
6
7#include "opt_ddb.h"
8
9#include <sys/param.h>
10#include <sys/proc.h>
11#include <sys/systm.h>
12
13#include <machine/db_machdep.h>
14#include <machine/frame.h>
15#include <machine/trap.h>
16#ifdef PPC_IBM4XX
17#include <machine/tlb.h>
18#include <powerpc/spr.h>
19#include <uvm/uvm_extern.h>
20#endif
21
22#ifdef DDB
23#include <ddb/ddb.h>
24#include <ddb/db_sym.h>
25#include <ddb/db_command.h>
26#include <ddb/db_access.h>
27#include <ddb/db_output.h>
28#endif
29
30#ifdef KGDB
31#include <sys/kgdb.h>
32#endif
33
34#include <dev/ofw/openfirm.h>
35
36int	db_active = 0;
37
38db_regs_t ddb_regs;
39
40void ddb_trap(void);				/* Call into trap_subr.S */
41int ddb_trap_glue(struct trapframe *);		/* Called from trap_subr.S */
42#ifdef PPC_IBM4XX
43static void db_ppc4xx_ctx(db_expr_t, int, db_expr_t, char *);
44static void db_ppc4xx_pv(db_expr_t, int, db_expr_t, char *);
45static void db_ppc4xx_reset(db_expr_t, int, db_expr_t, char *);
46static void db_ppc4xx_tf(db_expr_t, int, db_expr_t, char *);
47static void db_ppc4xx_dumptlb(db_expr_t, int, db_expr_t, char *);
48#ifdef USERACC
49static void db_ppc4xx_useracc(db_expr_t, int, db_expr_t, char *);
50#endif
51#endif /* PPC_IBM4XX */
52
53#ifdef DDB
54void
55Debugger(const char *msg)
56{
57	db_printf("Welcome to Debugger, %s\n", msg);
58	ddb_trap();
59}
60#endif
61
62int
63ddb_trap_glue(frame)
64	struct trapframe *frame;
65{
66	if (!(frame->srr1 & PSL_PR)
67	    && (frame->exc == EXC_TRC || frame->exc == EXC_RUNMODETRC
68		|| (frame->exc == EXC_PGM
69		    && (frame->srr1 & 0x20000))
70		|| frame->exc == EXC_BPT)) {
71		int type = frame->exc;
72		if (type == EXC_PGM && (frame->srr1 & 0x20000)) {
73			type = T_BREAKPOINT;
74		}
75		return kdb_trap(type, frame);
76	}
77	return 0;
78}
79
80int
81kdb_trap(type, v)
82	int type;
83	void *v;
84{
85	struct trapframe *frame = v;
86
87#if 0
88	switch (type) {
89	case T_BREAKPOINT:
90	case -1:
91		break;
92	default:
93		if (!db_onpanic && db_recover == 0)
94			return 0;
95		if (db_recover != 0) {
96			db_error("Faulted in DDB; continuing...\n");
97			/*NOTREACHED*/
98		}
99	}
100#endif
101
102	/* XXX Should switch to kdb's own stack here. */
103
104	memcpy(DDB_REGS->r, frame->fixreg, 32 * sizeof(u_int32_t));
105	DDB_REGS->iar = frame->srr0;
106	DDB_REGS->msr = frame->srr1;
107	DDB_REGS->lr = frame->lr;
108	DDB_REGS->ctr = frame->ctr;
109	DDB_REGS->cr = frame->cr;
110	DDB_REGS->xer = frame->xer;
111#ifdef PPC_IBM4XX
112	DDB_REGS->dear = frame->dear;
113	DDB_REGS->esr = frame->esr;
114	DDB_REGS->pid = frame->pid;
115#endif
116
117#ifdef DDB
118	db_active++;
119	cndbctl(1);
120	db_trap(type, 0);
121	cndbctl(0);
122	db_active--;
123#elif defined(KGDB)
124	if (!kgdb_trap(type, DDB_REGS))
125		return 0;
126#endif
127
128	/* KGDB isn't smart about advancing PC if we
129	 * take a breakpoint trap after kgdb_active is set.
130	 * Therefore, we help out here.
131	 */
132	if (IS_BREAKPOINT_TRAP(type, 0)) {
133		int bkpt;
134		db_read_bytes(PC_REGS(DDB_REGS),BKPT_SIZE,(void *)&bkpt);
135		if (bkpt== BKPT_INST) {
136			PC_REGS(DDB_REGS) += BKPT_SIZE;
137		}
138	}
139
140	memcpy(frame->fixreg, DDB_REGS->r, 32 * sizeof(u_int32_t));
141	frame->srr0 = DDB_REGS->iar;
142	frame->srr1 = DDB_REGS->msr;
143	frame->lr = DDB_REGS->lr;
144	frame->ctr = DDB_REGS->ctr;
145	frame->cr = DDB_REGS->cr;
146	frame->xer = DDB_REGS->xer;
147#ifdef PPC_IBM4XX
148	frame->dear = DDB_REGS->dear;
149	frame->esr = DDB_REGS->esr;
150	frame->pid = DDB_REGS->pid;
151#endif
152
153	return 1;
154}
155
156#ifdef PPC_IBM4XX
157const struct db_command db_machine_command_table[] = {
158	{ "ctx",	db_ppc4xx_ctx,		0,	0 },
159	{ "pv",		db_ppc4xx_pv,		0,	0 },
160	{ "reset",	db_ppc4xx_reset,	0,	0 },
161	{ "tf",		db_ppc4xx_tf,	0,	0 },
162	{ "tlb",	db_ppc4xx_dumptlb,	0,	0 },
163#ifdef USERACC
164	{ "user",	db_ppc4xx_useracc,	0,	0 },
165#endif
166	{ NULL, }
167};
168
169static void
170db_ppc4xx_ctx(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
171{
172	struct proc *p;
173
174	/* XXX LOCKING XXX */
175	for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) {
176		if (p->p_stat) {
177			db_printf("process %p:", p);
178			db_printf("pid:%d pmap:%p ctx:%d %s\n",
179				p->p_pid, p->p_vmspace->vm_map.pmap,
180				p->p_vmspace->vm_map.pmap->pm_ctx,
181				p->p_comm);
182		}
183	}
184	return;
185}
186
187static void
188db_ppc4xx_pv(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
189{
190	struct pv_entry {
191		struct pv_entry *pv_next;	/* Linked list of mappings */
192		vaddr_t pv_va;			/* virtual address of mapping */
193		struct pmap *pv_pm;
194	};
195	struct pv_entry *pa_to_pv(paddr_t);
196	struct pv_entry *pv;
197
198	if (!have_addr) {
199		db_printf("pv: <pa>\n");
200		return;
201	}
202	pv = pa_to_pv(addr);
203	db_printf("pv at %p\n", pv);
204	while (pv && pv->pv_pm) {
205		db_printf("next %p va %p pmap %p\n", pv->pv_next,
206			(void *)pv->pv_va, pv->pv_pm);
207		pv = pv->pv_next;
208	}
209}
210
211static void
212db_ppc4xx_reset(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
213{
214	printf("Reseting...\n");
215	ppc4xx_reset();
216}
217
218static void
219db_ppc4xx_tf(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
220{
221	struct trapframe *f;
222
223
224	if (have_addr) {
225		f = (struct trapframe *)addr;
226
227		db_printf("r0-r3:  \t%8.8x %8.8x %8.8x %8.8x\n",
228			f->fixreg[0], f->fixreg[1],
229			f->fixreg[2], f->fixreg[3]);
230		db_printf("r4-r7:  \t%8.8x %8.8x %8.8x %8.8x\n",
231			f->fixreg[4], f->fixreg[5],
232			f->fixreg[6], f->fixreg[7]);
233		db_printf("r8-r11: \t%8.8x %8.8x %8.8x %8.8x\n",
234			f->fixreg[8], f->fixreg[9],
235			f->fixreg[10], f->fixreg[11]);
236		db_printf("r12-r15:\t%8.8x %8.8x %8.8x %8.8x\n",
237			f->fixreg[12], f->fixreg[13],
238			f->fixreg[14], f->fixreg[15]);
239		db_printf("r16-r19:\t%8.8x %8.8x %8.8x %8.8x\n",
240			f->fixreg[16], f->fixreg[17],
241			f->fixreg[18], f->fixreg[19]);
242		db_printf("r20-r23:\t%8.8x %8.8x %8.8x %8.8x\n",
243			f->fixreg[20], f->fixreg[21],
244			f->fixreg[22], f->fixreg[23]);
245		db_printf("r24-r27:\t%8.8x %8.8x %8.8x %8.8x\n",
246			f->fixreg[24], f->fixreg[25],
247			f->fixreg[26], f->fixreg[27]);
248		db_printf("r28-r31:\t%8.8x %8.8x %8.8x %8.8x\n",
249			f->fixreg[28], f->fixreg[29],
250			f->fixreg[30], f->fixreg[31]);
251
252		db_printf("lr: %8.8x cr: %8.8x xer: %8.8x ctr: %8.8x\n",
253			f->lr, f->cr, f->xer, f->ctr);
254		db_printf("srr0(pc): %8.8x srr1(msr): %8.8x "
255			"dear: %8.8x esr: %8.8x\n",
256			f->srr0, f->srr1, f->dear, f->esr);
257		db_printf("exc: %8.8x pid: %8.8x\n",
258			f->exc, f->pid);
259	}
260	return;
261}
262
263static const char *const tlbsizes[] = {
264	  "1kB",
265	  "4kB",
266	 "16kB",
267	 "64kB",
268	"256kB",
269	  "1MB",
270	  "4MB",
271	 "16MB"
272};
273
274static void
275db_ppc4xx_dumptlb(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
276{
277	int i, zone, tlbsize;
278	u_int zpr, pid, opid, msr;
279	u_long tlblo, tlbhi, tlbmask;
280
281	zpr = mfspr(SPR_ZPR);
282	for (i = 0; i < NTLB; i++) {
283		asm volatile("mfmsr %3;"
284			"mfpid %4;"
285			"li %0,0;"
286			"mtmsr %0;"
287			"sync; isync;"
288			"tlbre %0,%5,1;"
289			"tlbre %1,%5,0;"
290			"mfpid %2;"
291			"mtpid %4;"
292			"mtmsr %3;"
293			"sync; isync"
294			: "=&r" (tlblo), "=&r" (tlbhi), "=r" (pid),
295			"=&r" (msr), "=&r" (opid) : "r" (i));
296
297		if (strchr(modif, 'v') && !(tlbhi & TLB_VALID))
298			continue;
299
300		tlbsize = (tlbhi & TLB_SIZE_MASK) >> TLB_SIZE_SHFT;
301		/* map tlbsize 0 .. 7 to masks for 1kB .. 16MB */
302		tlbmask = ~(1 << (tlbsize * 2 + 10)) + 1;
303
304		if (have_addr && ((tlbhi & tlbmask) != (addr & tlbmask)))
305			continue;
306
307		zone = (tlblo & TLB_ZSEL_MASK) >> TLB_ZSEL_SHFT;
308		db_printf("tlb%c%2d", tlbhi & TLB_VALID ? ' ' : '*', i);
309		db_printf("  PID %3d EPN 0x%08lx %-5s",
310		    pid,
311		    tlbhi & tlbmask,
312		    tlbsizes[tlbsize]);
313		db_printf("  RPN 0x%08lx  ZONE %2d%c  %s %s %c%c%c%c%c %s",
314		    tlblo & tlbmask,
315		    zone,
316		    "NTTA"[(zpr >> ((15 - zone) * 2)) & 3],
317		    tlblo & TLB_EX ? "EX" : "  ",
318		    tlblo & TLB_WR ? "WR" : "  ",
319		    tlblo & TLB_W ? 'W' : ' ',
320		    tlblo & TLB_I ? 'I' : ' ',
321		    tlblo & TLB_M ? 'M' : ' ',
322		    tlblo & TLB_G ? 'G' : ' ',
323		    tlbhi & TLB_ENDIAN ? 'E' : ' ',
324		    tlbhi & TLB_U0 ? "U0" : "  ");
325		db_printf("\n");
326	}
327}
328
329#ifdef USERACC
330static void
331db_ppc4xx_useracc(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
332{
333	static paddr_t oldaddr = -1;
334	int instr = 0;
335	int data;
336	extern vaddr_t opc_disasm(vaddr_t loc, int);
337
338
339	if (!have_addr) {
340		addr = oldaddr;
341	}
342	if (addr == -1) {
343		db_printf("no address\n");
344		return;
345	}
346	addr &= ~0x3; /* align */
347	{
348		register char c, *cp = modif;
349		while ((c = *cp++) != 0)
350			if (c == 'i')
351				instr = 1;
352	}
353	while (count--) {
354		if (db_print_position() == 0) {
355			/* Always print the address. */
356			db_printf("%8.4lx:\t", addr);
357		}
358		oldaddr=addr;
359		copyin((void *)addr, &data, sizeof(data));
360		if (instr) {
361			opc_disasm(addr, data);
362		} else {
363			db_printf("%4.4x\n", data);
364		}
365		addr += 4;
366		db_end_line();
367	}
368
369}
370#endif
371
372#endif /* PPC_IBM4XX */
373
374void
375db_show_mdpcpu(struct pcpu *pc)
376{
377}
378