db_interface.c revision 1.49 1 /* $NetBSD: db_interface.c,v 1.49 2012/02/01 05:25:58 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.49 2012/02/01 05:25:58 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_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 cpuvers = mfpvr() >> 16;
347
348 ibat[0].batu = mfspr(SPR_IBAT0U);
349 ibat[0].batl = mfspr(SPR_IBAT0L);
350 ibat[1].batu = mfspr(SPR_IBAT1U);
351 ibat[1].batl = mfspr(SPR_IBAT1L);
352 ibat[2].batu = mfspr(SPR_IBAT2U);
353 ibat[2].batl = mfspr(SPR_IBAT2L);
354 ibat[3].batu = mfspr(SPR_IBAT3U);
355 ibat[3].batl = mfspr(SPR_IBAT3L);
356 if (maxbat == 8) {
357 ibat[4].batu = mfspr(SPR_IBAT4U);
358 ibat[4].batl = mfspr(SPR_IBAT4L);
359 ibat[5].batu = mfspr(SPR_IBAT5U);
360 ibat[5].batl = mfspr(SPR_IBAT5L);
361 ibat[6].batu = mfspr(SPR_IBAT6U);
362 ibat[6].batl = mfspr(SPR_IBAT6L);
363 ibat[7].batu = mfspr(SPR_IBAT7U);
364 ibat[7].batl = mfspr(SPR_IBAT7L);
365 }
366
367 if (cpuvers != MPC601) {
368 /* The 601 has only four unified BATs */
369 dbat[0].batu = mfspr(SPR_DBAT0U);
370 dbat[0].batl = mfspr(SPR_DBAT0L);
371 dbat[1].batu = mfspr(SPR_DBAT1U);
372 dbat[1].batl = mfspr(SPR_DBAT1L);
373 dbat[2].batu = mfspr(SPR_DBAT2U);
374 dbat[2].batl = mfspr(SPR_DBAT2L);
375 dbat[3].batu = mfspr(SPR_DBAT3U);
376 dbat[3].batl = mfspr(SPR_DBAT3L);
377 if (maxbat == 8) {
378 dbat[4].batu = mfspr(SPR_DBAT4U);
379 dbat[4].batl = mfspr(SPR_DBAT4L);
380 dbat[5].batu = mfspr(SPR_DBAT5U);
381 dbat[5].batl = mfspr(SPR_DBAT5L);
382 dbat[6].batu = mfspr(SPR_DBAT6U);
383 dbat[6].batl = mfspr(SPR_DBAT6L);
384 dbat[7].batu = mfspr(SPR_DBAT7U);
385 dbat[7].batl = mfspr(SPR_DBAT7L);
386 }
387 }
388
389 for (i = 0; i < maxbat; i++) {
390 #ifdef PPC_OEA601
391 if (cpuvers == MPC601) {
392 db_printf("bat[%u]:\n", i);
393 print_bat601(&ibat[i]);
394 } else
395 #endif
396 {
397 db_printf("ibat[%u]:\n", i);
398 print_bat(&ibat[i]);
399 db_printf("dbat[%u]:\n", i);
400 print_bat(&dbat[i]);
401 }
402 }
403 }
404
405 static void
406 db_show_mmu(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
407 {
408 paddr_t sdr1;
409 #if !defined(PPC_OEA64) && !defined(PPC_OEA64_BRIDGE)
410 register_t sr;
411 vaddr_t saddr;
412 int i;
413 #endif
414
415 __asm volatile ("mfsdr1 %0" : "=r"(sdr1));
416 db_printf("sdr1\t\t0x%08lx\n", sdr1);
417
418 #if defined(PPC_OEA64) || defined(PPC_OEA64_BRIDGE)
419 __asm volatile ("mfasr %0" : "=r"(sdr1));
420 db_printf("asr\t\t0x%08lx\n", sdr1);
421 #else
422 saddr = 0;
423 for (i = 0; i<= 0xf; i++) {
424 if ((i & 3) == 0)
425 db_printf("sr%d-%d\t\t", i, i+3);
426 __asm volatile ("mfsrin %0,%1" : "=r"(sr) : "r"(saddr));
427 db_printf("0x%08lx %c", sr, (i&3) == 3 ? '\n' : ' ');
428 saddr += 1 << ADDR_SR_SHFT;
429 }
430 #endif
431 }
432 #endif /* PPC_OEA || PPC_OEA64 || PPC_OEA64_BRIDGE */
433
434 #if defined(PPC_IBM4XX) || defined(PPC_BOOKE)
435 db_addr_t
436 branch_taken(int inst, db_addr_t pc, db_regs_t *regs)
437 {
438
439 if ((inst & M_B ) == I_B || (inst & M_B ) == I_BL) {
440 db_expr_t off;
441 off = ((db_expr_t)((inst & 0x03fffffc) << 6)) >> 6;
442 return (((inst & 0x2) ? 0 : pc) + off);
443 }
444
445 if ((inst & M_BC) == I_BC || (inst & M_BC) == I_BCL) {
446 db_expr_t off;
447 off = ((db_expr_t)((inst & 0x0000fffc) << 16)) >> 16;
448 return (((inst & 0x2) ? 0 : pc) + off);
449 }
450
451 if ((inst & M_RTS) == I_RTS || (inst & M_RTS) == I_BLRL)
452 return (regs->lr);
453
454 if ((inst & M_BCTR) == I_BCTR || (inst & M_BCTR) == I_BCTRL)
455 return (regs->ctr);
456
457 db_printf("branch_taken: can't figure out branch target for 0x%x!\n",
458 inst);
459 return (0);
460 }
461 #endif /* PPC_IBM4XX || PPC_BOOKE */
462
463
464 #ifdef PPC_IBM4XX
465 #ifdef DDB
466 static void
467 db_ppc4xx_ctx(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
468 {
469 struct proc *p;
470
471 /* XXX LOCKING XXX */
472 for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) {
473 if (p->p_stat) {
474 db_printf("process %p:", p);
475 db_printf("pid:%d pmap:%p ctx:%d %s\n",
476 p->p_pid, p->p_vmspace->vm_map.pmap,
477 p->p_vmspace->vm_map.pmap->pm_ctx,
478 p->p_comm);
479 }
480 }
481 return;
482 }
483
484 static void
485 db_ppc4xx_pv(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
486 {
487 struct pv_entry {
488 struct pv_entry *pv_next; /* Linked list of mappings */
489 vaddr_t pv_va; /* virtual address of mapping */
490 struct pmap *pv_pm;
491 };
492 struct pv_entry *pa_to_pv(paddr_t);
493 struct pv_entry *pv;
494
495 if (!have_addr) {
496 db_printf("pv: <pa>\n");
497 return;
498 }
499 pv = pa_to_pv(addr);
500 db_printf("pv at %p\n", pv);
501 while (pv && pv->pv_pm) {
502 db_printf("next %p va %p pmap %p\n", pv->pv_next,
503 (void *)pv->pv_va, pv->pv_pm);
504 pv = pv->pv_next;
505 }
506 }
507
508 static void
509 db_ppc4xx_reset(db_expr_t addr, bool have_addr, db_expr_t count,
510 const char *modif)
511 {
512 printf("Reseting...\n");
513 ppc4xx_reset();
514 }
515
516 static void
517 db_ppc4xx_tf(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
518 {
519 struct trapframe *tf;
520
521
522 if (have_addr) {
523 tf = (struct trapframe *)addr;
524
525 db_printf("r0-r3: \t%8.8lx %8.8lx %8.8lx %8.8lx\n",
526 tf->tf_fixreg[0], tf->tf_fixreg[1],
527 tf->tf_fixreg[2], tf->tf_fixreg[3]);
528 db_printf("r4-r7: \t%8.8lx %8.8lx %8.8lx %8.8lx\n",
529 tf->tf_fixreg[4], tf->tf_fixreg[5],
530 tf->tf_fixreg[6], tf->tf_fixreg[7]);
531 db_printf("r8-r11: \t%8.8lx %8.8lx %8.8lx %8.8lx\n",
532 tf->tf_fixreg[8], tf->tf_fixreg[9],
533 tf->tf_fixreg[10], tf->tf_fixreg[11]);
534 db_printf("r12-r15:\t%8.8lx %8.8lx %8.8lx %8.8lx\n",
535 tf->tf_fixreg[12], tf->tf_fixreg[13],
536 tf->tf_fixreg[14], tf->tf_fixreg[15]);
537 db_printf("r16-r19:\t%8.8lx %8.8lx %8.8lx %8.8lx\n",
538 tf->tf_fixreg[16], tf->tf_fixreg[17],
539 tf->tf_fixreg[18], tf->tf_fixreg[19]);
540 db_printf("r20-r23:\t%8.8lx %8.8lx %8.8lx %8.8lx\n",
541 tf->tf_fixreg[20], tf->tf_fixreg[21],
542 tf->tf_fixreg[22], tf->tf_fixreg[23]);
543 db_printf("r24-r27:\t%8.8lx %8.8lx %8.8lx %8.8lx\n",
544 tf->tf_fixreg[24], tf->tf_fixreg[25],
545 tf->tf_fixreg[26], tf->tf_fixreg[27]);
546 db_printf("r28-r31:\t%8.8lx %8.8lx %8.8lx %8.8lx\n",
547 tf->tf_fixreg[28], tf->tf_fixreg[29],
548 tf->tf_fixreg[30], tf->tf_fixreg[31]);
549
550 db_printf("lr: %8.8lx cr: %8.8x xer: %8.8x ctr: %8.8lx\n",
551 tf->tf_lr, tf->tf_cr, tf->tf_xer, tf->tf_ctr);
552 db_printf("srr0(pc): %8.8lx srr1(msr): %8.8lx "
553 "dear: %8.8lx esr: %8.8x\n",
554 tf->tf_srr0, tf->tf_srr1, tf->tf_dear, tf->tf_esr);
555 db_printf("exc: %8.8x pid: %8.8x\n",
556 tf->tf_exc, tf->tf_pid);
557 }
558 return;
559 }
560
561 static const char *const tlbsizes[] = {
562 "1kB",
563 "4kB",
564 "16kB",
565 "64kB",
566 "256kB",
567 "1MB",
568 "4MB",
569 "16MB"
570 };
571
572 static void
573 db_ppc4xx_dumptlb(db_expr_t addr, bool have_addr, db_expr_t count,
574 const char *modif)
575 {
576 int i, zone, tlbsize;
577 u_int zpr, pid, opid, msr;
578 u_long tlblo, tlbhi, tlbmask;
579
580 zpr = mfspr(SPR_ZPR);
581 for (i = 0; i < NTLB; i++) {
582 __asm volatile("mfmsr %3;"
583 "mfpid %4;"
584 "li %0,0;"
585 "mtmsr %0;"
586 "sync; isync;"
587 "tlbrelo %0,%5;"
588 "tlbrehi %1,%5;"
589 "mfpid %2;"
590 "mtpid %4;"
591 "mtmsr %3;"
592 "sync; isync"
593 : "=&r" (tlblo), "=&r" (tlbhi), "=r" (pid),
594 "=&r" (msr), "=&r" (opid) : "r" (i));
595
596 if (strchr(modif, 'v') && !(tlbhi & TLB_VALID))
597 continue;
598
599 tlbsize = (tlbhi & TLB_SIZE_MASK) >> TLB_SIZE_SHFT;
600 /* map tlbsize 0 .. 7 to masks for 1kB .. 16MB */
601 tlbmask = ~(1 << (tlbsize * 2 + 10)) + 1;
602
603 if (have_addr && ((tlbhi & tlbmask) != (addr & tlbmask)))
604 continue;
605
606 zone = (tlblo & TLB_ZSEL_MASK) >> TLB_ZSEL_SHFT;
607 db_printf("tlb%c%2d", tlbhi & TLB_VALID ? ' ' : '*', i);
608 db_printf(" PID %3d EPN 0x%08lx %-5s",
609 pid,
610 tlbhi & tlbmask,
611 tlbsizes[tlbsize]);
612 db_printf(" RPN 0x%08lx ZONE %2d%c %s %s %c%c%c%c%c %s",
613 tlblo & tlbmask,
614 zone,
615 "NTTA"[(zpr >> ((15 - zone) * 2)) & 3],
616 tlblo & TLB_EX ? "EX" : " ",
617 tlblo & TLB_WR ? "WR" : " ",
618 tlblo & TLB_W ? 'W' : ' ',
619 tlblo & TLB_I ? 'I' : ' ',
620 tlblo & TLB_M ? 'M' : ' ',
621 tlblo & TLB_G ? 'G' : ' ',
622 tlbhi & TLB_ENDIAN ? 'E' : ' ',
623 tlbhi & TLB_U0 ? "U0" : " ");
624 db_printf("\n");
625 }
626 }
627
628 static void
629 db_ppc4xx_dcr(db_expr_t address, bool have_addr, db_expr_t count,
630 const char *modif)
631 {
632 db_expr_t new_value;
633 db_expr_t addr;
634
635 if (address < 0 || address > 0x3ff)
636 db_error("Invalid DCR address (Valid range is 0x0 - 0x3ff)\n");
637
638 addr = address;
639
640 while (db_expression(&new_value)) {
641 db_printf("dcr 0x%lx\t\t%s = ", addr,
642 db_num_to_str(db_ppc4xx_mfdcr(addr)));
643 db_ppc4xx_mtdcr(addr, new_value);
644 db_printf("%s\n", db_num_to_str(db_ppc4xx_mfdcr(addr)));
645 addr += 1;
646 }
647
648 if (addr == address) {
649 db_next = (db_addr_t)addr + 1;
650 db_prev = (db_addr_t)addr;
651 db_printf("dcr 0x%lx\t\t%s\n", addr,
652 db_num_to_str(db_ppc4xx_mfdcr(addr)));
653 } else {
654 db_next = (db_addr_t)addr;
655 db_prev = (db_addr_t)addr - 1;
656 }
657
658 db_skip_to_eol();
659 }
660
661 /*
662 * XXX Grossness Alert! XXX
663 *
664 * Please look away now if you don't like self-modifying code
665 */
666 static u_int32_t db_ppc4xx_dcrfunc[4];
667
668 static db_expr_t
669 db_ppc4xx_mfdcr(db_expr_t reg)
670 {
671 db_expr_t (*func)(void);
672
673 reg = (((reg & 0x1f) << 5) | ((reg >> 5) & 0x1f)) << 11;
674 db_ppc4xx_dcrfunc[0] = 0x7c0004ac; /* sync */
675 db_ppc4xx_dcrfunc[1] = 0x4c00012c; /* isync */
676 db_ppc4xx_dcrfunc[2] = 0x7c600286 | reg; /* mfdcr reg, r3 */
677 db_ppc4xx_dcrfunc[3] = 0x4e800020; /* blr */
678
679 __syncicache((void *)db_ppc4xx_dcrfunc, sizeof(db_ppc4xx_dcrfunc));
680 func = (db_expr_t (*)(void))(void *)db_ppc4xx_dcrfunc;
681
682 return ((*func)());
683 }
684
685 static void
686 db_ppc4xx_mtdcr(db_expr_t reg, db_expr_t val)
687 {
688 db_expr_t (*func)(db_expr_t);
689
690 reg = (((reg & 0x1f) << 5) | ((reg >> 5) & 0x1f)) << 11;
691 db_ppc4xx_dcrfunc[0] = 0x7c0004ac; /* sync */
692 db_ppc4xx_dcrfunc[1] = 0x4c00012c; /* isync */
693 db_ppc4xx_dcrfunc[2] = 0x7c600386 | reg; /* mtdcr r3, reg */
694 db_ppc4xx_dcrfunc[3] = 0x4e800020; /* blr */
695
696 __syncicache((void *)db_ppc4xx_dcrfunc, sizeof(db_ppc4xx_dcrfunc));
697 func = (db_expr_t (*)(db_expr_t))(void *)db_ppc4xx_dcrfunc;
698
699 (*func)(val);
700 }
701
702 #ifdef USERACC
703 static void
704 db_ppc4xx_useracc(db_expr_t addr, bool have_addr, db_expr_t count,
705 const char *modif)
706 {
707 static paddr_t oldaddr = -1;
708 int instr = 0;
709 int data;
710 extern vaddr_t opc_disasm(vaddr_t loc, int);
711
712
713 if (!have_addr) {
714 addr = oldaddr;
715 }
716 if (addr == -1) {
717 db_printf("no address\n");
718 return;
719 }
720 addr &= ~0x3; /* align */
721 {
722 const char *cp = modif;
723 char c;
724 while ((c = *cp++) != 0)
725 if (c == 'i')
726 instr = 1;
727 }
728 while (count--) {
729 if (db_print_position() == 0) {
730 /* Always print the address. */
731 db_printf("%8.4lx:\t", addr);
732 }
733 oldaddr=addr;
734 copyin((void *)addr, &data, sizeof(data));
735 if (instr) {
736 opc_disasm(addr, data);
737 } else {
738 db_printf("%4.4x\n", data);
739 }
740 addr += 4;
741 db_end_line();
742 }
743
744 }
745 #endif
746
747 #endif /* DDB */
748
749 #endif /* PPC_IBM4XX */
750
751 #ifdef PPC_BOOKE
752 static void
753 db_ppcbooke_reset(db_expr_t addr, bool have_addr, db_expr_t count,
754 const char *modif)
755 {
756 printf("Reseting...\n");
757 (*cpu_md_ops.md_cpu_reset)();
758 }
759
760 static void
761 db_ppcbooke_tf(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
762 {
763 if (!have_addr)
764 return;
765
766 const struct trapframe * const tf = (const struct trapframe *)addr;
767
768 db_printf("trapframe %p (exc=%x srr0/1=%#lx/%#lx esr/dear=%#x/%#lx)\n",
769 tf, tf->tf_exc, tf->tf_srr0, tf->tf_srr1, tf->tf_esr, tf->tf_dear);
770 db_printf("lr =%08lx ctr=%08lx cr =%08x xer=%08x\n",
771 tf->tf_lr, tf->tf_ctr, tf->tf_cr, tf->tf_xer);
772 for (u_int r = 0; r < 32; r += 4) {
773 db_printf("r%02u=%08lx r%02u=%08lx r%02u=%08lx r%02u=%08lx\n",
774 r+0, tf->tf_fixreg[r+0], r+1, tf->tf_fixreg[r+1],
775 r+2, tf->tf_fixreg[r+2], r+3, tf->tf_fixreg[r+3]);
776 }
777 }
778
779 static void
780 db_ppcbooke_dumptlb(db_expr_t addr, bool have_addr, db_expr_t count,
781 const char *modif)
782 {
783 tlb_dump(db_printf);
784 }
785 #endif /* PPC_BOOKE */
786