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