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