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