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