Home | History | Annotate | Line # | Download | only in powerpc
db_interface.c revision 1.49
      1 /*	$NetBSD: db_interface.c,v 1.49 2012/02/01 05:25:58 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.49 2012/02/01 05:25:58 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_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 	cpuvers = mfpvr() >> 16;
    347 
    348 	ibat[0].batu = mfspr(SPR_IBAT0U);
    349 	ibat[0].batl = mfspr(SPR_IBAT0L);
    350 	ibat[1].batu = mfspr(SPR_IBAT1U);
    351 	ibat[1].batl = mfspr(SPR_IBAT1L);
    352 	ibat[2].batu = mfspr(SPR_IBAT2U);
    353 	ibat[2].batl = mfspr(SPR_IBAT2L);
    354 	ibat[3].batu = mfspr(SPR_IBAT3U);
    355 	ibat[3].batl = mfspr(SPR_IBAT3L);
    356 	if (maxbat == 8) {
    357 		ibat[4].batu = mfspr(SPR_IBAT4U);
    358 		ibat[4].batl = mfspr(SPR_IBAT4L);
    359 		ibat[5].batu = mfspr(SPR_IBAT5U);
    360 		ibat[5].batl = mfspr(SPR_IBAT5L);
    361 		ibat[6].batu = mfspr(SPR_IBAT6U);
    362 		ibat[6].batl = mfspr(SPR_IBAT6L);
    363 		ibat[7].batu = mfspr(SPR_IBAT7U);
    364 		ibat[7].batl = mfspr(SPR_IBAT7L);
    365 	}
    366 
    367 	if (cpuvers != MPC601) {
    368 		/* The 601 has only four unified BATs */
    369 		dbat[0].batu = mfspr(SPR_DBAT0U);
    370 		dbat[0].batl = mfspr(SPR_DBAT0L);
    371 		dbat[1].batu = mfspr(SPR_DBAT1U);
    372 		dbat[1].batl = mfspr(SPR_DBAT1L);
    373 		dbat[2].batu = mfspr(SPR_DBAT2U);
    374 		dbat[2].batl = mfspr(SPR_DBAT2L);
    375 		dbat[3].batu = mfspr(SPR_DBAT3U);
    376 		dbat[3].batl = mfspr(SPR_DBAT3L);
    377 		if (maxbat == 8) {
    378 			dbat[4].batu = mfspr(SPR_DBAT4U);
    379 			dbat[4].batl = mfspr(SPR_DBAT4L);
    380 			dbat[5].batu = mfspr(SPR_DBAT5U);
    381 			dbat[5].batl = mfspr(SPR_DBAT5L);
    382 			dbat[6].batu = mfspr(SPR_DBAT6U);
    383 			dbat[6].batl = mfspr(SPR_DBAT6L);
    384 			dbat[7].batu = mfspr(SPR_DBAT7U);
    385 			dbat[7].batl = mfspr(SPR_DBAT7L);
    386 		}
    387 	}
    388 
    389 	for (i = 0; i < maxbat; i++) {
    390 #ifdef PPC_OEA601
    391 		if (cpuvers == MPC601) {
    392 			db_printf("bat[%u]:\n", i);
    393 			print_bat601(&ibat[i]);
    394 		} else
    395 #endif
    396 		{
    397 			db_printf("ibat[%u]:\n", i);
    398 			print_bat(&ibat[i]);
    399 			db_printf("dbat[%u]:\n", i);
    400 			print_bat(&dbat[i]);
    401 		}
    402 	}
    403 }
    404 
    405 static void
    406 db_show_mmu(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
    407 {
    408 	paddr_t sdr1;
    409 #if !defined(PPC_OEA64) && !defined(PPC_OEA64_BRIDGE)
    410 	register_t sr;
    411 	vaddr_t saddr;
    412 	int i;
    413 #endif
    414 
    415 	__asm volatile ("mfsdr1 %0" : "=r"(sdr1));
    416 	db_printf("sdr1\t\t0x%08lx\n", sdr1);
    417 
    418 #if defined(PPC_OEA64) || defined(PPC_OEA64_BRIDGE)
    419 	__asm volatile ("mfasr %0" : "=r"(sdr1));
    420 	db_printf("asr\t\t0x%08lx\n", sdr1);
    421 #else
    422 	saddr = 0;
    423 	for (i = 0; i<= 0xf; i++) {
    424 		if ((i & 3) == 0)
    425 			db_printf("sr%d-%d\t\t", i, i+3);
    426 		__asm volatile ("mfsrin %0,%1" : "=r"(sr) : "r"(saddr));
    427 		db_printf("0x%08lx   %c", sr, (i&3) == 3 ? '\n' : ' ');
    428 		saddr += 1 << ADDR_SR_SHFT;
    429 	}
    430 #endif
    431 }
    432 #endif /* PPC_OEA || PPC_OEA64 || PPC_OEA64_BRIDGE */
    433 
    434 #if defined(PPC_IBM4XX) || defined(PPC_BOOKE)
    435 db_addr_t
    436 branch_taken(int inst, db_addr_t pc, db_regs_t *regs)
    437 {
    438 
    439 	if ((inst & M_B ) == I_B || (inst & M_B ) == I_BL) {
    440 		db_expr_t off;
    441 		off = ((db_expr_t)((inst & 0x03fffffc) << 6)) >> 6;
    442 		return (((inst & 0x2) ? 0 : pc) + off);
    443 	}
    444 
    445 	if ((inst & M_BC) == I_BC || (inst & M_BC) == I_BCL) {
    446 		db_expr_t off;
    447 		off = ((db_expr_t)((inst & 0x0000fffc) << 16)) >> 16;
    448 		return (((inst & 0x2) ? 0 : pc) + off);
    449 	}
    450 
    451 	if ((inst & M_RTS) == I_RTS || (inst & M_RTS) == I_BLRL)
    452 		return (regs->lr);
    453 
    454 	if ((inst & M_BCTR) == I_BCTR || (inst & M_BCTR) == I_BCTRL)
    455 		return (regs->ctr);
    456 
    457 	db_printf("branch_taken: can't figure out branch target for 0x%x!\n",
    458 	    inst);
    459 	return (0);
    460 }
    461 #endif /* PPC_IBM4XX || PPC_BOOKE */
    462 
    463 
    464 #ifdef PPC_IBM4XX
    465 #ifdef DDB
    466 static void
    467 db_ppc4xx_ctx(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
    468 {
    469 	struct proc *p;
    470 
    471 	/* XXX LOCKING XXX */
    472 	for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) {
    473 		if (p->p_stat) {
    474 			db_printf("process %p:", p);
    475 			db_printf("pid:%d pmap:%p ctx:%d %s\n",
    476 				p->p_pid, p->p_vmspace->vm_map.pmap,
    477 				p->p_vmspace->vm_map.pmap->pm_ctx,
    478 				p->p_comm);
    479 		}
    480 	}
    481 	return;
    482 }
    483 
    484 static void
    485 db_ppc4xx_pv(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
    486 {
    487 	struct pv_entry {
    488 		struct pv_entry *pv_next;	/* Linked list of mappings */
    489 		vaddr_t pv_va;			/* virtual address of mapping */
    490 		struct pmap *pv_pm;
    491 	};
    492 	struct pv_entry *pa_to_pv(paddr_t);
    493 	struct pv_entry *pv;
    494 
    495 	if (!have_addr) {
    496 		db_printf("pv: <pa>\n");
    497 		return;
    498 	}
    499 	pv = pa_to_pv(addr);
    500 	db_printf("pv at %p\n", pv);
    501 	while (pv && pv->pv_pm) {
    502 		db_printf("next %p va %p pmap %p\n", pv->pv_next,
    503 			(void *)pv->pv_va, pv->pv_pm);
    504 		pv = pv->pv_next;
    505 	}
    506 }
    507 
    508 static void
    509 db_ppc4xx_reset(db_expr_t addr, bool have_addr, db_expr_t count,
    510     const char *modif)
    511 {
    512 	printf("Reseting...\n");
    513 	ppc4xx_reset();
    514 }
    515 
    516 static void
    517 db_ppc4xx_tf(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
    518 {
    519 	struct trapframe *tf;
    520 
    521 
    522 	if (have_addr) {
    523 		tf = (struct trapframe *)addr;
    524 
    525 		db_printf("r0-r3:  \t%8.8lx %8.8lx %8.8lx %8.8lx\n",
    526 			tf->tf_fixreg[0], tf->tf_fixreg[1],
    527 			tf->tf_fixreg[2], tf->tf_fixreg[3]);
    528 		db_printf("r4-r7:  \t%8.8lx %8.8lx %8.8lx %8.8lx\n",
    529 			tf->tf_fixreg[4], tf->tf_fixreg[5],
    530 			tf->tf_fixreg[6], tf->tf_fixreg[7]);
    531 		db_printf("r8-r11: \t%8.8lx %8.8lx %8.8lx %8.8lx\n",
    532 			tf->tf_fixreg[8], tf->tf_fixreg[9],
    533 			tf->tf_fixreg[10], tf->tf_fixreg[11]);
    534 		db_printf("r12-r15:\t%8.8lx %8.8lx %8.8lx %8.8lx\n",
    535 			tf->tf_fixreg[12], tf->tf_fixreg[13],
    536 			tf->tf_fixreg[14], tf->tf_fixreg[15]);
    537 		db_printf("r16-r19:\t%8.8lx %8.8lx %8.8lx %8.8lx\n",
    538 			tf->tf_fixreg[16], tf->tf_fixreg[17],
    539 			tf->tf_fixreg[18], tf->tf_fixreg[19]);
    540 		db_printf("r20-r23:\t%8.8lx %8.8lx %8.8lx %8.8lx\n",
    541 			tf->tf_fixreg[20], tf->tf_fixreg[21],
    542 			tf->tf_fixreg[22], tf->tf_fixreg[23]);
    543 		db_printf("r24-r27:\t%8.8lx %8.8lx %8.8lx %8.8lx\n",
    544 			tf->tf_fixreg[24], tf->tf_fixreg[25],
    545 			tf->tf_fixreg[26], tf->tf_fixreg[27]);
    546 		db_printf("r28-r31:\t%8.8lx %8.8lx %8.8lx %8.8lx\n",
    547 			tf->tf_fixreg[28], tf->tf_fixreg[29],
    548 			tf->tf_fixreg[30], tf->tf_fixreg[31]);
    549 
    550 		db_printf("lr: %8.8lx cr: %8.8x xer: %8.8x ctr: %8.8lx\n",
    551 			tf->tf_lr, tf->tf_cr, tf->tf_xer, tf->tf_ctr);
    552 		db_printf("srr0(pc): %8.8lx srr1(msr): %8.8lx "
    553 			"dear: %8.8lx esr: %8.8x\n",
    554 			tf->tf_srr0, tf->tf_srr1, tf->tf_dear, tf->tf_esr);
    555 		db_printf("exc: %8.8x pid: %8.8x\n",
    556 			tf->tf_exc, tf->tf_pid);
    557 	}
    558 	return;
    559 }
    560 
    561 static const char *const tlbsizes[] = {
    562 	  "1kB",
    563 	  "4kB",
    564 	 "16kB",
    565 	 "64kB",
    566 	"256kB",
    567 	  "1MB",
    568 	  "4MB",
    569 	 "16MB"
    570 };
    571 
    572 static void
    573 db_ppc4xx_dumptlb(db_expr_t addr, bool have_addr, db_expr_t count,
    574     const char *modif)
    575 {
    576 	int i, zone, tlbsize;
    577 	u_int zpr, pid, opid, msr;
    578 	u_long tlblo, tlbhi, tlbmask;
    579 
    580 	zpr = mfspr(SPR_ZPR);
    581 	for (i = 0; i < NTLB; i++) {
    582 		__asm volatile("mfmsr %3;"
    583 			"mfpid %4;"
    584 			"li %0,0;"
    585 			"mtmsr %0;"
    586 			"sync; isync;"
    587 			"tlbrelo %0,%5;"
    588 			"tlbrehi %1,%5;"
    589 			"mfpid %2;"
    590 			"mtpid %4;"
    591 			"mtmsr %3;"
    592 			"sync; isync"
    593 			: "=&r" (tlblo), "=&r" (tlbhi), "=r" (pid),
    594 			"=&r" (msr), "=&r" (opid) : "r" (i));
    595 
    596 		if (strchr(modif, 'v') && !(tlbhi & TLB_VALID))
    597 			continue;
    598 
    599 		tlbsize = (tlbhi & TLB_SIZE_MASK) >> TLB_SIZE_SHFT;
    600 		/* map tlbsize 0 .. 7 to masks for 1kB .. 16MB */
    601 		tlbmask = ~(1 << (tlbsize * 2 + 10)) + 1;
    602 
    603 		if (have_addr && ((tlbhi & tlbmask) != (addr & tlbmask)))
    604 			continue;
    605 
    606 		zone = (tlblo & TLB_ZSEL_MASK) >> TLB_ZSEL_SHFT;
    607 		db_printf("tlb%c%2d", tlbhi & TLB_VALID ? ' ' : '*', i);
    608 		db_printf("  PID %3d EPN 0x%08lx %-5s",
    609 		    pid,
    610 		    tlbhi & tlbmask,
    611 		    tlbsizes[tlbsize]);
    612 		db_printf("  RPN 0x%08lx  ZONE %2d%c  %s %s %c%c%c%c%c %s",
    613 		    tlblo & tlbmask,
    614 		    zone,
    615 		    "NTTA"[(zpr >> ((15 - zone) * 2)) & 3],
    616 		    tlblo & TLB_EX ? "EX" : "  ",
    617 		    tlblo & TLB_WR ? "WR" : "  ",
    618 		    tlblo & TLB_W ? 'W' : ' ',
    619 		    tlblo & TLB_I ? 'I' : ' ',
    620 		    tlblo & TLB_M ? 'M' : ' ',
    621 		    tlblo & TLB_G ? 'G' : ' ',
    622 		    tlbhi & TLB_ENDIAN ? 'E' : ' ',
    623 		    tlbhi & TLB_U0 ? "U0" : "  ");
    624 		db_printf("\n");
    625 	}
    626 }
    627 
    628 static void
    629 db_ppc4xx_dcr(db_expr_t address, bool have_addr, db_expr_t count,
    630     const char *modif)
    631 {
    632 	db_expr_t new_value;
    633 	db_expr_t addr;
    634 
    635 	if (address < 0 || address > 0x3ff)
    636 		db_error("Invalid DCR address (Valid range is 0x0 - 0x3ff)\n");
    637 
    638 	addr = address;
    639 
    640 	while (db_expression(&new_value)) {
    641 		db_printf("dcr 0x%lx\t\t%s = ", addr,
    642 		    db_num_to_str(db_ppc4xx_mfdcr(addr)));
    643 		db_ppc4xx_mtdcr(addr, new_value);
    644 		db_printf("%s\n", db_num_to_str(db_ppc4xx_mfdcr(addr)));
    645 		addr += 1;
    646 	}
    647 
    648 	if (addr == address) {
    649 		db_next = (db_addr_t)addr + 1;
    650 		db_prev = (db_addr_t)addr;
    651 		db_printf("dcr 0x%lx\t\t%s\n", addr,
    652 		    db_num_to_str(db_ppc4xx_mfdcr(addr)));
    653 	} else {
    654 		db_next = (db_addr_t)addr;
    655 		db_prev = (db_addr_t)addr - 1;
    656 	}
    657 
    658 	db_skip_to_eol();
    659 }
    660 
    661 /*
    662  * XXX Grossness Alert! XXX
    663  *
    664  * Please look away now if you don't like self-modifying code
    665  */
    666 static u_int32_t db_ppc4xx_dcrfunc[4];
    667 
    668 static db_expr_t
    669 db_ppc4xx_mfdcr(db_expr_t reg)
    670 {
    671 	db_expr_t (*func)(void);
    672 
    673 	reg = (((reg & 0x1f) << 5) | ((reg >> 5) & 0x1f)) << 11;
    674 	db_ppc4xx_dcrfunc[0] = 0x7c0004ac;		/* sync */
    675 	db_ppc4xx_dcrfunc[1] = 0x4c00012c;		/* isync */
    676 	db_ppc4xx_dcrfunc[2] = 0x7c600286 | reg;	/* mfdcr reg, r3 */
    677 	db_ppc4xx_dcrfunc[3] = 0x4e800020;		/* blr */
    678 
    679 	__syncicache((void *)db_ppc4xx_dcrfunc, sizeof(db_ppc4xx_dcrfunc));
    680 	func = (db_expr_t (*)(void))(void *)db_ppc4xx_dcrfunc;
    681 
    682 	return ((*func)());
    683 }
    684 
    685 static void
    686 db_ppc4xx_mtdcr(db_expr_t reg, db_expr_t val)
    687 {
    688 	db_expr_t (*func)(db_expr_t);
    689 
    690 	reg = (((reg & 0x1f) << 5) | ((reg >> 5) & 0x1f)) << 11;
    691 	db_ppc4xx_dcrfunc[0] = 0x7c0004ac;		/* sync */
    692 	db_ppc4xx_dcrfunc[1] = 0x4c00012c;		/* isync */
    693 	db_ppc4xx_dcrfunc[2] = 0x7c600386 | reg;	/* mtdcr r3, reg */
    694 	db_ppc4xx_dcrfunc[3] = 0x4e800020;		/* blr */
    695 
    696 	__syncicache((void *)db_ppc4xx_dcrfunc, sizeof(db_ppc4xx_dcrfunc));
    697 	func = (db_expr_t (*)(db_expr_t))(void *)db_ppc4xx_dcrfunc;
    698 
    699 	(*func)(val);
    700 }
    701 
    702 #ifdef USERACC
    703 static void
    704 db_ppc4xx_useracc(db_expr_t addr, bool have_addr, db_expr_t count,
    705     const char *modif)
    706 {
    707 	static paddr_t oldaddr = -1;
    708 	int instr = 0;
    709 	int data;
    710 	extern vaddr_t opc_disasm(vaddr_t loc, int);
    711 
    712 
    713 	if (!have_addr) {
    714 		addr = oldaddr;
    715 	}
    716 	if (addr == -1) {
    717 		db_printf("no address\n");
    718 		return;
    719 	}
    720 	addr &= ~0x3; /* align */
    721 	{
    722 		const char *cp = modif;
    723 		char c;
    724 		while ((c = *cp++) != 0)
    725 			if (c == 'i')
    726 				instr = 1;
    727 	}
    728 	while (count--) {
    729 		if (db_print_position() == 0) {
    730 			/* Always print the address. */
    731 			db_printf("%8.4lx:\t", addr);
    732 		}
    733 		oldaddr=addr;
    734 		copyin((void *)addr, &data, sizeof(data));
    735 		if (instr) {
    736 			opc_disasm(addr, data);
    737 		} else {
    738 			db_printf("%4.4x\n", data);
    739 		}
    740 		addr += 4;
    741 		db_end_line();
    742 	}
    743 
    744 }
    745 #endif
    746 
    747 #endif /* DDB */
    748 
    749 #endif /* PPC_IBM4XX */
    750 
    751 #ifdef PPC_BOOKE
    752 static void
    753 db_ppcbooke_reset(db_expr_t addr, bool have_addr, db_expr_t count,
    754     const char *modif)
    755 {
    756 	printf("Reseting...\n");
    757 	(*cpu_md_ops.md_cpu_reset)();
    758 }
    759 
    760 static void
    761 db_ppcbooke_tf(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
    762 {
    763 	if (!have_addr)
    764 		return;
    765 
    766 	const struct trapframe * const tf = (const struct trapframe *)addr;
    767 
    768 	db_printf("trapframe %p (exc=%x srr0/1=%#lx/%#lx esr/dear=%#x/%#lx)\n",
    769 	    tf, tf->tf_exc, tf->tf_srr0, tf->tf_srr1, tf->tf_esr, tf->tf_dear);
    770 	db_printf("lr =%08lx ctr=%08lx cr =%08x xer=%08x\n",
    771 	    tf->tf_lr, tf->tf_ctr, tf->tf_cr, tf->tf_xer);
    772 	for (u_int r = 0; r < 32; r += 4) {
    773 		db_printf("r%02u=%08lx r%02u=%08lx r%02u=%08lx r%02u=%08lx\n",
    774 		    r+0, tf->tf_fixreg[r+0], r+1, tf->tf_fixreg[r+1],
    775 		    r+2, tf->tf_fixreg[r+2], r+3, tf->tf_fixreg[r+3]);
    776 	}
    777 }
    778 
    779 static void
    780 db_ppcbooke_dumptlb(db_expr_t addr, bool have_addr, db_expr_t count,
    781     const char *modif)
    782 {
    783 	tlb_dump(db_printf);
    784 }
    785 #endif /* PPC_BOOKE */
    786