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