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