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
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 #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
print_battranslation(struct bat * bat,unsigned int blidx)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
print_batmodes(register_t super,register_t user,register_t pp)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
print_wimg(register_t wimg)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
print_bat(struct bat * bat)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
print_bat601(struct bat * bat)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
db_show_bat(db_expr_t addr,bool have_addr,db_expr_t count,const char * modif)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
db_show_mmu(db_expr_t addr,bool have_addr,db_expr_t count,const char * modif)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
branch_taken(int inst,db_addr_t pc,db_regs_t * regs)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
db_ppc4xx_ctx(db_expr_t addr,bool have_addr,db_expr_t count,const char * modif)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
db_ppc4xx_pv(db_expr_t addr,bool have_addr,db_expr_t count,const char * modif)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
db_ppc4xx_reset(db_expr_t addr,bool have_addr,db_expr_t count,const char * modif)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
db_ppc4xx_tf(db_expr_t addr,bool have_addr,db_expr_t count,const char * modif)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
db_ppc4xx_dumptlb(db_expr_t addr,bool have_addr,db_expr_t count,const char * modif)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
db_ppc4xx_dcr(db_expr_t address,bool have_addr,db_expr_t count,const char * modif)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
db_ppc4xx_mfdcr(db_expr_t reg)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
db_ppc4xx_mtdcr(db_expr_t reg,db_expr_t val)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
db_ppc4xx_useracc(db_expr_t addr,bool have_addr,db_expr_t count,const char * modif)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
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 #endif /* DDB */
908