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