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