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