xref: /netbsd/sys/arch/powerpc/powerpc/db_interface.c (revision e00aa033)
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