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