db_interface.c revision 1.31 1 /* $NetBSD: db_interface.c,v 1.31 2003/09/27 04:44:42 matt Exp $ */
2 /* $OpenBSD: db_interface.c,v 1.2 1996/12/28 06:21:50 rahnds Exp $ */
3
4 #include <sys/cdefs.h>
5 __KERNEL_RCSID(0, "$NetBSD: db_interface.c,v 1.31 2003/09/27 04:44:42 matt Exp $");
6
7 #define USERACC
8
9 #include "opt_ddb.h"
10 #include "opt_kgdb.h"
11 #include "opt_ppcarch.h"
12
13 #include <sys/param.h>
14 #include <sys/proc.h>
15 #include <sys/systm.h>
16
17 #include <dev/cons.h>
18
19 #include <machine/db_machdep.h>
20 #include <machine/frame.h>
21 #ifdef PPC_IBM4XX
22 #include <machine/tlb.h>
23 #include <powerpc/spr.h>
24 #include <uvm/uvm_extern.h>
25 #endif
26
27 #ifdef DDB
28 #include <ddb/db_sym.h>
29 #include <ddb/db_command.h>
30 #include <ddb/db_extern.h>
31 #include <ddb/db_access.h>
32 #include <ddb/db_lex.h>
33 #include <ddb/db_output.h>
34 #include <ddb/ddbvar.h>
35 #endif
36
37 #ifdef KGDB
38 #include <sys/kgdb.h>
39 #endif
40
41 #include <dev/ofw/openfirm.h>
42
43 int db_active = 0;
44
45 db_regs_t ddb_regs;
46
47 void ddb_trap(void); /* Call into trap_subr.S */
48 int ddb_trap_glue(struct trapframe *); /* Called from trap_subr.S */
49 #ifdef PPC_IBM4XX
50 static void db_ppc4xx_ctx(db_expr_t, int, db_expr_t, char *);
51 static void db_ppc4xx_pv(db_expr_t, int, db_expr_t, char *);
52 static void db_ppc4xx_reset(db_expr_t, int, db_expr_t, char *);
53 static void db_ppc4xx_tf(db_expr_t, int, db_expr_t, char *);
54 static void db_ppc4xx_dumptlb(db_expr_t, int, db_expr_t, char *);
55 static void db_ppc4xx_dcr(db_expr_t, int, db_expr_t, char *);
56 static db_expr_t db_ppc4xx_mfdcr(db_expr_t);
57 static void db_ppc4xx_mtdcr(db_expr_t, db_expr_t);
58 #ifdef USERACC
59 static void db_ppc4xx_useracc(db_expr_t, int, db_expr_t, char *);
60 #endif
61 #endif /* PPC_IBM4XX */
62
63 #ifdef DDB
64 void
65 cpu_Debugger(void)
66 {
67 ddb_trap();
68 }
69 #endif
70
71 int
72 ddb_trap_glue(struct trapframe *frame)
73 {
74 #ifdef PPC_IBM4XX
75 if ((frame->srr1 & PSL_PR) == 0)
76 return kdb_trap(frame->exc, frame);
77 #else /* PPC_OEA */
78 if ((frame->srr1 & PSL_PR) == 0 &&
79 (frame->exc == EXC_TRC || frame->exc == EXC_RUNMODETRC ||
80 (frame->exc == EXC_PGM && (frame->srr1 & 0x20000)) ||
81 frame->exc == EXC_BPT)) {
82 int type = frame->exc;
83 if (type == EXC_PGM && (frame->srr1 & 0x20000)) {
84 type = T_BREAKPOINT;
85 }
86 return kdb_trap(type, frame);
87 }
88 #endif
89 return 0;
90 }
91
92 int
93 kdb_trap(int type, void *v)
94 {
95 struct trapframe *frame = v;
96
97 #ifdef DDB
98 if (db_recover != 0 && (type != -1 && type != T_BREAKPOINT)) {
99 db_error("Faulted in DDB; continuing...\n");
100 /* NOTREACHED */
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_OEA
114 DDB_REGS->mq = frame->tf_xtra[TF_MQ];
115 #endif
116 #ifdef PPC_IBM4XX
117 DDB_REGS->dear = frame->dar;
118 DDB_REGS->esr = frame->tf_xtra[TF_ESR];
119 DDB_REGS->pid = frame->tf_xtra[TF_PID];
120 #endif
121
122 #ifdef DDB
123 db_active++;
124 cnpollc(1);
125 db_trap(type, 0);
126 cnpollc(0);
127 db_active--;
128 #elif defined(KGDB)
129 if (!kgdb_trap(type, DDB_REGS))
130 return 0;
131 #endif
132
133 /* KGDB isn't smart about advancing PC if we
134 * take a breakpoint trap after kgdb_active is set.
135 * Therefore, we help out here.
136 */
137 if (IS_BREAKPOINT_TRAP(type, 0)) {
138 int bkpt;
139 db_read_bytes(PC_REGS(DDB_REGS),BKPT_SIZE,(void *)&bkpt);
140 if (bkpt== BKPT_INST) {
141 PC_REGS(DDB_REGS) += BKPT_SIZE;
142 }
143 }
144
145 memcpy(frame->fixreg, DDB_REGS->r, 32 * sizeof(u_int32_t));
146 frame->srr0 = DDB_REGS->iar;
147 frame->srr1 = DDB_REGS->msr;
148 frame->lr = DDB_REGS->lr;
149 frame->ctr = DDB_REGS->ctr;
150 frame->cr = DDB_REGS->cr;
151 frame->xer = DDB_REGS->xer;
152 #ifdef PPC_OEA
153 frame->tf_xtra[TF_MQ] = DDB_REGS->mq;
154 #endif
155 #ifdef PPC_IBM4XX
156 frame->dar = DDB_REGS->dear;
157 frame->tf_xtra[TF_ESR] = DDB_REGS->esr;
158 frame->tf_xtra[TF_PID] = DDB_REGS->pid;
159 #endif
160
161 return 1;
162 }
163
164 #ifdef PPC_IBM4XX
165 db_addr_t
166 branch_taken(int inst, db_addr_t pc, db_regs_t *regs)
167 {
168
169 if ((inst & M_B ) == I_B || (inst & M_B ) == I_BL) {
170 db_expr_t off;
171 off = ((db_expr_t)((inst & 0x03fffffc) << 6)) >> 6;
172 return (((inst & 0x2) ? 0 : pc) + off);
173 }
174
175 if ((inst & M_BC) == I_BC || (inst & M_BC) == I_BCL) {
176 db_expr_t off;
177 off = ((db_expr_t)((inst & 0x0000fffc) << 16)) >> 16;
178 return (((inst & 0x2) ? 0 : pc) + off);
179 }
180
181 if ((inst & M_RTS) == I_RTS || (inst & M_RTS) == I_BLRL)
182 return (regs->lr);
183
184 if ((inst & M_BCTR) == I_BCTR || (inst & M_BCTR) == I_BCTRL)
185 return (regs->ctr);
186
187 db_printf("branch_taken: can't figure out branch target for 0x%x!\n",
188 inst);
189 return (0);
190 }
191
192 const struct db_command db_machine_command_table[] = {
193 { "ctx", db_ppc4xx_ctx, 0, 0 },
194 { "pv", db_ppc4xx_pv, 0, 0 },
195 { "reset", db_ppc4xx_reset, 0, 0 },
196 { "tf", db_ppc4xx_tf, 0, 0 },
197 { "tlb", db_ppc4xx_dumptlb, 0, 0 },
198 { "dcr", db_ppc4xx_dcr, CS_MORE|CS_SET_DOT, 0 },
199 #ifdef USERACC
200 { "user", db_ppc4xx_useracc, 0, 0 },
201 #endif
202 { NULL, }
203 };
204
205 static void
206 db_ppc4xx_ctx(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
207 {
208 struct proc *p;
209
210 /* XXX LOCKING XXX */
211 for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) {
212 if (p->p_stat) {
213 db_printf("process %p:", p);
214 db_printf("pid:%d pmap:%p ctx:%d %s\n",
215 p->p_pid, p->p_vmspace->vm_map.pmap,
216 p->p_vmspace->vm_map.pmap->pm_ctx,
217 p->p_comm);
218 }
219 }
220 return;
221 }
222
223 static void
224 db_ppc4xx_pv(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
225 {
226 struct pv_entry {
227 struct pv_entry *pv_next; /* Linked list of mappings */
228 vaddr_t pv_va; /* virtual address of mapping */
229 struct pmap *pv_pm;
230 };
231 struct pv_entry *pa_to_pv(paddr_t);
232 struct pv_entry *pv;
233
234 if (!have_addr) {
235 db_printf("pv: <pa>\n");
236 return;
237 }
238 pv = pa_to_pv(addr);
239 db_printf("pv at %p\n", pv);
240 while (pv && pv->pv_pm) {
241 db_printf("next %p va %p pmap %p\n", pv->pv_next,
242 (void *)pv->pv_va, pv->pv_pm);
243 pv = pv->pv_next;
244 }
245 }
246
247 static void
248 db_ppc4xx_reset(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
249 {
250 printf("Reseting...\n");
251 ppc4xx_reset();
252 }
253
254 static void
255 db_ppc4xx_tf(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
256 {
257 struct trapframe *f;
258
259
260 if (have_addr) {
261 f = (struct trapframe *)addr;
262
263 db_printf("r0-r3: \t%8.8lx %8.8lx %8.8lx %8.8lx\n",
264 f->fixreg[0], f->fixreg[1],
265 f->fixreg[2], f->fixreg[3]);
266 db_printf("r4-r7: \t%8.8lx %8.8lx %8.8lx %8.8lx\n",
267 f->fixreg[4], f->fixreg[5],
268 f->fixreg[6], f->fixreg[7]);
269 db_printf("r8-r11: \t%8.8lx %8.8lx %8.8lx %8.8lx\n",
270 f->fixreg[8], f->fixreg[9],
271 f->fixreg[10], f->fixreg[11]);
272 db_printf("r12-r15:\t%8.8lx %8.8lx %8.8lx %8.8lx\n",
273 f->fixreg[12], f->fixreg[13],
274 f->fixreg[14], f->fixreg[15]);
275 db_printf("r16-r19:\t%8.8lx %8.8lx %8.8lx %8.8lx\n",
276 f->fixreg[16], f->fixreg[17],
277 f->fixreg[18], f->fixreg[19]);
278 db_printf("r20-r23:\t%8.8lx %8.8lx %8.8lx %8.8lx\n",
279 f->fixreg[20], f->fixreg[21],
280 f->fixreg[22], f->fixreg[23]);
281 db_printf("r24-r27:\t%8.8lx %8.8lx %8.8lx %8.8lx\n",
282 f->fixreg[24], f->fixreg[25],
283 f->fixreg[26], f->fixreg[27]);
284 db_printf("r28-r31:\t%8.8lx %8.8lx %8.8lx %8.8lx\n",
285 f->fixreg[28], f->fixreg[29],
286 f->fixreg[30], f->fixreg[31]);
287
288 db_printf("lr: %8.8lx cr: %8.8x xer: %8.8x ctr: %8.8lx\n",
289 f->lr, f->cr, f->xer, f->ctr);
290 db_printf("srr0(pc): %8.8lx srr1(msr): %8.8lx "
291 "dear: %8.8lx esr: %8.8x\n",
292 f->srr0, f->srr1, f->dar, f->tf_xtra[TF_ESR]);
293 db_printf("exc: %8.8x pid: %8.8x\n",
294 f->exc, f->tf_xtra[TF_PID]);
295 }
296 return;
297 }
298
299 static const char *const tlbsizes[] = {
300 "1kB",
301 "4kB",
302 "16kB",
303 "64kB",
304 "256kB",
305 "1MB",
306 "4MB",
307 "16MB"
308 };
309
310 static void
311 db_ppc4xx_dumptlb(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
312 {
313 int i, zone, tlbsize;
314 u_int zpr, pid, opid, msr;
315 u_long tlblo, tlbhi, tlbmask;
316
317 zpr = mfspr(SPR_ZPR);
318 for (i = 0; i < NTLB; i++) {
319 asm volatile("mfmsr %3;"
320 "mfpid %4;"
321 "li %0,0;"
322 "mtmsr %0;"
323 "sync; isync;"
324 "tlbrelo %0,%5;"
325 "tlbrehi %1,%5;"
326 "mfpid %2;"
327 "mtpid %4;"
328 "mtmsr %3;"
329 "sync; isync"
330 : "=&r" (tlblo), "=&r" (tlbhi), "=r" (pid),
331 "=&r" (msr), "=&r" (opid) : "r" (i));
332
333 if (strchr(modif, 'v') && !(tlbhi & TLB_VALID))
334 continue;
335
336 tlbsize = (tlbhi & TLB_SIZE_MASK) >> TLB_SIZE_SHFT;
337 /* map tlbsize 0 .. 7 to masks for 1kB .. 16MB */
338 tlbmask = ~(1 << (tlbsize * 2 + 10)) + 1;
339
340 if (have_addr && ((tlbhi & tlbmask) != (addr & tlbmask)))
341 continue;
342
343 zone = (tlblo & TLB_ZSEL_MASK) >> TLB_ZSEL_SHFT;
344 db_printf("tlb%c%2d", tlbhi & TLB_VALID ? ' ' : '*', i);
345 db_printf(" PID %3d EPN 0x%08lx %-5s",
346 pid,
347 tlbhi & tlbmask,
348 tlbsizes[tlbsize]);
349 db_printf(" RPN 0x%08lx ZONE %2d%c %s %s %c%c%c%c%c %s",
350 tlblo & tlbmask,
351 zone,
352 "NTTA"[(zpr >> ((15 - zone) * 2)) & 3],
353 tlblo & TLB_EX ? "EX" : " ",
354 tlblo & TLB_WR ? "WR" : " ",
355 tlblo & TLB_W ? 'W' : ' ',
356 tlblo & TLB_I ? 'I' : ' ',
357 tlblo & TLB_M ? 'M' : ' ',
358 tlblo & TLB_G ? 'G' : ' ',
359 tlbhi & TLB_ENDIAN ? 'E' : ' ',
360 tlbhi & TLB_U0 ? "U0" : " ");
361 db_printf("\n");
362 }
363 }
364
365 static void
366 db_ppc4xx_dcr(db_expr_t address, int have_addr, db_expr_t count, char *modif)
367 {
368 db_expr_t new_value;
369 db_expr_t addr;
370
371 if (address < 0 || address > 0x3ff)
372 db_error("Invalid DCR address (Valid range is 0x0 - 0x3ff)\n");
373
374 addr = address;
375
376 while (db_expression(&new_value)) {
377 db_printf("dcr 0x%lx\t\t%s = ", addr,
378 db_num_to_str(db_ppc4xx_mfdcr(addr)));
379 db_ppc4xx_mtdcr(addr, new_value);
380 db_printf("%s\n", db_num_to_str(db_ppc4xx_mfdcr(addr)));
381 addr += 1;
382 }
383
384 if (addr == address) {
385 db_next = (db_addr_t)addr + 1;
386 db_prev = (db_addr_t)addr;
387 db_printf("dcr 0x%lx\t\t%s\n", addr,
388 db_num_to_str(db_ppc4xx_mfdcr(addr)));
389 } else {
390 db_next = (db_addr_t)addr;
391 db_prev = (db_addr_t)addr - 1;
392 }
393
394 db_skip_to_eol();
395 }
396
397 /*
398 * XXX Grossness Alert! XXX
399 *
400 * Please look away now if you don't like self-modifying code
401 */
402 static u_int32_t db_ppc4xx_dcrfunc[4];
403
404 static db_expr_t
405 db_ppc4xx_mfdcr(db_expr_t reg)
406 {
407 db_expr_t (*func)(void);
408
409 reg = (((reg & 0x1f) << 5) | ((reg >> 5) & 0x1f)) << 11;
410 db_ppc4xx_dcrfunc[0] = 0x7c0004ac; /* sync */
411 db_ppc4xx_dcrfunc[1] = 0x4c00012c; /* isync */
412 db_ppc4xx_dcrfunc[2] = 0x7c600286 | reg; /* mfdcr reg, r3 */
413 db_ppc4xx_dcrfunc[3] = 0x4e800020; /* blr */
414
415 __syncicache((void *)db_ppc4xx_dcrfunc, sizeof(db_ppc4xx_dcrfunc));
416 func = (db_expr_t (*)(void))(void *)db_ppc4xx_dcrfunc;
417
418 return ((*func)());
419 }
420
421 static void
422 db_ppc4xx_mtdcr(db_expr_t reg, db_expr_t val)
423 {
424 db_expr_t (*func)(db_expr_t);
425
426 reg = (((reg & 0x1f) << 5) | ((reg >> 5) & 0x1f)) << 11;
427 db_ppc4xx_dcrfunc[0] = 0x7c0004ac; /* sync */
428 db_ppc4xx_dcrfunc[1] = 0x4c00012c; /* isync */
429 db_ppc4xx_dcrfunc[2] = 0x7c600386 | reg; /* mtdcr r3, reg */
430 db_ppc4xx_dcrfunc[3] = 0x4e800020; /* blr */
431
432 __syncicache((void *)db_ppc4xx_dcrfunc, sizeof(db_ppc4xx_dcrfunc));
433 func = (db_expr_t (*)(db_expr_t))(void *)db_ppc4xx_dcrfunc;
434
435 (*func)(val);
436 }
437
438 #ifdef USERACC
439 static void
440 db_ppc4xx_useracc(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
441 {
442 static paddr_t oldaddr = -1;
443 int instr = 0;
444 int data;
445 extern vaddr_t opc_disasm(vaddr_t loc, int);
446
447
448 if (!have_addr) {
449 addr = oldaddr;
450 }
451 if (addr == -1) {
452 db_printf("no address\n");
453 return;
454 }
455 addr &= ~0x3; /* align */
456 {
457 register char c, *cp = modif;
458 while ((c = *cp++) != 0)
459 if (c == 'i')
460 instr = 1;
461 }
462 while (count--) {
463 if (db_print_position() == 0) {
464 /* Always print the address. */
465 db_printf("%8.4lx:\t", addr);
466 }
467 oldaddr=addr;
468 copyin((void *)addr, &data, sizeof(data));
469 if (instr) {
470 opc_disasm(addr, data);
471 } else {
472 db_printf("%4.4x\n", data);
473 }
474 addr += 4;
475 db_end_line();
476 }
477
478 }
479 #endif
480
481 #endif /* PPC_IBM4XX */
482