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