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