db_interface.c revision 1.39.42.1 1 /* $NetBSD: db_interface.c,v 1.39.42.1 2011/01/07 02:01:21 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.39.42.1 2011/01/07 02:01:21 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 #include <powerpc/spr.h>
22 #include <powerpc/cpu.h>
23 #include <powerpc/bat.h>
24 #include <powerpc/pte.h>
25
26 #if defined (PPC_OEA) || defined(PPC_OEA64) || defined (PPC_OEA64_BRIDGE)
27 #include <powerpc/oea/spr.h>
28 #endif
29
30 #ifdef PPC_IBM4XX
31 #include <powerpc/ibm4xx/spr.h>
32 #include <machine/tlb.h>
33 #include <uvm/uvm_extern.h>
34 #endif
35
36 #ifdef PPC_BOOKE
37 #include <powerpc/booke/cpuvar.h>
38 #include <powerpc/booke/spr.h>
39 #endif
40
41 #ifdef DDB
42 #include <ddb/db_sym.h>
43 #include <ddb/db_command.h>
44 #include <ddb/db_extern.h>
45 #include <ddb/db_access.h>
46 #include <ddb/db_lex.h>
47 #include <ddb/db_output.h>
48 #include <ddb/ddbvar.h>
49 #endif
50
51 #ifdef KGDB
52 #include <sys/kgdb.h>
53 #define db_printf printf
54 #endif
55
56 #include <dev/ofw/openfirm.h>
57
58 int db_active = 0;
59
60 db_regs_t ddb_regs;
61
62 void ddb_trap(void); /* Call into trap_subr.S */
63 int ddb_trap_glue(struct trapframe *); /* Called from trap_subr.S */
64 static void db_ppc_msr(db_expr_t, bool, db_expr_t, const char *);
65 #if defined (PPC_OEA) || defined(PPC_OEA64) || defined (PPC_OEA64_BRIDGE)
66 static void db_show_bat(db_expr_t, bool, db_expr_t, const char *);
67 static void db_show_mmu(db_expr_t, bool, db_expr_t, const char *);
68 #endif /* PPC_OEA || PPC_OEA64 || PPC_OEA64_BRIDGE */
69 #ifdef PPC_IBM4XX
70 static void db_ppc4xx_ctx(db_expr_t, bool, db_expr_t, const char *);
71 static void db_ppc4xx_pv(db_expr_t, bool, db_expr_t, const char *);
72 static void db_ppc4xx_reset(db_expr_t, bool, db_expr_t, const char *);
73 static void db_ppc4xx_tf(db_expr_t, bool, db_expr_t, const char *);
74 static void db_ppc4xx_dumptlb(db_expr_t, bool, db_expr_t, const char *);
75 static void db_ppc4xx_dcr(db_expr_t, bool, db_expr_t, const char *);
76 static db_expr_t db_ppc4xx_mfdcr(db_expr_t);
77 static void db_ppc4xx_mtdcr(db_expr_t, db_expr_t);
78 #ifdef USERACC
79 static void db_ppc4xx_useracc(db_expr_t, bool, db_expr_t, const char *);
80 #endif
81 #endif /* PPC_IBM4XX */
82
83 #ifdef PPC_BOOKE
84 static void db_ppcbooke_reset(db_expr_t, bool, db_expr_t, const char *);
85 static void db_ppcbooke_tf(db_expr_t, bool, db_expr_t, const char *);
86 static void db_ppcbooke_dumptlb(db_expr_t, bool, db_expr_t, const char *);
87 #endif
88
89 #ifdef DDB
90 const struct db_command db_machine_command_table[] = {
91 { DDB_ADD_CMD("msr", db_ppc_msr, 0, NULL,NULL,NULL) },
92 #if defined (PPC_OEA) || defined(PPC_OEA64) || defined (PPC_OEA64_BRIDGE)
93 { DDB_ADD_CMD("bat", db_show_bat, 0,
94 "Print BAT register translations", NULL,NULL) },
95 { DDB_ADD_CMD("mmu", db_show_mmu, 0,
96 "Print MMU registers", NULL,NULL) },
97 #endif /* PPC_OEA || PPC_OEA64 || PPC_OEA64_BRIDGE */
98 #ifdef PPC_IBM4XX
99 { DDB_ADD_CMD("ctx", db_ppc4xx_ctx, 0, NULL,NULL,NULL) },
100 { DDB_ADD_CMD("pv", db_ppc4xx_pv, 0, NULL,NULL,NULL) },
101 { DDB_ADD_CMD("reset", db_ppc4xx_reset, 0, NULL,NULL,NULL) },
102 { DDB_ADD_CMD("tf", db_ppc4xx_tf, 0, NULL,NULL,NULL) },
103 { DDB_ADD_CMD("tlb", db_ppc4xx_dumptlb, 0, NULL,NULL,NULL) },
104 { DDB_ADD_CMD("dcr", db_ppc4xx_dcr, CS_MORE|CS_SET_DOT, NULL,NULL,NULL) },
105 #ifdef USERACC
106 { DDB_ADD_CMD("user", db_ppc4xx_useracc, 0, NULL,NULL,NULL) },
107 #endif
108 #endif /* PPC_IBM4XX */
109 #ifdef PPC_BOOKE
110 { DDB_ADD_CMD("reset", db_ppcbooke_reset, 0,
111 "Reset the system ", NULL,NULL) },
112 { DDB_ADD_CMD("tf", db_ppcbooke_tf, 0,
113 "Display the contents of the trapframe",
114 "address",
115 " address:\tthe struct trapframe to print") },
116 { DDB_ADD_CMD("tlb", db_ppcbooke_dumptlb, 0,
117 "Display instruction translation storage buffer information.",
118 NULL,NULL) },
119 #endif /* PPC_BOOKE */
120 { DDB_ADD_CMD(NULL, NULL, 0, NULL,NULL,NULL) }
121 };
122
123 void
124 cpu_Debugger(void)
125 {
126 #ifdef PPC_BOOKE
127 const register_t msr = mfmsr();
128 __asm volatile("wrteei 0\n\ttweq\t1,1");
129 mtmsr(msr);
130 __asm volatile("isync");
131 #else
132 ddb_trap();
133 #endif
134 }
135 #endif /* DDB */
136
137 int
138 ddb_trap_glue(struct trapframe *tf)
139 {
140 #if defined(PPC_IBM4XX) || defined(PPC_BOOKE)
141 if ((tf->tf_srr1 & PSL_PR) == 0)
142 return kdb_trap(tf->tf_exc, tf);
143 #else /* PPC_OEA */
144 if ((tf->tf_srr1 & PSL_PR) == 0 &&
145 (tf->tf_exc == EXC_TRC ||
146 tf->tf_exc == EXC_RUNMODETRC ||
147 (tf->tf_exc == EXC_PGM && (tf->tf_srr1 & 0x20000)) ||
148 tf->tf_exc == EXC_BPT ||
149 tf->tf_exc == EXC_DSI)) {
150 int type = tf->tf_exc;
151 if (type == EXC_PGM && (tf->tf_srr1 & 0x20000)) {
152 type = T_BREAKPOINT;
153 }
154 return kdb_trap(type, tf);
155 }
156 #endif
157 return 0;
158 }
159
160 int
161 kdb_trap(int type, void *v)
162 {
163 struct trapframe *tf = v;
164
165 #ifdef DDB
166 if (db_recover != 0 && (type != -1 && type != T_BREAKPOINT)) {
167 db_error("Faulted in DDB; continuing...\n");
168 /* NOTREACHED */
169 }
170 #endif
171
172 /* XXX Should switch to kdb's own stack here. */
173
174 memcpy(DDB_REGS->r, tf->tf_fixreg, 32 * sizeof(u_int32_t));
175 DDB_REGS->iar = tf->tf_srr0;
176 DDB_REGS->msr = tf->tf_srr1;
177 DDB_REGS->lr = tf->tf_lr;
178 DDB_REGS->ctr = tf->tf_ctr;
179 DDB_REGS->cr = tf->tf_cr;
180 DDB_REGS->xer = tf->tf_xer;
181 #ifdef PPC_OEA
182 DDB_REGS->mq = tf->tf_mq;
183 #elif defined(PPC_IBM4XX) || defined(PPC_BOOKE)
184 DDB_REGS->dear = tf->tf_dear;
185 DDB_REGS->esr = tf->tf_esr;
186 DDB_REGS->pid = tf->tf_pid;
187 #endif
188
189 #ifdef DDB
190 db_active++;
191 cnpollc(1);
192 db_trap(type, 0);
193 cnpollc(0);
194 db_active--;
195 #elif defined(KGDB)
196 if (!kgdb_trap(type, DDB_REGS))
197 return 0;
198 #endif
199
200 /* KGDB isn't smart about advancing PC if we
201 * take a breakpoint trap after kgdb_active is set.
202 * Therefore, we help out here.
203 */
204 if (IS_BREAKPOINT_TRAP(type, 0)) {
205 int bkpt;
206 db_read_bytes(PC_REGS(DDB_REGS),BKPT_SIZE,(void *)&bkpt);
207 if (bkpt== BKPT_INST) {
208 PC_REGS(DDB_REGS) += BKPT_SIZE;
209 }
210 }
211
212 memcpy(tf->tf_fixreg, DDB_REGS->r, 32 * sizeof(u_int32_t));
213 tf->tf_srr0 = DDB_REGS->iar;
214 tf->tf_srr1 = DDB_REGS->msr;
215 tf->tf_lr = DDB_REGS->lr;
216 tf->tf_ctr = DDB_REGS->ctr;
217 tf->tf_cr = DDB_REGS->cr;
218 tf->tf_xer = DDB_REGS->xer;
219 #ifdef PPC_OEA
220 tf->tf_mq = DDB_REGS->mq;
221 #endif
222 #if defined(PPC_IBM4XX) || defined(PPC_BOOKE)
223 tf->tf_dear = DDB_REGS->dear;
224 tf->tf_esr = DDB_REGS->esr;
225 tf->tf_pid = DDB_REGS->pid;
226 #endif
227
228 return 1;
229 }
230
231 #if defined (PPC_OEA) || defined(PPC_OEA64) || defined (PPC_OEA64_BRIDGE)
232 static void
233 print_battranslation(struct bat *bat, unsigned int blidx)
234 {
235 static const char *const batsizes[] = {
236 "128kB",
237 "256kB",
238 "512kB",
239 "1MB",
240 "2MB",
241 "4MB",
242 "8MB",
243 "16MB",
244 "32MB",
245 "64MB",
246 "128MB",
247 "256MB"
248 };
249 vsize_t len;
250
251 len = (0x20000L << blidx) - 1;
252 db_printf("\t%08lx %08lx %5s: 0x%08lx..0x%08lx -> 0x%08lx physical\n",
253 bat->batu, bat->batl, batsizes[blidx], bat->batu & ~len,
254 (bat->batu & ~len) + len, bat->batl & ~len);
255 }
256
257 static void
258 print_batmodes(register_t super, register_t user, register_t pp)
259 {
260 static const char *const accessmodes[] = {
261 "none",
262 "ro soft",
263 "read/write",
264 "read only"
265 };
266
267 db_printf("\tvalid: %c%c access: %-10s memory:",
268 super ? 'S' : '-', user ? 'U' : '-', accessmodes[pp]);
269 }
270
271 static void
272 print_wimg(register_t wimg)
273 {
274 if (wimg & BAT_W)
275 db_printf(" wrthrough");
276 if (wimg & BAT_I)
277 db_printf(" nocache");
278 if (wimg & BAT_M)
279 db_printf(" coherent");
280 if (wimg & BAT_G)
281 db_printf(" guard");
282 }
283
284 static void
285 print_bat(struct bat *bat)
286 {
287 if ((bat->batu & BAT_V) == 0) {
288 db_printf("\tdisabled\n\n");
289 return;
290 }
291 print_battranslation(bat, 30 - __builtin_clz((bat->batu & BAT_BL)|2));
292 print_batmodes(bat->batu & BAT_Vs, bat->batu & BAT_Vu,
293 bat->batl & BAT_PP);
294 print_wimg(bat->batl & BAT_WIMG);
295 db_printf("\n");
296 }
297
298 #ifdef PPC_OEA601
299 static void
300 print_bat601(struct bat *bat)
301 {
302 if ((bat->batl & BAT601_V) == 0) {
303 db_printf("\tdisabled\n\n");
304 return;
305 }
306 print_battranslation(bat, 32 - __builtin_clz(bat->batl & BAT601_BSM));
307 print_batmodes(bat->batu & BAT601_Ks, bat->batu & BAT601_Ku,
308 bat->batu & BAT601_PP);
309 print_wimg(bat->batu & (BAT601_W | BAT601_I | BAT601_M));
310 db_printf("\n");
311 }
312 #endif
313
314 static void
315 db_show_bat(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
316 {
317 struct bat ibat[4];
318 struct bat dbat[4];
319 unsigned int cpuvers;
320 int i;
321
322 cpuvers = mfpvr() >> 16;
323
324 __asm volatile ("mfibatu %0,0" : "=r"(ibat[0].batu));
325 __asm volatile ("mfibatl %0,0" : "=r"(ibat[0].batl));
326 __asm volatile ("mfibatu %0,1" : "=r"(ibat[1].batu));
327 __asm volatile ("mfibatl %0,1" : "=r"(ibat[1].batl));
328 __asm volatile ("mfibatu %0,2" : "=r"(ibat[2].batu));
329 __asm volatile ("mfibatl %0,2" : "=r"(ibat[2].batl));
330 __asm volatile ("mfibatu %0,3" : "=r"(ibat[3].batu));
331 __asm volatile ("mfibatl %0,3" : "=r"(ibat[3].batl));
332
333 if (cpuvers != MPC601) {
334 /* The 601 has only four unified BATs */
335 __asm volatile ("mfdbatu %0,0" : "=r"(dbat[0].batu));
336 __asm volatile ("mfdbatl %0,0" : "=r"(dbat[0].batl));
337 __asm volatile ("mfdbatu %0,1" : "=r"(dbat[1].batu));
338 __asm volatile ("mfdbatl %0,1" : "=r"(dbat[1].batl));
339 __asm volatile ("mfdbatu %0,2" : "=r"(dbat[2].batu));
340 __asm volatile ("mfdbatl %0,2" : "=r"(dbat[2].batl));
341 __asm volatile ("mfdbatu %0,3" : "=r"(dbat[3].batu));
342 __asm volatile ("mfdbatl %0,3" : "=r"(dbat[3].batl));
343 }
344
345 for (i = 0; i < 4; i++) {
346 #ifdef PPC_OEA601
347 if (cpuvers == MPC601) {
348 db_printf("bat%d:", i);
349 print_bat601(&ibat[i]);
350 } else
351 #endif
352 {
353 db_printf("ibat%d:", i);
354 print_bat(&ibat[i]);
355 }
356 }
357 if (cpuvers != MPC601) {
358 for (i = 0; i < 4; i++) {
359 db_printf("dbat%d:", i);
360 print_bat(&dbat[i]);
361 }
362 }
363 }
364
365 static void
366 db_show_mmu(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
367 {
368 paddr_t sdr1;
369 #if !defined(PPC_OEA64) && !defined(PPC_OEA64_BRIDGE)
370 register_t sr;
371 vaddr_t saddr;
372 int i;
373 #endif
374
375 __asm volatile ("mfsdr1 %0" : "=r"(sdr1));
376 db_printf("sdr1\t\t0x%08lx\n", sdr1);
377
378 #if defined(PPC_OEA64) || defined(PPC_OEA64_BRIDGE)
379 __asm volatile ("mfasr %0" : "=r"(sdr1));
380 db_printf("asr\t\t0x%08lx\n", sdr1);
381 #else
382 saddr = 0;
383 for (i = 0; i<= 0xf; i++) {
384 if ((i & 3) == 0)
385 db_printf("sr%d-%d\t\t", i, i+3);
386 __asm volatile ("mfsrin %0,%1" : "=r"(sr) : "r"(saddr));
387 db_printf("0x%08lx %c", sr, (i&3) == 3 ? '\n' : ' ');
388 saddr += 1 << ADDR_SR_SHFT;
389 }
390 #endif
391 }
392 #endif /* PPC_OEA || PPC_OEA64 || PPC_OEA64_BRIDGE */
393
394 #if defined(PPC_IBM4XX) || defined(PPC_BOOKE)
395 db_addr_t
396 branch_taken(int inst, db_addr_t pc, db_regs_t *regs)
397 {
398
399 if ((inst & M_B ) == I_B || (inst & M_B ) == I_BL) {
400 db_expr_t off;
401 off = ((db_expr_t)((inst & 0x03fffffc) << 6)) >> 6;
402 return (((inst & 0x2) ? 0 : pc) + off);
403 }
404
405 if ((inst & M_BC) == I_BC || (inst & M_BC) == I_BCL) {
406 db_expr_t off;
407 off = ((db_expr_t)((inst & 0x0000fffc) << 16)) >> 16;
408 return (((inst & 0x2) ? 0 : pc) + off);
409 }
410
411 if ((inst & M_RTS) == I_RTS || (inst & M_RTS) == I_BLRL)
412 return (regs->lr);
413
414 if ((inst & M_BCTR) == I_BCTR || (inst & M_BCTR) == I_BCTRL)
415 return (regs->ctr);
416
417 db_printf("branch_taken: can't figure out branch target for 0x%x!\n",
418 inst);
419 return (0);
420 }
421 #endif /* PPC_IBM4XX || PPC_BOOKE */
422
423
424 #ifdef PPC_IBM4XX
425 #ifdef DDB
426 static void
427 db_ppc4xx_ctx(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
428 {
429 struct proc *p;
430
431 /* XXX LOCKING XXX */
432 for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) {
433 if (p->p_stat) {
434 db_printf("process %p:", p);
435 db_printf("pid:%d pmap:%p ctx:%d %s\n",
436 p->p_pid, p->p_vmspace->vm_map.pmap,
437 p->p_vmspace->vm_map.pmap->pm_ctx,
438 p->p_comm);
439 }
440 }
441 return;
442 }
443
444 static void
445 db_ppc4xx_pv(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
446 {
447 struct pv_entry {
448 struct pv_entry *pv_next; /* Linked list of mappings */
449 vaddr_t pv_va; /* virtual address of mapping */
450 struct pmap *pv_pm;
451 };
452 struct pv_entry *pa_to_pv(paddr_t);
453 struct pv_entry *pv;
454
455 if (!have_addr) {
456 db_printf("pv: <pa>\n");
457 return;
458 }
459 pv = pa_to_pv(addr);
460 db_printf("pv at %p\n", pv);
461 while (pv && pv->pv_pm) {
462 db_printf("next %p va %p pmap %p\n", pv->pv_next,
463 (void *)pv->pv_va, pv->pv_pm);
464 pv = pv->pv_next;
465 }
466 }
467
468 static void
469 db_ppc4xx_reset(db_expr_t addr, bool have_addr, db_expr_t count,
470 const char *modif)
471 {
472 printf("Reseting...\n");
473 ppc4xx_reset();
474 }
475
476 static void
477 db_ppc4xx_tf(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
478 {
479 struct trapframe *tf;
480
481
482 if (have_addr) {
483 tf = (struct trapframe *)addr;
484
485 db_printf("r0-r3: \t%8.8lx %8.8lx %8.8lx %8.8lx\n",
486 tf->tf_fixreg[0], tf->tf_fixreg[1],
487 tf->tf_fixreg[2], tf->tf_fixreg[3]);
488 db_printf("r4-r7: \t%8.8lx %8.8lx %8.8lx %8.8lx\n",
489 tf->tf_fixreg[4], tf->tf_fixreg[5],
490 tf->tf_fixreg[6], tf->tf_fixreg[7]);
491 db_printf("r8-r11: \t%8.8lx %8.8lx %8.8lx %8.8lx\n",
492 tf->tf_fixreg[8], tf->tf_fixreg[9],
493 tf->tf_fixreg[10], tf->tf_fixreg[11]);
494 db_printf("r12-r15:\t%8.8lx %8.8lx %8.8lx %8.8lx\n",
495 tf->tf_fixreg[12], tf->tf_fixreg[13],
496 tf->tf_fixreg[14], tf->tf_fixreg[15]);
497 db_printf("r16-r19:\t%8.8lx %8.8lx %8.8lx %8.8lx\n",
498 tf->tf_fixreg[16], tf->tf_fixreg[17],
499 tf->tf_fixreg[18], tf->tf_fixreg[19]);
500 db_printf("r20-r23:\t%8.8lx %8.8lx %8.8lx %8.8lx\n",
501 tf->tf_fixreg[20], tf->tf_fixreg[21],
502 tf->tf_fixreg[22], tf->tf_fixreg[23]);
503 db_printf("r24-r27:\t%8.8lx %8.8lx %8.8lx %8.8lx\n",
504 tf->tf_fixreg[24], tf->tf_fixreg[25],
505 tf->tf_fixreg[26], tf->tf_fixreg[27]);
506 db_printf("r28-r31:\t%8.8lx %8.8lx %8.8lx %8.8lx\n",
507 tf->tf_fixreg[28], tf->tf_fixreg[29],
508 tf->tf_fixreg[30], tf->tf_fixreg[31]);
509
510 db_printf("lr: %8.8lx cr: %8.8x xer: %8.8x ctr: %8.8lx\n",
511 tf->tf_lr, tf->tf_cr, tf->tf_xer, tf->tf_ctr);
512 db_printf("srr0(pc): %8.8lx srr1(msr): %8.8lx "
513 "dear: %8.8lx esr: %8.8x\n",
514 tf->tf_srr0, tf->tf_srr1, tf->tf_dear, tf->tf_esr);
515 db_printf("exc: %8.8x pid: %8.8x\n",
516 tf->tf_exc, tf->tf_pid);
517 }
518 return;
519 }
520
521 static const char *const tlbsizes[] = {
522 "1kB",
523 "4kB",
524 "16kB",
525 "64kB",
526 "256kB",
527 "1MB",
528 "4MB",
529 "16MB"
530 };
531
532 static void
533 db_ppc4xx_dumptlb(db_expr_t addr, bool have_addr, db_expr_t count,
534 const char *modif)
535 {
536 int i, zone, tlbsize;
537 u_int zpr, pid, opid, msr;
538 u_long tlblo, tlbhi, tlbmask;
539
540 zpr = mfspr(SPR_ZPR);
541 for (i = 0; i < NTLB; i++) {
542 __asm volatile("mfmsr %3;"
543 "mfpid %4;"
544 "li %0,0;"
545 "mtmsr %0;"
546 "sync; isync;"
547 "tlbrelo %0,%5;"
548 "tlbrehi %1,%5;"
549 "mfpid %2;"
550 "mtpid %4;"
551 "mtmsr %3;"
552 "sync; isync"
553 : "=&r" (tlblo), "=&r" (tlbhi), "=r" (pid),
554 "=&r" (msr), "=&r" (opid) : "r" (i));
555
556 if (strchr(modif, 'v') && !(tlbhi & TLB_VALID))
557 continue;
558
559 tlbsize = (tlbhi & TLB_SIZE_MASK) >> TLB_SIZE_SHFT;
560 /* map tlbsize 0 .. 7 to masks for 1kB .. 16MB */
561 tlbmask = ~(1 << (tlbsize * 2 + 10)) + 1;
562
563 if (have_addr && ((tlbhi & tlbmask) != (addr & tlbmask)))
564 continue;
565
566 zone = (tlblo & TLB_ZSEL_MASK) >> TLB_ZSEL_SHFT;
567 db_printf("tlb%c%2d", tlbhi & TLB_VALID ? ' ' : '*', i);
568 db_printf(" PID %3d EPN 0x%08lx %-5s",
569 pid,
570 tlbhi & tlbmask,
571 tlbsizes[tlbsize]);
572 db_printf(" RPN 0x%08lx ZONE %2d%c %s %s %c%c%c%c%c %s",
573 tlblo & tlbmask,
574 zone,
575 "NTTA"[(zpr >> ((15 - zone) * 2)) & 3],
576 tlblo & TLB_EX ? "EX" : " ",
577 tlblo & TLB_WR ? "WR" : " ",
578 tlblo & TLB_W ? 'W' : ' ',
579 tlblo & TLB_I ? 'I' : ' ',
580 tlblo & TLB_M ? 'M' : ' ',
581 tlblo & TLB_G ? 'G' : ' ',
582 tlbhi & TLB_ENDIAN ? 'E' : ' ',
583 tlbhi & TLB_U0 ? "U0" : " ");
584 db_printf("\n");
585 }
586 }
587
588 static void
589 db_ppc4xx_dcr(db_expr_t address, bool have_addr, db_expr_t count,
590 const char *modif)
591 {
592 db_expr_t new_value;
593 db_expr_t addr;
594
595 if (address < 0 || address > 0x3ff)
596 db_error("Invalid DCR address (Valid range is 0x0 - 0x3ff)\n");
597
598 addr = address;
599
600 while (db_expression(&new_value)) {
601 db_printf("dcr 0x%lx\t\t%s = ", addr,
602 db_num_to_str(db_ppc4xx_mfdcr(addr)));
603 db_ppc4xx_mtdcr(addr, new_value);
604 db_printf("%s\n", db_num_to_str(db_ppc4xx_mfdcr(addr)));
605 addr += 1;
606 }
607
608 if (addr == address) {
609 db_next = (db_addr_t)addr + 1;
610 db_prev = (db_addr_t)addr;
611 db_printf("dcr 0x%lx\t\t%s\n", addr,
612 db_num_to_str(db_ppc4xx_mfdcr(addr)));
613 } else {
614 db_next = (db_addr_t)addr;
615 db_prev = (db_addr_t)addr - 1;
616 }
617
618 db_skip_to_eol();
619 }
620
621 /*
622 * XXX Grossness Alert! XXX
623 *
624 * Please look away now if you don't like self-modifying code
625 */
626 static u_int32_t db_ppc4xx_dcrfunc[4];
627
628 static db_expr_t
629 db_ppc4xx_mfdcr(db_expr_t reg)
630 {
631 db_expr_t (*func)(void);
632
633 reg = (((reg & 0x1f) << 5) | ((reg >> 5) & 0x1f)) << 11;
634 db_ppc4xx_dcrfunc[0] = 0x7c0004ac; /* sync */
635 db_ppc4xx_dcrfunc[1] = 0x4c00012c; /* isync */
636 db_ppc4xx_dcrfunc[2] = 0x7c600286 | reg; /* mfdcr reg, r3 */
637 db_ppc4xx_dcrfunc[3] = 0x4e800020; /* blr */
638
639 __syncicache((void *)db_ppc4xx_dcrfunc, sizeof(db_ppc4xx_dcrfunc));
640 func = (db_expr_t (*)(void))(void *)db_ppc4xx_dcrfunc;
641
642 return ((*func)());
643 }
644
645 static void
646 db_ppc4xx_mtdcr(db_expr_t reg, db_expr_t val)
647 {
648 db_expr_t (*func)(db_expr_t);
649
650 reg = (((reg & 0x1f) << 5) | ((reg >> 5) & 0x1f)) << 11;
651 db_ppc4xx_dcrfunc[0] = 0x7c0004ac; /* sync */
652 db_ppc4xx_dcrfunc[1] = 0x4c00012c; /* isync */
653 db_ppc4xx_dcrfunc[2] = 0x7c600386 | reg; /* mtdcr r3, reg */
654 db_ppc4xx_dcrfunc[3] = 0x4e800020; /* blr */
655
656 __syncicache((void *)db_ppc4xx_dcrfunc, sizeof(db_ppc4xx_dcrfunc));
657 func = (db_expr_t (*)(db_expr_t))(void *)db_ppc4xx_dcrfunc;
658
659 (*func)(val);
660 }
661
662 #ifdef USERACC
663 static void
664 db_ppc4xx_useracc(db_expr_t addr, bool have_addr, db_expr_t count,
665 const char *modif)
666 {
667 static paddr_t oldaddr = -1;
668 int instr = 0;
669 int data;
670 extern vaddr_t opc_disasm(vaddr_t loc, int);
671
672
673 if (!have_addr) {
674 addr = oldaddr;
675 }
676 if (addr == -1) {
677 db_printf("no address\n");
678 return;
679 }
680 addr &= ~0x3; /* align */
681 {
682 const char *cp = modif;
683 char c;
684 while ((c = *cp++) != 0)
685 if (c == 'i')
686 instr = 1;
687 }
688 while (count--) {
689 if (db_print_position() == 0) {
690 /* Always print the address. */
691 db_printf("%8.4lx:\t", addr);
692 }
693 oldaddr=addr;
694 copyin((void *)addr, &data, sizeof(data));
695 if (instr) {
696 opc_disasm(addr, data);
697 } else {
698 db_printf("%4.4x\n", data);
699 }
700 addr += 4;
701 db_end_line();
702 }
703
704 }
705 #endif
706
707 #endif /* DDB */
708
709 #endif /* PPC_IBM4XX */
710
711 #ifdef PPC_BOOKE
712 static void
713 db_ppcbooke_reset(db_expr_t addr, bool have_addr, db_expr_t count,
714 const char *modif)
715 {
716 printf("Reseting...\n");
717 (*cpu_md_ops.md_cpu_reset)();
718 }
719
720 static void
721 db_ppcbooke_tf(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
722 {
723 if (!have_addr)
724 return;
725
726 const struct trapframe * const tf = (const struct trapframe *)addr;
727
728 db_printf("trapframe %p (exc=%x srr0/1=%#lx/%#lx esr/dear=%#x/%#lx)\n",
729 tf, tf->tf_exc, tf->tf_srr0, tf->tf_srr1, tf->tf_esr, tf->tf_dear);
730 db_printf("lr =%08lx ctr=%08lx cr =%08x xer=%08x\n",
731 tf->tf_lr, tf->tf_ctr, tf->tf_cr, tf->tf_xer);
732 for (u_int r = 0; r < 32; r += 4) {
733 db_printf("r%02u=%08lx r%02u=%08lx r%02u=%08lx r%02u=%08lx\n",
734 r+0, tf->tf_fixreg[r+0], r+1, tf->tf_fixreg[r+1],
735 r+2, tf->tf_fixreg[r+2], r+3, tf->tf_fixreg[r+3]);
736 }
737 }
738
739 static void
740 db_ppcbooke_dumptlb(db_expr_t addr, bool have_addr, db_expr_t count,
741 const char *modif)
742 {
743 tlb_dump(db_printf);
744 }
745 #endif /* PPC_BOOKE */
746
747 static void
748 db_ppc_msr(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
749 {
750 register_t msr;
751
752 __asm volatile ("mfmsr %0" : "=r"(msr));
753
754 db_printf("msr %#lx\n", msr);
755 }
756