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