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