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