Home | History | Annotate | Line # | Download | only in powerpc
      1 /*	$NetBSD: db_interface.c,v 1.65 2026/11/07 22:20:12 thorpej 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.65 2026/11/07 22:20:12 thorpej 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 db_regs_t ddb_regs;
     70 
     71 void ddb_trap(void);				/* Call into trap_subr.S */
     72 int ddb_trap_glue(struct trapframe *);		/* Called from trap_subr.S */
     73 #ifdef DDB
     74 #if defined (PPC_OEA) || defined(PPC_OEA64) || defined (PPC_OEA64_BRIDGE)
     75 static void db_show_bat(db_expr_t, bool, db_expr_t, const char *);
     76 static void db_show_mmu(db_expr_t, bool, db_expr_t, const char *);
     77 #endif /* PPC_OEA || PPC_OEA64 || PPC_OEA64_BRIDGE */
     78 #ifdef PPC_IBM4XX
     79 static void db_ppc4xx_ctx(db_expr_t, bool, db_expr_t, const char *);
     80 static void db_ppc4xx_pv(db_expr_t, bool, db_expr_t, const char *);
     81 static void db_ppc4xx_reset(db_expr_t, bool, db_expr_t, const char *);
     82 static void db_ppc4xx_tf(db_expr_t, bool, db_expr_t, const char *);
     83 static void db_ppc4xx_dumptlb(db_expr_t, bool, db_expr_t, const char *);
     84 static void db_ppc4xx_dcr(db_expr_t, bool, db_expr_t, const char *);
     85 static db_expr_t db_ppc4xx_mfdcr(db_expr_t);
     86 static void db_ppc4xx_mtdcr(db_expr_t, db_expr_t);
     87 #ifdef USERACC
     88 static void db_ppc4xx_useracc(db_expr_t, bool, db_expr_t, const char *);
     89 #endif
     90 #endif /* PPC_IBM4XX */
     91 
     92 #ifdef PPC_BOOKE
     93 static void db_ppcbooke_reset(db_expr_t, bool, db_expr_t, const char *);
     94 static void db_ppcbooke_splhist(db_expr_t, bool, db_expr_t, const char *);
     95 static void db_ppcbooke_tf(db_expr_t, bool, db_expr_t, const char *);
     96 static void db_ppcbooke_dumptlb(db_expr_t, bool, db_expr_t, const char *);
     97 #endif
     98 
     99 #ifdef MULTIPROCESSOR
    100 static void db_mach_cpu(db_expr_t, bool, db_expr_t, const char *);
    101 #endif	/* MULTIPROCESSOR */
    102 
    103 const struct db_command db_machine_command_table[] = {
    104 #if defined (PPC_OEA) || defined(PPC_OEA64) || defined (PPC_OEA64_BRIDGE)
    105 	{ DDB_ADD_CMD("bat",	db_show_bat,		0,
    106 	  "Print BAT register translations", NULL,NULL) },
    107 	{ DDB_ADD_CMD("mmu",	db_show_mmu,		0,
    108 	  "Print MMU registers", NULL,NULL) },
    109 #endif /* PPC_OEA || PPC_OEA64 || PPC_OEA64_BRIDGE */
    110 #ifdef PPC_IBM4XX
    111 	{ DDB_ADD_CMD("ctx",	db_ppc4xx_ctx,		0,
    112 	  "Print process MMU context information", NULL,NULL) },
    113 	{ DDB_ADD_CMD("pv",	db_ppc4xx_pv,		0,
    114 	  "Print PA->VA mapping information",
    115 	  "address",
    116 	  "   address:\tphysical address to look up") },
    117 	{ DDB_ADD_CMD("reset",	db_ppc4xx_reset,	0,
    118 	  "Reset the system ", NULL,NULL) },
    119 	{ DDB_ADD_CMD("tf",	db_ppc4xx_tf,		0,
    120 	  "Display the contents of the trapframe",
    121 	  "address",
    122 	  "   address:\tthe struct trapframe to print") },
    123 	{ DDB_ADD_CMD("tlb",	db_ppc4xx_dumptlb,	0,
    124 	  "Display instruction translation storage buffer information.",
    125 	  NULL,NULL) },
    126 	{ DDB_ADD_CMD("dcr",	db_ppc4xx_dcr,		CS_MORE|CS_SET_DOT,
    127 	  "Set the DCR register",
    128 	  "dcr",
    129 	  "   dcr:\tNew DCR value (between 0x0 and 0x3ff)") },
    130 #ifdef USERACC
    131 	{ DDB_ADD_CMD("user",	db_ppc4xx_useracc,	0,
    132 	   "Display user memory.", "[address][,count]",
    133 	   "   address:\tuserspace address to start\n"
    134 	   "   count:\tnumber of bytes to display") },
    135 #endif
    136 #endif /* PPC_IBM4XX */
    137 #ifdef PPC_BOOKE
    138 	{ DDB_ADD_CMD("reset",	db_ppcbooke_reset,	0,
    139 	  "Reset the system ", NULL,NULL) },
    140 	{ DDB_ADD_CMD("tf",	db_ppcbooke_tf,		0,
    141 	  "Display the contents of the trapframe",
    142 	  "address",
    143 	  "   address:\tthe struct trapframe to print") },
    144 	{ DDB_ADD_CMD("splhist", db_ppcbooke_splhist,	0,
    145 	  "Display the splraise/splx splx",
    146 	  NULL, NULL) },
    147 	{ DDB_ADD_CMD("tlb",	db_ppcbooke_dumptlb,	0,
    148 	  "Display instruction translation storage buffer information.",
    149 	  NULL,NULL) },
    150 #endif /* PPC_BOOKE */
    151 
    152 #ifdef MULTIPROCESSOR
    153 	{ DDB_ADD_CMD("cpu",	db_mach_cpu,	0,
    154 	  "switch to another cpu", "cpu-no", NULL) },
    155 #endif	/* MULTIPROCESSOR */
    156 
    157 	{ DDB_END_CMD },
    158 };
    159 
    160 void
    161 cpu_Debugger(void)
    162 {
    163 #ifdef PPC_BOOKE
    164 	const register_t msr = mfmsr();
    165 	__asm volatile("wrteei 0\n\ttweq\t1,1");
    166 	mtmsr(msr);
    167 	__asm volatile("isync");
    168 #else
    169 	ddb_trap();
    170 #endif
    171 }
    172 #endif /* DDB */
    173 
    174 int
    175 ddb_trap_glue(struct trapframe *tf)
    176 {
    177 #if defined(PPC_IBM4XX) || defined(PPC_BOOKE)
    178 	if ((tf->tf_srr1 & PSL_PR) == 0)
    179 		return kdb_trap(tf->tf_exc, tf);
    180 #else /* PPC_OEA */
    181 	if ((tf->tf_srr1 & PSL_PR) == 0 &&
    182 	    (tf->tf_exc == EXC_TRC ||
    183 	     tf->tf_exc == EXC_RUNMODETRC ||
    184 	     (tf->tf_exc == EXC_PGM && (tf->tf_srr1 & 0x20000)) ||
    185 	     tf->tf_exc == EXC_BPT ||
    186 	     tf->tf_exc == EXC_DSI)) {
    187 		int type = tf->tf_exc;
    188 		if (type == EXC_PGM && (tf->tf_srr1 & 0x20000)) {
    189 			type = T_BREAKPOINT;
    190 		}
    191 		return kdb_trap(type, tf);
    192 	}
    193 #endif
    194 	return 0;
    195 }
    196 
    197 int
    198 kdb_trap(int type, void *v)
    199 {
    200 	struct trapframe *tf = v;
    201 	int rv = 1;
    202 	int s;
    203 
    204 #ifdef DDB
    205 	if (db_recover != 0 && (type != -1 && type != T_BREAKPOINT)) {
    206 		db_error("Faulted in DDB; continuing...\n");
    207 		/* NOTREACHED */
    208 	}
    209 #endif
    210 
    211 	/* XXX Should switch to kdb's own stack here. */
    212 
    213 #ifdef MULTIPROCESSOR
    214 	bool first_in_ddb = false;
    215 	const u_int cpu_me = cpu_number();
    216 	const u_int old_ddb_cpu = atomic_cas_uint(&ddb_cpu, NOCPU, cpu_me);
    217 	if (old_ddb_cpu == NOCPU) {
    218 		first_in_ddb = true;
    219 		cpu_pause_others();
    220 	} else {
    221 		if (old_ddb_cpu != cpu_me) {
    222 			KASSERT(cpu_is_paused(cpu_me));
    223 			cpu_pause(tf);
    224 			return 1;
    225 		}
    226 	}
    227 	KASSERT(!cpu_is_paused(cpu_me));
    228 #endif	/* MULTIPROCESSOR */
    229 
    230 	s = splhigh();
    231 	memcpy(DDB_REGS->r, tf->tf_fixreg, 32 * sizeof(u_int32_t));
    232 	DDB_REGS->iar = tf->tf_srr0;
    233 	DDB_REGS->msr = tf->tf_srr1;
    234 	DDB_REGS->lr = tf->tf_lr;
    235 	DDB_REGS->ctr = tf->tf_ctr;
    236 	DDB_REGS->cr = tf->tf_cr;
    237 	DDB_REGS->xer = tf->tf_xer;
    238 #ifdef PPC_OEA
    239 	DDB_REGS->mq = tf->tf_mq;
    240 #elif defined(PPC_IBM4XX) || defined(PPC_BOOKE)
    241 	DDB_REGS->dear = tf->tf_dear;
    242 	DDB_REGS->esr = tf->tf_esr;
    243 	DDB_REGS->pid = tf->tf_pid;
    244 #endif
    245 
    246 #ifdef DDB
    247 	db_active++;
    248 	cnpollc(true);
    249 	db_trap(type, 0);
    250 	cnpollc(false);
    251 	db_active--;
    252 #endif
    253 #ifdef KGDB
    254 	if (!kgdb_trap(type, DDB_REGS)) {
    255 		rv = 0;
    256 		goto out;
    257 	}
    258 #endif
    259 
    260 	/* KGDB isn't smart about advancing PC if we
    261 	 * take a breakpoint trap after kgdb_active is set.
    262 	 * Therefore, we help out here.
    263 	 */
    264 	if (IS_BREAKPOINT_TRAP(type, 0)) {
    265 		int bkpt;
    266 		db_read_bytes(PC_REGS(DDB_REGS),BKPT_SIZE,(void *)&bkpt);
    267 		if (bkpt== BKPT_INST) {
    268 			PC_REGS(DDB_REGS) += BKPT_SIZE;
    269 		}
    270 	}
    271 
    272 	memcpy(tf->tf_fixreg, DDB_REGS->r, 32 * sizeof(u_int32_t));
    273 	tf->tf_srr0 = DDB_REGS->iar;
    274 	tf->tf_srr1 = DDB_REGS->msr;
    275 	tf->tf_lr = DDB_REGS->lr;
    276 	tf->tf_ctr = DDB_REGS->ctr;
    277 	tf->tf_cr = DDB_REGS->cr;
    278 	tf->tf_xer = DDB_REGS->xer;
    279 #ifdef PPC_OEA
    280 	tf->tf_mq = DDB_REGS->mq;
    281 #endif
    282 #if defined(PPC_IBM4XX) || defined(PPC_BOOKE)
    283 	tf->tf_dear = DDB_REGS->dear;
    284 	tf->tf_esr = DDB_REGS->esr;
    285 	tf->tf_pid = DDB_REGS->pid;
    286 #endif
    287 #ifdef KGDB
    288  out:
    289 #endif	/* KGDB */
    290 	splx(s);
    291 
    292 #ifdef MULTIPROCESSOR
    293 	if (atomic_cas_uint(&ddb_cpu, cpu_me, NOCPU) == cpu_me) {
    294 		cpu_resume_others();
    295 	} else {
    296 		cpu_resume(ddb_cpu);
    297 		if (first_in_ddb)
    298 			cpu_pause(tf);
    299 	}
    300 #endif	/* MULTIPROCESSOR */
    301 
    302 	return rv;
    303 }
    304 
    305 #ifdef DDB
    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 #endif /* DDB */
    495 
    496 #if defined(PPC_IBM4XX) || defined(PPC_BOOKE)
    497 db_addr_t
    498 branch_taken(int inst, db_addr_t pc, db_regs_t *regs)
    499 {
    500 
    501 	if ((inst & M_B ) == I_B || (inst & M_B ) == I_BL) {
    502 		db_expr_t off;
    503 		off = ((db_expr_t)((inst & 0x03fffffc) << 6)) >> 6;
    504 		return (((inst & 0x2) ? 0 : pc) + off);
    505 	}
    506 
    507 	if ((inst & M_BC) == I_BC || (inst & M_BC) == I_BCL) {
    508 		db_expr_t off;
    509 		off = ((db_expr_t)((inst & 0x0000fffc) << 16)) >> 16;
    510 		return (((inst & 0x2) ? 0 : pc) + off);
    511 	}
    512 
    513 	if ((inst & M_RTS) == I_RTS || (inst & M_RTS) == I_BLRL)
    514 		return (regs->lr);
    515 
    516 	if ((inst & M_BCTR) == I_BCTR || (inst & M_BCTR) == I_BCTRL)
    517 		return (regs->ctr);
    518 
    519 	db_printf("branch_taken: can't figure out branch target for 0x%x!\n",
    520 	    inst);
    521 	return (0);
    522 }
    523 #endif /* PPC_IBM4XX || PPC_BOOKE */
    524 
    525 #ifdef DDB
    526 #ifdef PPC_IBM4XX
    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 #ifdef PPC_IBM440
    642 	for (i = 0; i < NTLB; i++) {
    643 		u_long w0, w1, w2, tid;
    644 
    645 		ppc44x_tlb_read(i, &w0, &w1, &w2, &tid);
    646 
    647 		if (strchr(modif, 'v') && !(w0 & TLB44_V))
    648 			continue;
    649 
    650 		tlbsize = (w0 & TLB44_SIZE_MASK) >> TLB44_SIZE_SHFT;
    651 		tlbmask = tlbsize <= TLB44_SIZE_1G ?
    652 		    ~((1UL << (tlbsize * 2 + 10)) - 1) : ~0UL;
    653 
    654 		if (have_addr && ((w0 & tlbmask) != ((u_long)addr & tlbmask)))
    655 			continue;
    656 
    657 		ppc44x_tlb_print(i, w0, w1, w2, tid, db_printf);
    658 	}
    659 	return;
    660 #endif /* PPC_IBM440 */
    661 
    662 	zpr = mfspr(SPR_ZPR);
    663 	for (i = 0; i < NTLB; i++) {
    664 		__asm volatile("mfmsr %3;"
    665 			MFPID(%4)
    666 			"li %0,0;"
    667 			"mtmsr %0;"
    668 			"sync; isync;"
    669 			"tlbrelo %0,%5;"
    670 			"tlbrehi %1,%5;"
    671 			MFPID(%2)
    672 			MTPID(%4)
    673 			"mtmsr %3;"
    674 			"sync; isync"
    675 			: "=&r" (tlblo), "=&r" (tlbhi), "=r" (pid),
    676 			"=&r" (msr), "=&r" (opid) : "r" (i));
    677 
    678 		if (strchr(modif, 'v') && !(tlbhi & TLB_VALID))
    679 			continue;
    680 
    681 		tlbsize = (tlbhi & TLB_SIZE_MASK) >> TLB_SIZE_SHFT;
    682 		/* map tlbsize 0 .. 7 to masks for 1kB .. 16MB */
    683 		tlbmask = ~(1 << (tlbsize * 2 + 10)) + 1;
    684 
    685 		if (have_addr && ((tlbhi & tlbmask) != (addr & tlbmask)))
    686 			continue;
    687 
    688 		zone = (tlblo & TLB_ZSEL_MASK) >> TLB_ZSEL_SHFT;
    689 		db_printf("tlb%c%2d", tlbhi & TLB_VALID ? ' ' : '*', i);
    690 		db_printf("  PID %3d EPN 0x%08lx %-5s",
    691 		    pid,
    692 		    tlbhi & tlbmask,
    693 		    tlbsizes[tlbsize]);
    694 		db_printf("  RPN 0x%08lx  ZONE %2d%c  %s %s %c%c%c%c%c %s",
    695 		    tlblo & tlbmask,
    696 		    zone,
    697 		    "NTTA"[(zpr >> ((15 - zone) * 2)) & 3],
    698 		    tlblo & TLB_EX ? "EX" : "  ",
    699 		    tlblo & TLB_WR ? "WR" : "  ",
    700 		    tlblo & TLB_W ? 'W' : ' ',
    701 		    tlblo & TLB_I ? 'I' : ' ',
    702 		    tlblo & TLB_M ? 'M' : ' ',
    703 		    tlblo & TLB_G ? 'G' : ' ',
    704 		    tlbhi & TLB_ENDIAN ? 'E' : ' ',
    705 		    tlbhi & TLB_U0 ? "U0" : "  ");
    706 		db_printf("\n");
    707 	}
    708 }
    709 
    710 static void
    711 db_ppc4xx_dcr(db_expr_t address, bool have_addr, db_expr_t count,
    712     const char *modif)
    713 {
    714 	db_expr_t new_value;
    715 	db_expr_t addr;
    716 
    717 	if (address < 0 || address > 0x3ff)
    718 		db_error("Invalid DCR address (Valid range is 0x0 - 0x3ff)\n");
    719 
    720 	addr = address;
    721 
    722 	while (db_expression(&new_value)) {
    723 		db_printf("dcr 0x%lx\t\t%s = ", addr,
    724 		    db_num_to_str(db_ppc4xx_mfdcr(addr)));
    725 		db_ppc4xx_mtdcr(addr, new_value);
    726 		db_printf("%s\n", db_num_to_str(db_ppc4xx_mfdcr(addr)));
    727 		addr += 1;
    728 	}
    729 
    730 	if (addr == address) {
    731 		db_next = (db_addr_t)addr + 1;
    732 		db_prev = (db_addr_t)addr;
    733 		db_printf("dcr 0x%lx\t\t%s\n", addr,
    734 		    db_num_to_str(db_ppc4xx_mfdcr(addr)));
    735 	} else {
    736 		db_next = (db_addr_t)addr;
    737 		db_prev = (db_addr_t)addr - 1;
    738 	}
    739 
    740 	db_skip_to_eol();
    741 }
    742 
    743 /*
    744  * XXX Grossness Alert! XXX
    745  *
    746  * Please look away now if you don't like self-modifying code
    747  */
    748 static u_int32_t db_ppc4xx_dcrfunc[4];
    749 
    750 static db_expr_t
    751 db_ppc4xx_mfdcr(db_expr_t reg)
    752 {
    753 	db_expr_t (*func)(void);
    754 
    755 	reg = (((reg & 0x1f) << 5) | ((reg >> 5) & 0x1f)) << 11;
    756 	db_ppc4xx_dcrfunc[0] = 0x7c0004ac;		/* sync */
    757 	db_ppc4xx_dcrfunc[1] = 0x4c00012c;		/* isync */
    758 	db_ppc4xx_dcrfunc[2] = 0x7c600286 | reg;	/* mfdcr reg, r3 */
    759 	db_ppc4xx_dcrfunc[3] = 0x4e800020;		/* blr */
    760 
    761 	__syncicache((void *)db_ppc4xx_dcrfunc, sizeof(db_ppc4xx_dcrfunc));
    762 	func = (db_expr_t (*)(void))(void *)db_ppc4xx_dcrfunc;
    763 
    764 	return ((*func)());
    765 }
    766 
    767 static void
    768 db_ppc4xx_mtdcr(db_expr_t reg, db_expr_t val)
    769 {
    770 	db_expr_t (*func)(db_expr_t);
    771 
    772 	reg = (((reg & 0x1f) << 5) | ((reg >> 5) & 0x1f)) << 11;
    773 	db_ppc4xx_dcrfunc[0] = 0x7c0004ac;		/* sync */
    774 	db_ppc4xx_dcrfunc[1] = 0x4c00012c;		/* isync */
    775 	db_ppc4xx_dcrfunc[2] = 0x7c600386 | reg;	/* mtdcr r3, reg */
    776 	db_ppc4xx_dcrfunc[3] = 0x4e800020;		/* blr */
    777 
    778 	__syncicache((void *)db_ppc4xx_dcrfunc, sizeof(db_ppc4xx_dcrfunc));
    779 	func = (db_expr_t (*)(db_expr_t))(void *)db_ppc4xx_dcrfunc;
    780 
    781 	(*func)(val);
    782 }
    783 
    784 #ifdef USERACC
    785 static void
    786 db_ppc4xx_useracc(db_expr_t addr, bool have_addr, db_expr_t count,
    787     const char *modif)
    788 {
    789 	static paddr_t oldaddr = -1;
    790 	int instr = 0;
    791 	int data;
    792 	extern vaddr_t opc_disasm(vaddr_t loc, int);
    793 
    794 
    795 	if (!have_addr) {
    796 		addr = oldaddr;
    797 	}
    798 	if (addr == -1) {
    799 		db_printf("no address\n");
    800 		return;
    801 	}
    802 	addr &= ~0x3; /* align */
    803 	{
    804 		const char *cp = modif;
    805 		char c;
    806 		while ((c = *cp++) != 0)
    807 			if (c == 'i')
    808 				instr = 1;
    809 	}
    810 	while (count--) {
    811 		if (db_print_position() == 0) {
    812 			/* Always print the address. */
    813 			db_printf("%8.4lx:\t", addr);
    814 		}
    815 		oldaddr=addr;
    816 		copyin((void *)addr, &data, sizeof(data));
    817 		if (instr) {
    818 			opc_disasm(addr, data);
    819 		} else {
    820 			db_printf("%4.4x\n", data);
    821 		}
    822 		addr += 4;
    823 		db_end_line();
    824 	}
    825 
    826 }
    827 #endif
    828 
    829 #endif /* PPC_IBM4XX */
    830 
    831 #ifdef PPC_BOOKE
    832 static void
    833 db_ppcbooke_reset(db_expr_t addr, bool have_addr, db_expr_t count,
    834     const char *modif)
    835 {
    836 	printf("Resetting...\n");
    837 	(*cpu_md_ops.md_cpu_reset)();
    838 }
    839 
    840 static void
    841 db_ppcbooke_splhist(db_expr_t addr, bool have_addr, db_expr_t count,
    842     const char *modif)
    843 {
    844 	dump_splhist(curcpu(), db_printf);
    845 }
    846 
    847 static void
    848 db_ppcbooke_tf(db_expr_t addr, bool have_addr, db_expr_t count,
    849     const char *modif)
    850 {
    851 	if (!have_addr)
    852 		return;
    853 
    854 	dump_trapframe((const struct trapframe *)addr, db_printf);
    855 }
    856 
    857 static void
    858 db_ppcbooke_dumptlb(db_expr_t addr, bool have_addr, db_expr_t count,
    859     const char *modif)
    860 {
    861 	tlb_dump(db_printf);
    862 }
    863 #endif /* PPC_BOOKE */
    864 
    865 #ifdef MULTIPROCESSOR
    866 bool
    867 ddb_running_on_this_cpu_p(void)
    868 {
    869 
    870 	return ddb_cpu == cpu_number();
    871 }
    872 
    873 bool
    874 ddb_running_on_any_cpu_p(void)
    875 {
    876 
    877 	return ddb_cpu != NOCPU;
    878 }
    879 
    880 void
    881 db_resume_others(void)
    882 {
    883 	u_int cpu_me = cpu_number();
    884 
    885 	if (atomic_cas_uint(&ddb_cpu, cpu_me, NOCPU) == cpu_me)
    886 		cpu_resume_others();
    887 }
    888 
    889 static void
    890 db_mach_cpu(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
    891 {
    892 	CPU_INFO_ITERATOR cii;
    893 	struct cpu_info *ci;
    894 	bool found = false;
    895 
    896 	if (!have_addr) {
    897 		cpu_debug_dump();
    898 		return;
    899 	}
    900 
    901 	if (addr < 0) {
    902 		db_printf("%ld: CPU out of range\n", addr);
    903 		return;
    904 	}
    905 	for (CPU_INFO_FOREACH(cii, ci)) {
    906 		if (cpu_index(ci) == addr) {
    907 			found = true;
    908 			break;
    909 		}
    910 	}
    911 	if (!found) {
    912 		db_printf("CPU %ld not configured\n", addr);
    913 		return;
    914 	}
    915 	if (ci != curcpu()) {
    916 		if (!cpu_is_paused(cpu_index(ci))) {
    917 			db_printf("CPU %ld not paused\n", (long)addr);
    918 			return;
    919 		}
    920 		(void)atomic_cas_uint(&ddb_cpu, cpu_number(), cpu_index(ci));
    921 		db_continue_cmd(0, false, 0, "");
    922 	}
    923 }
    924 #endif	/* MULTIPROCESSOR */
    925 #endif /* DDB */
    926