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