1 /* $NetBSD: db_interface.c,v 1.60 2022/10/26 23:38:08 riastradh 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.60 2022/10/26 23:38:08 riastradh 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 #if defined (PPC_OEA) || defined(PPC_OEA64) || defined (PPC_OEA64_BRIDGE)
77 static void db_show_bat(db_expr_t, bool, db_expr_t, const char *);
78 static void db_show_mmu(db_expr_t, bool, db_expr_t, const char *);
79 #endif /* PPC_OEA || PPC_OEA64 || PPC_OEA64_BRIDGE */
80 #ifdef PPC_IBM4XX
81 static void db_ppc4xx_ctx(db_expr_t, bool, db_expr_t, const char *);
82 static void db_ppc4xx_pv(db_expr_t, bool, db_expr_t, const char *);
83 static void db_ppc4xx_reset(db_expr_t, bool, db_expr_t, const char *);
84 static void db_ppc4xx_tf(db_expr_t, bool, db_expr_t, const char *);
85 static void db_ppc4xx_dumptlb(db_expr_t, bool, db_expr_t, const char *);
86 static void db_ppc4xx_dcr(db_expr_t, bool, db_expr_t, const char *);
87 static db_expr_t db_ppc4xx_mfdcr(db_expr_t);
88 static void db_ppc4xx_mtdcr(db_expr_t, db_expr_t);
89 #ifdef USERACC
90 static void db_ppc4xx_useracc(db_expr_t, bool, db_expr_t, const char *);
91 #endif
92 #endif /* PPC_IBM4XX */
93
94 #ifdef PPC_BOOKE
95 static void db_ppcbooke_reset(db_expr_t, bool, db_expr_t, const char *);
96 static void db_ppcbooke_splhist(db_expr_t, bool, db_expr_t, const char *);
97 static void db_ppcbooke_tf(db_expr_t, bool, db_expr_t, const char *);
98 static void db_ppcbooke_dumptlb(db_expr_t, bool, db_expr_t, const char *);
99 #endif
100
101 #ifdef MULTIPROCESSOR
102 static void db_mach_cpu(db_expr_t, bool, db_expr_t, const char *);
103 #endif /* MULTIPROCESSOR */
104
105 #ifdef DDB
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
cpu_Debugger(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
ddb_trap_glue(struct trapframe * tf)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
kdb_trap(int type,void * v)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 #elif defined(KGDB)
256 if (!kgdb_trap(type, DDB_REGS)) {
257 rv = 0;
258 goto out;
259 }
260 #endif
261
262 /* KGDB isn't smart about advancing PC if we
263 * take a breakpoint trap after kgdb_active is set.
264 * Therefore, we help out here.
265 */
266 if (IS_BREAKPOINT_TRAP(type, 0)) {
267 int bkpt;
268 db_read_bytes(PC_REGS(DDB_REGS),BKPT_SIZE,(void *)&bkpt);
269 if (bkpt== BKPT_INST) {
270 PC_REGS(DDB_REGS) += BKPT_SIZE;
271 }
272 }
273
274 memcpy(tf->tf_fixreg, DDB_REGS->r, 32 * sizeof(u_int32_t));
275 tf->tf_srr0 = DDB_REGS->iar;
276 tf->tf_srr1 = DDB_REGS->msr;
277 tf->tf_lr = DDB_REGS->lr;
278 tf->tf_ctr = DDB_REGS->ctr;
279 tf->tf_cr = DDB_REGS->cr;
280 tf->tf_xer = DDB_REGS->xer;
281 #ifdef PPC_OEA
282 tf->tf_mq = DDB_REGS->mq;
283 #endif
284 #if defined(PPC_IBM4XX) || defined(PPC_BOOKE)
285 tf->tf_dear = DDB_REGS->dear;
286 tf->tf_esr = DDB_REGS->esr;
287 tf->tf_pid = DDB_REGS->pid;
288 #endif
289 #ifdef KGDB
290 out:
291 #endif /* KGDB */
292 splx(s);
293
294 #ifdef MULTIPROCESSOR
295 if (atomic_cas_uint(&ddb_cpu, cpu_me, NOCPU) == cpu_me) {
296 cpu_resume_others();
297 } else {
298 cpu_resume(ddb_cpu);
299 if (first_in_ddb)
300 cpu_pause(tf);
301 }
302 #endif /* MULTIPROCESSOR */
303
304 return rv;
305 }
306
307 #if defined (PPC_OEA) || defined(PPC_OEA64) || defined (PPC_OEA64_BRIDGE)
308 static void
print_battranslation(struct bat * bat,unsigned int blidx)309 print_battranslation(struct bat *bat, unsigned int blidx)
310 {
311 static const char batsizes[][6] = {
312 "128KB",
313 "256KB",
314 "512KB",
315 "1MB",
316 "2MB",
317 "4MB",
318 "8MB",
319 "16MB",
320 "32MB",
321 "64MB",
322 "128MB",
323 "256MB",
324 "512MB",
325 "1GB",
326 "2GB",
327 "4GB",
328 };
329 vsize_t len;
330
331 len = (0x20000L << blidx) - 1;
332 db_printf("\t%08lx %08lx %5s: 0x%08lx..0x%08lx -> 0x%08lx physical\n",
333 bat->batu, bat->batl, batsizes[blidx], bat->batu & ~len,
334 (bat->batu & ~len) + len, bat->batl & ~len);
335 }
336
337 static void
print_batmodes(register_t super,register_t user,register_t pp)338 print_batmodes(register_t super, register_t user, register_t pp)
339 {
340 static const char *const accessmodes[] = {
341 "none",
342 "ro soft",
343 "read/write",
344 "read only"
345 };
346
347 db_printf("\tvalid: %c%c access: %-10s memory:",
348 super ? 'S' : '-', user ? 'U' : '-', accessmodes[pp]);
349 }
350
351 static void
print_wimg(register_t wimg)352 print_wimg(register_t wimg)
353 {
354 if (wimg & BAT_W)
355 db_printf(" wrthrough");
356 if (wimg & BAT_I)
357 db_printf(" nocache");
358 if (wimg & BAT_M)
359 db_printf(" coherent");
360 if (wimg & BAT_G)
361 db_printf(" guard");
362 }
363
364 static void
print_bat(struct bat * bat)365 print_bat(struct bat *bat)
366 {
367 if ((bat->batu & BAT_V) == 0) {
368 db_printf("\tdisabled\n\n");
369 return;
370 }
371 print_battranslation(bat,
372 30 - __builtin_clz((bat->batu & (BAT_XBL|BAT_BL))|2));
373 print_batmodes(bat->batu & BAT_Vs, bat->batu & BAT_Vu,
374 bat->batl & BAT_PP);
375 print_wimg(bat->batl & BAT_WIMG);
376 db_printf("\n");
377 }
378
379 #ifdef PPC_OEA601
380 static void
print_bat601(struct bat * bat)381 print_bat601(struct bat *bat)
382 {
383 if ((bat->batl & BAT601_V) == 0) {
384 db_printf("\tdisabled\n\n");
385 return;
386 }
387 print_battranslation(bat, 32 - __builtin_clz(bat->batl & BAT601_BSM));
388 print_batmodes(bat->batu & BAT601_Ks, bat->batu & BAT601_Ku,
389 bat->batu & BAT601_PP);
390 print_wimg(bat->batu & (BAT601_W | BAT601_I | BAT601_M));
391 db_printf("\n");
392 }
393 #endif
394
395 static void
db_show_bat(db_expr_t addr,bool have_addr,db_expr_t count,const char * modif)396 db_show_bat(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
397 {
398 struct bat ibat[8];
399 struct bat dbat[8];
400 unsigned int cpuvers;
401 u_int i;
402 u_int maxbat = (oeacpufeat & OEACPU_HIGHBAT) ? 8 : 4;
403
404 if (oeacpufeat & OEACPU_NOBAT)
405 return;
406
407 cpuvers = mfpvr() >> 16;
408
409 ibat[0].batu = mfspr(SPR_IBAT0U);
410 ibat[0].batl = mfspr(SPR_IBAT0L);
411 ibat[1].batu = mfspr(SPR_IBAT1U);
412 ibat[1].batl = mfspr(SPR_IBAT1L);
413 ibat[2].batu = mfspr(SPR_IBAT2U);
414 ibat[2].batl = mfspr(SPR_IBAT2L);
415 ibat[3].batu = mfspr(SPR_IBAT3U);
416 ibat[3].batl = mfspr(SPR_IBAT3L);
417 if (maxbat == 8) {
418 ibat[4].batu = mfspr(SPR_IBAT4U);
419 ibat[4].batl = mfspr(SPR_IBAT4L);
420 ibat[5].batu = mfspr(SPR_IBAT5U);
421 ibat[5].batl = mfspr(SPR_IBAT5L);
422 ibat[6].batu = mfspr(SPR_IBAT6U);
423 ibat[6].batl = mfspr(SPR_IBAT6L);
424 ibat[7].batu = mfspr(SPR_IBAT7U);
425 ibat[7].batl = mfspr(SPR_IBAT7L);
426 }
427
428 if (cpuvers != MPC601) {
429 /* The 601 has only four unified BATs */
430 dbat[0].batu = mfspr(SPR_DBAT0U);
431 dbat[0].batl = mfspr(SPR_DBAT0L);
432 dbat[1].batu = mfspr(SPR_DBAT1U);
433 dbat[1].batl = mfspr(SPR_DBAT1L);
434 dbat[2].batu = mfspr(SPR_DBAT2U);
435 dbat[2].batl = mfspr(SPR_DBAT2L);
436 dbat[3].batu = mfspr(SPR_DBAT3U);
437 dbat[3].batl = mfspr(SPR_DBAT3L);
438 if (maxbat == 8) {
439 dbat[4].batu = mfspr(SPR_DBAT4U);
440 dbat[4].batl = mfspr(SPR_DBAT4L);
441 dbat[5].batu = mfspr(SPR_DBAT5U);
442 dbat[5].batl = mfspr(SPR_DBAT5L);
443 dbat[6].batu = mfspr(SPR_DBAT6U);
444 dbat[6].batl = mfspr(SPR_DBAT6L);
445 dbat[7].batu = mfspr(SPR_DBAT7U);
446 dbat[7].batl = mfspr(SPR_DBAT7L);
447 }
448 }
449
450 for (i = 0; i < maxbat; i++) {
451 #ifdef PPC_OEA601
452 if (cpuvers == MPC601) {
453 db_printf("bat[%u]:\n", i);
454 print_bat601(&ibat[i]);
455 } else
456 #endif
457 {
458 db_printf("ibat[%u]:\n", i);
459 print_bat(&ibat[i]);
460 db_printf("dbat[%u]:\n", i);
461 print_bat(&dbat[i]);
462 }
463 }
464 }
465
466 static void
db_show_mmu(db_expr_t addr,bool have_addr,db_expr_t count,const char * modif)467 db_show_mmu(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
468 {
469 paddr_t sdr1;
470
471 __asm volatile ("mfsdr1 %0" : "=r"(sdr1));
472 db_printf("sdr1\t\t0x%08lx\n", sdr1);
473
474 #if defined(PPC_OEA64) || defined(PPC_OEA64_BRIDGE)
475 if (oeacpufeat & (OEACPU_64|OEACPU_64_BRIDGE)) {
476 __asm volatile ("mfasr %0" : "=r"(sdr1));
477 db_printf("asr\t\t0x%08lx\n", sdr1);
478 }
479 #endif
480 #if defined(PPC_OEA) || defined(PPC_OEA64_BRIDGE)
481 if ((oeacpufeat & OEACPU_64) == 0) {
482 vaddr_t saddr = 0;
483 for (u_int i = 0; i <= 0xf; i++) {
484 register_t sr;
485 if ((i & 3) == 0)
486 db_printf("sr%d-%d\t\t", i, i+3);
487 __asm volatile ("mfsrin %0,%1" : "=r"(sr) : "r"(saddr));
488 db_printf("0x%08lx %c", sr, (i&3) == 3 ? '\n' : ' ');
489 saddr += 1 << ADDR_SR_SHFT;
490 }
491 }
492 #endif
493 }
494 #endif /* PPC_OEA || PPC_OEA64 || PPC_OEA64_BRIDGE */
495
496 #if defined(PPC_IBM4XX) || defined(PPC_BOOKE)
497 db_addr_t
branch_taken(int inst,db_addr_t pc,db_regs_t * regs)498 branch_taken(int inst, db_addr_t pc, db_regs_t *regs)
499 {
500
501 if ((inst & M_B ) == I_B || (inst & M_B ) == I_BL) {
502 db_expr_t off;
503 off = ((db_expr_t)((inst & 0x03fffffc) << 6)) >> 6;
504 return (((inst & 0x2) ? 0 : pc) + off);
505 }
506
507 if ((inst & M_BC) == I_BC || (inst & M_BC) == I_BCL) {
508 db_expr_t off;
509 off = ((db_expr_t)((inst & 0x0000fffc) << 16)) >> 16;
510 return (((inst & 0x2) ? 0 : pc) + off);
511 }
512
513 if ((inst & M_RTS) == I_RTS || (inst & M_RTS) == I_BLRL)
514 return (regs->lr);
515
516 if ((inst & M_BCTR) == I_BCTR || (inst & M_BCTR) == I_BCTRL)
517 return (regs->ctr);
518
519 db_printf("branch_taken: can't figure out branch target for 0x%x!\n",
520 inst);
521 return (0);
522 }
523 #endif /* PPC_IBM4XX || PPC_BOOKE */
524
525
526 #ifdef PPC_IBM4XX
527 #ifdef DDB
528 static void
db_ppc4xx_ctx(db_expr_t addr,bool have_addr,db_expr_t count,const char * modif)529 db_ppc4xx_ctx(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
530 {
531 struct proc *p;
532
533 /* XXX LOCKING XXX */
534 for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) {
535 if (p->p_stat) {
536 db_printf("process %p:", p);
537 db_printf("pid:%d pmap:%p ctx:%d %s\n",
538 p->p_pid, p->p_vmspace->vm_map.pmap,
539 p->p_vmspace->vm_map.pmap->pm_ctx,
540 p->p_comm);
541 }
542 }
543 return;
544 }
545
546 static void
db_ppc4xx_pv(db_expr_t addr,bool have_addr,db_expr_t count,const char * modif)547 db_ppc4xx_pv(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
548 {
549 struct pv_entry {
550 struct pv_entry *pv_next; /* Linked list of mappings */
551 vaddr_t pv_va; /* virtual address of mapping */
552 struct pmap *pv_pm;
553 };
554 struct pv_entry *pa_to_pv(paddr_t);
555 struct pv_entry *pv;
556
557 if (!have_addr) {
558 db_printf("pv: <pa>\n");
559 return;
560 }
561 pv = pa_to_pv(addr);
562 db_printf("pv at %p\n", pv);
563 while (pv && pv->pv_pm) {
564 db_printf("next %p va %p pmap %p\n", pv->pv_next,
565 (void *)pv->pv_va, pv->pv_pm);
566 pv = pv->pv_next;
567 }
568 }
569
570 static void
db_ppc4xx_reset(db_expr_t addr,bool have_addr,db_expr_t count,const char * modif)571 db_ppc4xx_reset(db_expr_t addr, bool have_addr, db_expr_t count,
572 const char *modif)
573 {
574 printf("Resetting...\n");
575 ppc4xx_reset();
576 }
577
578 static void
db_ppc4xx_tf(db_expr_t addr,bool have_addr,db_expr_t count,const char * modif)579 db_ppc4xx_tf(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
580 {
581 struct trapframe *tf;
582
583
584 if (have_addr) {
585 tf = (struct trapframe *)addr;
586
587 db_printf("r0-r3: \t%8.8lx %8.8lx %8.8lx %8.8lx\n",
588 tf->tf_fixreg[0], tf->tf_fixreg[1],
589 tf->tf_fixreg[2], tf->tf_fixreg[3]);
590 db_printf("r4-r7: \t%8.8lx %8.8lx %8.8lx %8.8lx\n",
591 tf->tf_fixreg[4], tf->tf_fixreg[5],
592 tf->tf_fixreg[6], tf->tf_fixreg[7]);
593 db_printf("r8-r11: \t%8.8lx %8.8lx %8.8lx %8.8lx\n",
594 tf->tf_fixreg[8], tf->tf_fixreg[9],
595 tf->tf_fixreg[10], tf->tf_fixreg[11]);
596 db_printf("r12-r15:\t%8.8lx %8.8lx %8.8lx %8.8lx\n",
597 tf->tf_fixreg[12], tf->tf_fixreg[13],
598 tf->tf_fixreg[14], tf->tf_fixreg[15]);
599 db_printf("r16-r19:\t%8.8lx %8.8lx %8.8lx %8.8lx\n",
600 tf->tf_fixreg[16], tf->tf_fixreg[17],
601 tf->tf_fixreg[18], tf->tf_fixreg[19]);
602 db_printf("r20-r23:\t%8.8lx %8.8lx %8.8lx %8.8lx\n",
603 tf->tf_fixreg[20], tf->tf_fixreg[21],
604 tf->tf_fixreg[22], tf->tf_fixreg[23]);
605 db_printf("r24-r27:\t%8.8lx %8.8lx %8.8lx %8.8lx\n",
606 tf->tf_fixreg[24], tf->tf_fixreg[25],
607 tf->tf_fixreg[26], tf->tf_fixreg[27]);
608 db_printf("r28-r31:\t%8.8lx %8.8lx %8.8lx %8.8lx\n",
609 tf->tf_fixreg[28], tf->tf_fixreg[29],
610 tf->tf_fixreg[30], tf->tf_fixreg[31]);
611
612 db_printf("lr: %8.8lx cr: %8.8x xer: %8.8x ctr: %8.8lx\n",
613 tf->tf_lr, tf->tf_cr, tf->tf_xer, tf->tf_ctr);
614 db_printf("srr0(pc): %8.8lx srr1(msr): %8.8lx "
615 "dear: %8.8lx esr: %8.8x\n",
616 tf->tf_srr0, tf->tf_srr1, tf->tf_dear, tf->tf_esr);
617 db_printf("exc: %8.8x pid: %8.8x\n",
618 tf->tf_exc, tf->tf_pid);
619 }
620 return;
621 }
622
623 static const char *const tlbsizes[] = {
624 "1kB",
625 "4kB",
626 "16kB",
627 "64kB",
628 "256kB",
629 "1MB",
630 "4MB",
631 "16MB"
632 };
633
634 static void
db_ppc4xx_dumptlb(db_expr_t addr,bool have_addr,db_expr_t count,const char * modif)635 db_ppc4xx_dumptlb(db_expr_t addr, bool have_addr, db_expr_t count,
636 const char *modif)
637 {
638 int i, zone, tlbsize;
639 u_int zpr, pid, opid, msr;
640 u_long tlblo, tlbhi, tlbmask;
641
642 zpr = mfspr(SPR_ZPR);
643 for (i = 0; i < NTLB; i++) {
644 __asm volatile("mfmsr %3;"
645 MFPID(%4)
646 "li %0,0;"
647 "mtmsr %0;"
648 "sync; isync;"
649 "tlbrelo %0,%5;"
650 "tlbrehi %1,%5;"
651 MFPID(%2)
652 MTPID(%4)
653 "mtmsr %3;"
654 "sync; isync"
655 : "=&r" (tlblo), "=&r" (tlbhi), "=r" (pid),
656 "=&r" (msr), "=&r" (opid) : "r" (i));
657
658 if (strchr(modif, 'v') && !(tlbhi & TLB_VALID))
659 continue;
660
661 tlbsize = (tlbhi & TLB_SIZE_MASK) >> TLB_SIZE_SHFT;
662 /* map tlbsize 0 .. 7 to masks for 1kB .. 16MB */
663 tlbmask = ~(1 << (tlbsize * 2 + 10)) + 1;
664
665 if (have_addr && ((tlbhi & tlbmask) != (addr & tlbmask)))
666 continue;
667
668 zone = (tlblo & TLB_ZSEL_MASK) >> TLB_ZSEL_SHFT;
669 db_printf("tlb%c%2d", tlbhi & TLB_VALID ? ' ' : '*', i);
670 db_printf(" PID %3d EPN 0x%08lx %-5s",
671 pid,
672 tlbhi & tlbmask,
673 tlbsizes[tlbsize]);
674 db_printf(" RPN 0x%08lx ZONE %2d%c %s %s %c%c%c%c%c %s",
675 tlblo & tlbmask,
676 zone,
677 "NTTA"[(zpr >> ((15 - zone) * 2)) & 3],
678 tlblo & TLB_EX ? "EX" : " ",
679 tlblo & TLB_WR ? "WR" : " ",
680 tlblo & TLB_W ? 'W' : ' ',
681 tlblo & TLB_I ? 'I' : ' ',
682 tlblo & TLB_M ? 'M' : ' ',
683 tlblo & TLB_G ? 'G' : ' ',
684 tlbhi & TLB_ENDIAN ? 'E' : ' ',
685 tlbhi & TLB_U0 ? "U0" : " ");
686 db_printf("\n");
687 }
688 }
689
690 static void
db_ppc4xx_dcr(db_expr_t address,bool have_addr,db_expr_t count,const char * modif)691 db_ppc4xx_dcr(db_expr_t address, bool have_addr, db_expr_t count,
692 const char *modif)
693 {
694 db_expr_t new_value;
695 db_expr_t addr;
696
697 if (address < 0 || address > 0x3ff)
698 db_error("Invalid DCR address (Valid range is 0x0 - 0x3ff)\n");
699
700 addr = address;
701
702 while (db_expression(&new_value)) {
703 db_printf("dcr 0x%lx\t\t%s = ", addr,
704 db_num_to_str(db_ppc4xx_mfdcr(addr)));
705 db_ppc4xx_mtdcr(addr, new_value);
706 db_printf("%s\n", db_num_to_str(db_ppc4xx_mfdcr(addr)));
707 addr += 1;
708 }
709
710 if (addr == address) {
711 db_next = (db_addr_t)addr + 1;
712 db_prev = (db_addr_t)addr;
713 db_printf("dcr 0x%lx\t\t%s\n", addr,
714 db_num_to_str(db_ppc4xx_mfdcr(addr)));
715 } else {
716 db_next = (db_addr_t)addr;
717 db_prev = (db_addr_t)addr - 1;
718 }
719
720 db_skip_to_eol();
721 }
722
723 /*
724 * XXX Grossness Alert! XXX
725 *
726 * Please look away now if you don't like self-modifying code
727 */
728 static u_int32_t db_ppc4xx_dcrfunc[4];
729
730 static db_expr_t
db_ppc4xx_mfdcr(db_expr_t reg)731 db_ppc4xx_mfdcr(db_expr_t reg)
732 {
733 db_expr_t (*func)(void);
734
735 reg = (((reg & 0x1f) << 5) | ((reg >> 5) & 0x1f)) << 11;
736 db_ppc4xx_dcrfunc[0] = 0x7c0004ac; /* sync */
737 db_ppc4xx_dcrfunc[1] = 0x4c00012c; /* isync */
738 db_ppc4xx_dcrfunc[2] = 0x7c600286 | reg; /* mfdcr reg, r3 */
739 db_ppc4xx_dcrfunc[3] = 0x4e800020; /* blr */
740
741 __syncicache((void *)db_ppc4xx_dcrfunc, sizeof(db_ppc4xx_dcrfunc));
742 func = (db_expr_t (*)(void))(void *)db_ppc4xx_dcrfunc;
743
744 return ((*func)());
745 }
746
747 static void
db_ppc4xx_mtdcr(db_expr_t reg,db_expr_t val)748 db_ppc4xx_mtdcr(db_expr_t reg, db_expr_t val)
749 {
750 db_expr_t (*func)(db_expr_t);
751
752 reg = (((reg & 0x1f) << 5) | ((reg >> 5) & 0x1f)) << 11;
753 db_ppc4xx_dcrfunc[0] = 0x7c0004ac; /* sync */
754 db_ppc4xx_dcrfunc[1] = 0x4c00012c; /* isync */
755 db_ppc4xx_dcrfunc[2] = 0x7c600386 | reg; /* mtdcr r3, reg */
756 db_ppc4xx_dcrfunc[3] = 0x4e800020; /* blr */
757
758 __syncicache((void *)db_ppc4xx_dcrfunc, sizeof(db_ppc4xx_dcrfunc));
759 func = (db_expr_t (*)(db_expr_t))(void *)db_ppc4xx_dcrfunc;
760
761 (*func)(val);
762 }
763
764 #ifdef USERACC
765 static void
db_ppc4xx_useracc(db_expr_t addr,bool have_addr,db_expr_t count,const char * modif)766 db_ppc4xx_useracc(db_expr_t addr, bool have_addr, db_expr_t count,
767 const char *modif)
768 {
769 static paddr_t oldaddr = -1;
770 int instr = 0;
771 int data;
772 extern vaddr_t opc_disasm(vaddr_t loc, int);
773
774
775 if (!have_addr) {
776 addr = oldaddr;
777 }
778 if (addr == -1) {
779 db_printf("no address\n");
780 return;
781 }
782 addr &= ~0x3; /* align */
783 {
784 const char *cp = modif;
785 char c;
786 while ((c = *cp++) != 0)
787 if (c == 'i')
788 instr = 1;
789 }
790 while (count--) {
791 if (db_print_position() == 0) {
792 /* Always print the address. */
793 db_printf("%8.4lx:\t", addr);
794 }
795 oldaddr=addr;
796 copyin((void *)addr, &data, sizeof(data));
797 if (instr) {
798 opc_disasm(addr, data);
799 } else {
800 db_printf("%4.4x\n", data);
801 }
802 addr += 4;
803 db_end_line();
804 }
805
806 }
807 #endif
808
809 #endif /* DDB */
810
811 #endif /* PPC_IBM4XX */
812
813 #ifdef PPC_BOOKE
814 static void
db_ppcbooke_reset(db_expr_t addr,bool have_addr,db_expr_t count,const char * modif)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
db_ppcbooke_splhist(db_expr_t addr,bool have_addr,db_expr_t count,const char * modif)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
db_ppcbooke_tf(db_expr_t addr,bool have_addr,db_expr_t count,const char * modif)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
db_ppcbooke_dumptlb(db_expr_t addr,bool have_addr,db_expr_t count,const char * modif)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
ddb_running_on_this_cpu_p(void)849 ddb_running_on_this_cpu_p(void)
850 {
851
852 return ddb_cpu == cpu_number();
853 }
854
855 bool
ddb_running_on_any_cpu_p(void)856 ddb_running_on_any_cpu_p(void)
857 {
858
859 return ddb_cpu != NOCPU;
860 }
861
862 void
db_resume_others(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
db_mach_cpu(db_expr_t addr,bool have_addr,db_expr_t count,const char * modif)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