Home | History | Annotate | Line # | Download | only in powerpc
db_interface.c revision 1.54
      1 /*	$NetBSD: db_interface.c,v 1.54 2020/07/06 09:34:18 rin 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.54 2020/07/06 09:34:18 rin 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 <machine/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_ADD_CMD(NULL,	NULL,			0,
    160 	  NULL,NULL,NULL) }
    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 #elif defined(KGDB)
    256 	if (!kgdb_trap(type, DDB_REGS)) {
    257 		rv = 0;
    258 		goto out;
    259 	}
    260 #endif
    261 
    262 	/* KGDB isn't smart about advancing PC if we
    263 	 * take a breakpoint trap after kgdb_active is set.
    264 	 * Therefore, we help out here.
    265 	 */
    266 	if (IS_BREAKPOINT_TRAP(type, 0)) {
    267 		int bkpt;
    268 		db_read_bytes(PC_REGS(DDB_REGS),BKPT_SIZE,(void *)&bkpt);
    269 		if (bkpt== BKPT_INST) {
    270 			PC_REGS(DDB_REGS) += BKPT_SIZE;
    271 		}
    272 	}
    273 
    274 	memcpy(tf->tf_fixreg, DDB_REGS->r, 32 * sizeof(u_int32_t));
    275 	tf->tf_srr0 = DDB_REGS->iar;
    276 	tf->tf_srr1 = DDB_REGS->msr;
    277 	tf->tf_lr = DDB_REGS->lr;
    278 	tf->tf_ctr = DDB_REGS->ctr;
    279 	tf->tf_cr = DDB_REGS->cr;
    280 	tf->tf_xer = DDB_REGS->xer;
    281 #ifdef PPC_OEA
    282 	tf->tf_mq = DDB_REGS->mq;
    283 #endif
    284 #if defined(PPC_IBM4XX) || defined(PPC_BOOKE)
    285 	tf->tf_dear = DDB_REGS->dear;
    286 	tf->tf_esr = DDB_REGS->esr;
    287 	tf->tf_pid = DDB_REGS->pid;
    288 #endif
    289 #ifdef KGDB
    290  out:
    291 #endif	/* KGDB */
    292 	splx(s);
    293 
    294 #ifdef MULTIPROCESSOR
    295 	if (atomic_cas_uint(&ddb_cpu, cpu_me, NOCPU) == cpu_me) {
    296 		cpu_resume_others();
    297 	} else {
    298 		cpu_resume(ddb_cpu);
    299 		if (first_in_ddb)
    300 			cpu_pause(tf);
    301 	}
    302 #endif	/* MULTIPROCESSOR */
    303 
    304 	return rv;
    305 }
    306 
    307 #if defined (PPC_OEA) || defined(PPC_OEA64) || defined (PPC_OEA64_BRIDGE)
    308 static void
    309 print_battranslation(struct bat *bat, unsigned int blidx)
    310 {
    311 	static const char batsizes[][6] = {
    312 		"128KB",
    313 		"256KB",
    314 		"512KB",
    315 		"1MB",
    316 		"2MB",
    317 		"4MB",
    318 		"8MB",
    319 		"16MB",
    320 		"32MB",
    321 		"64MB",
    322 		"128MB",
    323 		"256MB",
    324 		"512MB",
    325 		"1GB",
    326 		"2GB",
    327 		"4GB",
    328 	};
    329 	vsize_t len;
    330 
    331 	len = (0x20000L << blidx) - 1;
    332 	db_printf("\t%08lx %08lx %5s: 0x%08lx..0x%08lx -> 0x%08lx physical\n",
    333 	    bat->batu, bat->batl, batsizes[blidx], bat->batu & ~len,
    334 	    (bat->batu & ~len) + len, bat->batl & ~len);
    335 }
    336 
    337 static void
    338 print_batmodes(register_t super, register_t user, register_t pp)
    339 {
    340 	static const char *const accessmodes[] = {
    341 		"none",
    342 		"ro soft",
    343 		"read/write",
    344 		"read only"
    345 	};
    346 
    347 	db_printf("\tvalid: %c%c  access: %-10s  memory:",
    348 	    super ? 'S' : '-', user ? 'U' : '-', accessmodes[pp]);
    349 }
    350 
    351 static void
    352 print_wimg(register_t wimg)
    353 {
    354 	if (wimg & BAT_W)
    355 		db_printf(" wrthrough");
    356 	if (wimg & BAT_I)
    357 		db_printf(" nocache");
    358 	if (wimg & BAT_M)
    359 		db_printf(" coherent");
    360 	if (wimg & BAT_G)
    361 		db_printf(" guard");
    362 }
    363 
    364 static void
    365 print_bat(struct bat *bat)
    366 {
    367 	if ((bat->batu & BAT_V) == 0) {
    368 		db_printf("\tdisabled\n\n");
    369 		return;
    370 	}
    371 	print_battranslation(bat,
    372 	    30 - __builtin_clz((bat->batu & (BAT_XBL|BAT_BL))|2));
    373 	print_batmodes(bat->batu & BAT_Vs, bat->batu & BAT_Vu,
    374 	    bat->batl & BAT_PP);
    375 	print_wimg(bat->batl & BAT_WIMG);
    376 	db_printf("\n");
    377 }
    378 
    379 #ifdef PPC_OEA601
    380 static void
    381 print_bat601(struct bat *bat)
    382 {
    383 	if ((bat->batl & BAT601_V) == 0) {
    384 		db_printf("\tdisabled\n\n");
    385 		return;
    386 	}
    387 	print_battranslation(bat, 32 - __builtin_clz(bat->batl & BAT601_BSM));
    388 	print_batmodes(bat->batu & BAT601_Ks, bat->batu & BAT601_Ku,
    389 	    bat->batu & BAT601_PP);
    390 	print_wimg(bat->batu & (BAT601_W | BAT601_I | BAT601_M));
    391 	db_printf("\n");
    392 }
    393 #endif
    394 
    395 static void
    396 db_show_bat(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
    397 {
    398 	struct bat ibat[8];
    399 	struct bat dbat[8];
    400 	unsigned int cpuvers;
    401 	u_int i;
    402 	u_int maxbat = (oeacpufeat & OEACPU_HIGHBAT) ? 8 : 4;
    403 
    404 	if (oeacpufeat & OEACPU_NOBAT)
    405 		return;
    406 
    407 	cpuvers = mfpvr() >> 16;
    408 
    409 	ibat[0].batu = mfspr(SPR_IBAT0U);
    410 	ibat[0].batl = mfspr(SPR_IBAT0L);
    411 	ibat[1].batu = mfspr(SPR_IBAT1U);
    412 	ibat[1].batl = mfspr(SPR_IBAT1L);
    413 	ibat[2].batu = mfspr(SPR_IBAT2U);
    414 	ibat[2].batl = mfspr(SPR_IBAT2L);
    415 	ibat[3].batu = mfspr(SPR_IBAT3U);
    416 	ibat[3].batl = mfspr(SPR_IBAT3L);
    417 	if (maxbat == 8) {
    418 		ibat[4].batu = mfspr(SPR_IBAT4U);
    419 		ibat[4].batl = mfspr(SPR_IBAT4L);
    420 		ibat[5].batu = mfspr(SPR_IBAT5U);
    421 		ibat[5].batl = mfspr(SPR_IBAT5L);
    422 		ibat[6].batu = mfspr(SPR_IBAT6U);
    423 		ibat[6].batl = mfspr(SPR_IBAT6L);
    424 		ibat[7].batu = mfspr(SPR_IBAT7U);
    425 		ibat[7].batl = mfspr(SPR_IBAT7L);
    426 	}
    427 
    428 	if (cpuvers != MPC601) {
    429 		/* The 601 has only four unified BATs */
    430 		dbat[0].batu = mfspr(SPR_DBAT0U);
    431 		dbat[0].batl = mfspr(SPR_DBAT0L);
    432 		dbat[1].batu = mfspr(SPR_DBAT1U);
    433 		dbat[1].batl = mfspr(SPR_DBAT1L);
    434 		dbat[2].batu = mfspr(SPR_DBAT2U);
    435 		dbat[2].batl = mfspr(SPR_DBAT2L);
    436 		dbat[3].batu = mfspr(SPR_DBAT3U);
    437 		dbat[3].batl = mfspr(SPR_DBAT3L);
    438 		if (maxbat == 8) {
    439 			dbat[4].batu = mfspr(SPR_DBAT4U);
    440 			dbat[4].batl = mfspr(SPR_DBAT4L);
    441 			dbat[5].batu = mfspr(SPR_DBAT5U);
    442 			dbat[5].batl = mfspr(SPR_DBAT5L);
    443 			dbat[6].batu = mfspr(SPR_DBAT6U);
    444 			dbat[6].batl = mfspr(SPR_DBAT6L);
    445 			dbat[7].batu = mfspr(SPR_DBAT7U);
    446 			dbat[7].batl = mfspr(SPR_DBAT7L);
    447 		}
    448 	}
    449 
    450 	for (i = 0; i < maxbat; i++) {
    451 #ifdef PPC_OEA601
    452 		if (cpuvers == MPC601) {
    453 			db_printf("bat[%u]:\n", i);
    454 			print_bat601(&ibat[i]);
    455 		} else
    456 #endif
    457 		{
    458 			db_printf("ibat[%u]:\n", i);
    459 			print_bat(&ibat[i]);
    460 			db_printf("dbat[%u]:\n", i);
    461 			print_bat(&dbat[i]);
    462 		}
    463 	}
    464 }
    465 
    466 static void
    467 db_show_mmu(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
    468 {
    469 	paddr_t sdr1;
    470 
    471 	__asm volatile ("mfsdr1 %0" : "=r"(sdr1));
    472 	db_printf("sdr1\t\t0x%08lx\n", sdr1);
    473 
    474 #if defined(PPC_OEA64) || defined(PPC_OEA64_BRIDGE)
    475 	if (oeacpufeat & (OEACPU_64|OEACPU_64_BRIDGE)) {
    476 		__asm volatile ("mfasr %0" : "=r"(sdr1));
    477 		db_printf("asr\t\t0x%08lx\n", sdr1);
    478 	}
    479 #endif
    480 #if defined(PPC_OEA) || defined(PPC_OEA64_BRIDGE)
    481 	if ((oeacpufeat & OEACPU_64) == 0) {
    482 		vaddr_t saddr = 0;
    483 		for (u_int i = 0; i <= 0xf; i++) {
    484 			register_t sr;
    485 			if ((i & 3) == 0)
    486 				db_printf("sr%d-%d\t\t", i, i+3);
    487 			__asm volatile ("mfsrin %0,%1" : "=r"(sr) : "r"(saddr));
    488 			db_printf("0x%08lx   %c", sr, (i&3) == 3 ? '\n' : ' ');
    489 			saddr += 1 << ADDR_SR_SHFT;
    490 		}
    491 	}
    492 #endif
    493 }
    494 #endif /* PPC_OEA || PPC_OEA64 || PPC_OEA64_BRIDGE */
    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 
    526 #ifdef PPC_IBM4XX
    527 #ifdef DDB
    528 static void
    529 db_ppc4xx_ctx(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
    530 {
    531 	struct proc *p;
    532 
    533 	/* XXX LOCKING XXX */
    534 	for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) {
    535 		if (p->p_stat) {
    536 			db_printf("process %p:", p);
    537 			db_printf("pid:%d pmap:%p ctx:%d %s\n",
    538 				p->p_pid, p->p_vmspace->vm_map.pmap,
    539 				p->p_vmspace->vm_map.pmap->pm_ctx,
    540 				p->p_comm);
    541 		}
    542 	}
    543 	return;
    544 }
    545 
    546 static void
    547 db_ppc4xx_pv(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
    548 {
    549 	struct pv_entry {
    550 		struct pv_entry *pv_next;	/* Linked list of mappings */
    551 		vaddr_t pv_va;			/* virtual address of mapping */
    552 		struct pmap *pv_pm;
    553 	};
    554 	struct pv_entry *pa_to_pv(paddr_t);
    555 	struct pv_entry *pv;
    556 
    557 	if (!have_addr) {
    558 		db_printf("pv: <pa>\n");
    559 		return;
    560 	}
    561 	pv = pa_to_pv(addr);
    562 	db_printf("pv at %p\n", pv);
    563 	while (pv && pv->pv_pm) {
    564 		db_printf("next %p va %p pmap %p\n", pv->pv_next,
    565 			(void *)pv->pv_va, pv->pv_pm);
    566 		pv = pv->pv_next;
    567 	}
    568 }
    569 
    570 static void
    571 db_ppc4xx_reset(db_expr_t addr, bool have_addr, db_expr_t count,
    572     const char *modif)
    573 {
    574 	printf("Reseting...\n");
    575 	ppc4xx_reset();
    576 }
    577 
    578 static void
    579 db_ppc4xx_tf(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
    580 {
    581 	struct trapframe *tf;
    582 
    583 
    584 	if (have_addr) {
    585 		tf = (struct trapframe *)addr;
    586 
    587 		db_printf("r0-r3:  \t%8.8lx %8.8lx %8.8lx %8.8lx\n",
    588 			tf->tf_fixreg[0], tf->tf_fixreg[1],
    589 			tf->tf_fixreg[2], tf->tf_fixreg[3]);
    590 		db_printf("r4-r7:  \t%8.8lx %8.8lx %8.8lx %8.8lx\n",
    591 			tf->tf_fixreg[4], tf->tf_fixreg[5],
    592 			tf->tf_fixreg[6], tf->tf_fixreg[7]);
    593 		db_printf("r8-r11: \t%8.8lx %8.8lx %8.8lx %8.8lx\n",
    594 			tf->tf_fixreg[8], tf->tf_fixreg[9],
    595 			tf->tf_fixreg[10], tf->tf_fixreg[11]);
    596 		db_printf("r12-r15:\t%8.8lx %8.8lx %8.8lx %8.8lx\n",
    597 			tf->tf_fixreg[12], tf->tf_fixreg[13],
    598 			tf->tf_fixreg[14], tf->tf_fixreg[15]);
    599 		db_printf("r16-r19:\t%8.8lx %8.8lx %8.8lx %8.8lx\n",
    600 			tf->tf_fixreg[16], tf->tf_fixreg[17],
    601 			tf->tf_fixreg[18], tf->tf_fixreg[19]);
    602 		db_printf("r20-r23:\t%8.8lx %8.8lx %8.8lx %8.8lx\n",
    603 			tf->tf_fixreg[20], tf->tf_fixreg[21],
    604 			tf->tf_fixreg[22], tf->tf_fixreg[23]);
    605 		db_printf("r24-r27:\t%8.8lx %8.8lx %8.8lx %8.8lx\n",
    606 			tf->tf_fixreg[24], tf->tf_fixreg[25],
    607 			tf->tf_fixreg[26], tf->tf_fixreg[27]);
    608 		db_printf("r28-r31:\t%8.8lx %8.8lx %8.8lx %8.8lx\n",
    609 			tf->tf_fixreg[28], tf->tf_fixreg[29],
    610 			tf->tf_fixreg[30], tf->tf_fixreg[31]);
    611 
    612 		db_printf("lr: %8.8lx cr: %8.8x xer: %8.8x ctr: %8.8lx\n",
    613 			tf->tf_lr, tf->tf_cr, tf->tf_xer, tf->tf_ctr);
    614 		db_printf("srr0(pc): %8.8lx srr1(msr): %8.8lx "
    615 			"dear: %8.8lx esr: %8.8x\n",
    616 			tf->tf_srr0, tf->tf_srr1, tf->tf_dear, tf->tf_esr);
    617 		db_printf("exc: %8.8x pid: %8.8x\n",
    618 			tf->tf_exc, tf->tf_pid);
    619 	}
    620 	return;
    621 }
    622 
    623 static const char *const tlbsizes[] = {
    624 	  "1kB",
    625 	  "4kB",
    626 	 "16kB",
    627 	 "64kB",
    628 	"256kB",
    629 	  "1MB",
    630 	  "4MB",
    631 	 "16MB"
    632 };
    633 
    634 static void
    635 db_ppc4xx_dumptlb(db_expr_t addr, bool have_addr, db_expr_t count,
    636     const char *modif)
    637 {
    638 	int i, zone, tlbsize;
    639 	u_int zpr, pid, opid, msr;
    640 	u_long tlblo, tlbhi, tlbmask;
    641 
    642 	zpr = mfspr(SPR_ZPR);
    643 	for (i = 0; i < NTLB; i++) {
    644 		__asm volatile("mfmsr %3;"
    645 			"mfpid %4;"
    646 			"li %0,0;"
    647 			"mtmsr %0;"
    648 			"sync; isync;"
    649 			"tlbrelo %0,%5;"
    650 			"tlbrehi %1,%5;"
    651 			"mfpid %2;"
    652 			"mtpid %4;"
    653 			"mtmsr %3;"
    654 			"sync; isync"
    655 			: "=&r" (tlblo), "=&r" (tlbhi), "=r" (pid),
    656 			"=&r" (msr), "=&r" (opid) : "r" (i));
    657 
    658 		if (strchr(modif, 'v') && !(tlbhi & TLB_VALID))
    659 			continue;
    660 
    661 		tlbsize = (tlbhi & TLB_SIZE_MASK) >> TLB_SIZE_SHFT;
    662 		/* map tlbsize 0 .. 7 to masks for 1kB .. 16MB */
    663 		tlbmask = ~(1 << (tlbsize * 2 + 10)) + 1;
    664 
    665 		if (have_addr && ((tlbhi & tlbmask) != (addr & tlbmask)))
    666 			continue;
    667 
    668 		zone = (tlblo & TLB_ZSEL_MASK) >> TLB_ZSEL_SHFT;
    669 		db_printf("tlb%c%2d", tlbhi & TLB_VALID ? ' ' : '*', i);
    670 		db_printf("  PID %3d EPN 0x%08lx %-5s",
    671 		    pid,
    672 		    tlbhi & tlbmask,
    673 		    tlbsizes[tlbsize]);
    674 		db_printf("  RPN 0x%08lx  ZONE %2d%c  %s %s %c%c%c%c%c %s",
    675 		    tlblo & tlbmask,
    676 		    zone,
    677 		    "NTTA"[(zpr >> ((15 - zone) * 2)) & 3],
    678 		    tlblo & TLB_EX ? "EX" : "  ",
    679 		    tlblo & TLB_WR ? "WR" : "  ",
    680 		    tlblo & TLB_W ? 'W' : ' ',
    681 		    tlblo & TLB_I ? 'I' : ' ',
    682 		    tlblo & TLB_M ? 'M' : ' ',
    683 		    tlblo & TLB_G ? 'G' : ' ',
    684 		    tlbhi & TLB_ENDIAN ? 'E' : ' ',
    685 		    tlbhi & TLB_U0 ? "U0" : "  ");
    686 		db_printf("\n");
    687 	}
    688 }
    689 
    690 static void
    691 db_ppc4xx_dcr(db_expr_t address, bool have_addr, db_expr_t count,
    692     const char *modif)
    693 {
    694 	db_expr_t new_value;
    695 	db_expr_t addr;
    696 
    697 	if (address < 0 || address > 0x3ff)
    698 		db_error("Invalid DCR address (Valid range is 0x0 - 0x3ff)\n");
    699 
    700 	addr = address;
    701 
    702 	while (db_expression(&new_value)) {
    703 		db_printf("dcr 0x%lx\t\t%s = ", addr,
    704 		    db_num_to_str(db_ppc4xx_mfdcr(addr)));
    705 		db_ppc4xx_mtdcr(addr, new_value);
    706 		db_printf("%s\n", db_num_to_str(db_ppc4xx_mfdcr(addr)));
    707 		addr += 1;
    708 	}
    709 
    710 	if (addr == address) {
    711 		db_next = (db_addr_t)addr + 1;
    712 		db_prev = (db_addr_t)addr;
    713 		db_printf("dcr 0x%lx\t\t%s\n", addr,
    714 		    db_num_to_str(db_ppc4xx_mfdcr(addr)));
    715 	} else {
    716 		db_next = (db_addr_t)addr;
    717 		db_prev = (db_addr_t)addr - 1;
    718 	}
    719 
    720 	db_skip_to_eol();
    721 }
    722 
    723 /*
    724  * XXX Grossness Alert! XXX
    725  *
    726  * Please look away now if you don't like self-modifying code
    727  */
    728 static u_int32_t db_ppc4xx_dcrfunc[4];
    729 
    730 static db_expr_t
    731 db_ppc4xx_mfdcr(db_expr_t reg)
    732 {
    733 	db_expr_t (*func)(void);
    734 
    735 	reg = (((reg & 0x1f) << 5) | ((reg >> 5) & 0x1f)) << 11;
    736 	db_ppc4xx_dcrfunc[0] = 0x7c0004ac;		/* sync */
    737 	db_ppc4xx_dcrfunc[1] = 0x4c00012c;		/* isync */
    738 	db_ppc4xx_dcrfunc[2] = 0x7c600286 | reg;	/* mfdcr reg, r3 */
    739 	db_ppc4xx_dcrfunc[3] = 0x4e800020;		/* blr */
    740 
    741 	__syncicache((void *)db_ppc4xx_dcrfunc, sizeof(db_ppc4xx_dcrfunc));
    742 	func = (db_expr_t (*)(void))(void *)db_ppc4xx_dcrfunc;
    743 
    744 	return ((*func)());
    745 }
    746 
    747 static void
    748 db_ppc4xx_mtdcr(db_expr_t reg, db_expr_t val)
    749 {
    750 	db_expr_t (*func)(db_expr_t);
    751 
    752 	reg = (((reg & 0x1f) << 5) | ((reg >> 5) & 0x1f)) << 11;
    753 	db_ppc4xx_dcrfunc[0] = 0x7c0004ac;		/* sync */
    754 	db_ppc4xx_dcrfunc[1] = 0x4c00012c;		/* isync */
    755 	db_ppc4xx_dcrfunc[2] = 0x7c600386 | reg;	/* mtdcr r3, reg */
    756 	db_ppc4xx_dcrfunc[3] = 0x4e800020;		/* blr */
    757 
    758 	__syncicache((void *)db_ppc4xx_dcrfunc, sizeof(db_ppc4xx_dcrfunc));
    759 	func = (db_expr_t (*)(db_expr_t))(void *)db_ppc4xx_dcrfunc;
    760 
    761 	(*func)(val);
    762 }
    763 
    764 #ifdef USERACC
    765 static void
    766 db_ppc4xx_useracc(db_expr_t addr, bool have_addr, db_expr_t count,
    767     const char *modif)
    768 {
    769 	static paddr_t oldaddr = -1;
    770 	int instr = 0;
    771 	int data;
    772 	extern vaddr_t opc_disasm(vaddr_t loc, int);
    773 
    774 
    775 	if (!have_addr) {
    776 		addr = oldaddr;
    777 	}
    778 	if (addr == -1) {
    779 		db_printf("no address\n");
    780 		return;
    781 	}
    782 	addr &= ~0x3; /* align */
    783 	{
    784 		const char *cp = modif;
    785 		char c;
    786 		while ((c = *cp++) != 0)
    787 			if (c == 'i')
    788 				instr = 1;
    789 	}
    790 	while (count--) {
    791 		if (db_print_position() == 0) {
    792 			/* Always print the address. */
    793 			db_printf("%8.4lx:\t", addr);
    794 		}
    795 		oldaddr=addr;
    796 		copyin((void *)addr, &data, sizeof(data));
    797 		if (instr) {
    798 			opc_disasm(addr, data);
    799 		} else {
    800 			db_printf("%4.4x\n", data);
    801 		}
    802 		addr += 4;
    803 		db_end_line();
    804 	}
    805 
    806 }
    807 #endif
    808 
    809 #endif /* DDB */
    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("Reseting...\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