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