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