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