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