Home | History | Annotate | Line # | Download | only in powerpc
db_interface.c revision 1.19
      1 /*	$NetBSD: db_interface.c,v 1.19 2002/05/13 06:05:32 matt Exp $ */
      2 /*	$OpenBSD: db_interface.c,v 1.2 1996/12/28 06:21:50 rahnds Exp $	*/
      3 
      4 #define USERACC
      5 
      6 #include "opt_ddb.h"
      7 #include "opt_kgdb.h"
      8 #include "opt_ppcarch.h"
      9 
     10 #include <sys/param.h>
     11 #include <sys/proc.h>
     12 #include <sys/systm.h>
     13 
     14 #include <dev/cons.h>
     15 
     16 #include <machine/db_machdep.h>
     17 #include <machine/frame.h>
     18 #ifdef PPC_IBM4XX
     19 #include <machine/tlb.h>
     20 #include <powerpc/spr.h>
     21 #include <uvm/uvm_extern.h>
     22 #endif
     23 
     24 #ifdef DDB
     25 #include <ddb/db_sym.h>
     26 #include <ddb/db_command.h>
     27 #include <ddb/db_extern.h>
     28 #include <ddb/db_access.h>
     29 #include <ddb/db_output.h>
     30 #include <ddb/ddbvar.h>
     31 #endif
     32 
     33 #ifdef KGDB
     34 #include <sys/kgdb.h>
     35 #endif
     36 
     37 #include <dev/ofw/openfirm.h>
     38 
     39 int	db_active = 0;
     40 
     41 db_regs_t ddb_regs;
     42 extern label_t *db_recover;
     43 
     44 void ddb_trap(void);				/* Call into trap_subr.S */
     45 int ddb_trap_glue(struct trapframe *);		/* Called from trap_subr.S */
     46 #ifdef PPC_IBM4XX
     47 static void db_ppc4xx_ctx(db_expr_t, int, db_expr_t, char *);
     48 static void db_ppc4xx_pv(db_expr_t, int, db_expr_t, char *);
     49 static void db_ppc4xx_reset(db_expr_t, int, db_expr_t, char *);
     50 static void db_ppc4xx_tf(db_expr_t, int, db_expr_t, char *);
     51 static void db_ppc4xx_dumptlb(db_expr_t, int, db_expr_t, char *);
     52 #ifdef USERACC
     53 static void db_ppc4xx_useracc(db_expr_t, int, db_expr_t, char *);
     54 #endif
     55 #endif /* PPC_IBM4XX */
     56 
     57 #ifdef DDB
     58 void
     59 cpu_Debugger()
     60 {
     61 	ddb_trap();
     62 }
     63 #endif
     64 
     65 int
     66 ddb_trap_glue(frame)
     67 	struct trapframe *frame;
     68 {
     69 	if (!(frame->srr1 & PSL_PR)
     70 	    && (frame->exc == EXC_TRC || frame->exc == EXC_RUNMODETRC
     71 		|| (frame->exc == EXC_PGM
     72 		    && (frame->srr1 & 0x20000))
     73 		|| frame->exc == EXC_BPT)) {
     74 		int type = frame->exc;
     75 		if (type == EXC_PGM && (frame->srr1 & 0x20000)) {
     76 			type = T_BREAKPOINT;
     77 		}
     78 		return kdb_trap(type, frame);
     79 	}
     80 	return 0;
     81 }
     82 
     83 int
     84 kdb_trap(type, v)
     85 	int type;
     86 	void *v;
     87 {
     88 	struct trapframe *frame = v;
     89 
     90 #ifdef DDB
     91 	switch (type) {
     92 	case T_BREAKPOINT:
     93 	case -1:
     94 		break;
     95 	default:
     96 		if (!db_onpanic && db_recover == 0)
     97 			return 0;
     98 		if (db_recover != 0) {
     99 			db_error("Faulted in DDB; continuing...\n");
    100 			/*NOTREACHED*/
    101 		}
    102 	}
    103 #endif
    104 
    105 	/* XXX Should switch to kdb's own stack here. */
    106 
    107 	memcpy(DDB_REGS->r, frame->fixreg, 32 * sizeof(u_int32_t));
    108 	DDB_REGS->iar = frame->srr0;
    109 	DDB_REGS->msr = frame->srr1;
    110 	DDB_REGS->lr = frame->lr;
    111 	DDB_REGS->ctr = frame->ctr;
    112 	DDB_REGS->cr = frame->cr;
    113 	DDB_REGS->xer = frame->xer;
    114 #ifdef PPC_IBM4XX
    115 	DDB_REGS->dear = frame->dear;
    116 	DDB_REGS->esr = frame->esr;
    117 	DDB_REGS->pid = frame->pid;
    118 #endif
    119 
    120 #ifdef DDB
    121 	db_active++;
    122 	cnpollc(1);
    123 	db_trap(type, 0);
    124 	cnpollc(0);
    125 	db_active--;
    126 #elif defined(KGDB)
    127 	if (!kgdb_trap(type, DDB_REGS))
    128 		return 0;
    129 #endif
    130 
    131 	/* KGDB isn't smart about advancing PC if we
    132 	 * take a breakpoint trap after kgdb_active is set.
    133 	 * Therefore, we help out here.
    134 	 */
    135 	if (IS_BREAKPOINT_TRAP(type, 0)) {
    136 		int bkpt;
    137 		db_read_bytes(PC_REGS(DDB_REGS),BKPT_SIZE,(void *)&bkpt);
    138 		if (bkpt== BKPT_INST) {
    139 			PC_REGS(DDB_REGS) += BKPT_SIZE;
    140 		}
    141 	}
    142 
    143 	memcpy(frame->fixreg, DDB_REGS->r, 32 * sizeof(u_int32_t));
    144 	frame->srr0 = DDB_REGS->iar;
    145 	frame->srr1 = DDB_REGS->msr;
    146 	frame->lr = DDB_REGS->lr;
    147 	frame->ctr = DDB_REGS->ctr;
    148 	frame->cr = DDB_REGS->cr;
    149 	frame->xer = DDB_REGS->xer;
    150 #ifdef PPC_IBM4XX
    151 	frame->dear = DDB_REGS->dear;
    152 	frame->esr = DDB_REGS->esr;
    153 	frame->pid = DDB_REGS->pid;
    154 #endif
    155 
    156 	return 1;
    157 }
    158 
    159 #ifdef PPC_IBM4XX
    160 const struct db_command db_machine_command_table[] = {
    161 	{ "ctx",	db_ppc4xx_ctx,		0,	0 },
    162 	{ "pv",		db_ppc4xx_pv,		0,	0 },
    163 	{ "reset",	db_ppc4xx_reset,	0,	0 },
    164 	{ "tf",		db_ppc4xx_tf,	0,	0 },
    165 	{ "tlb",	db_ppc4xx_dumptlb,	0,	0 },
    166 #ifdef USERACC
    167 	{ "user",	db_ppc4xx_useracc,	0,	0 },
    168 #endif
    169 	{ NULL, }
    170 };
    171 
    172 static void
    173 db_ppc4xx_ctx(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
    174 {
    175 	struct proc *p;
    176 
    177 	/* XXX LOCKING XXX */
    178 	for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) {
    179 		if (p->p_stat) {
    180 			db_printf("process %p:", p);
    181 			db_printf("pid:%d pmap:%p ctx:%d %s\n",
    182 				p->p_pid, p->p_vmspace->vm_map.pmap,
    183 				p->p_vmspace->vm_map.pmap->pm_ctx,
    184 				p->p_comm);
    185 		}
    186 	}
    187 	return;
    188 }
    189 
    190 static void
    191 db_ppc4xx_pv(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
    192 {
    193 	struct pv_entry {
    194 		struct pv_entry *pv_next;	/* Linked list of mappings */
    195 		vaddr_t pv_va;			/* virtual address of mapping */
    196 		struct pmap *pv_pm;
    197 	};
    198 	struct pv_entry *pa_to_pv(paddr_t);
    199 	struct pv_entry *pv;
    200 
    201 	if (!have_addr) {
    202 		db_printf("pv: <pa>\n");
    203 		return;
    204 	}
    205 	pv = pa_to_pv(addr);
    206 	db_printf("pv at %p\n", pv);
    207 	while (pv && pv->pv_pm) {
    208 		db_printf("next %p va %p pmap %p\n", pv->pv_next,
    209 			(void *)pv->pv_va, pv->pv_pm);
    210 		pv = pv->pv_next;
    211 	}
    212 }
    213 
    214 static void
    215 db_ppc4xx_reset(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
    216 {
    217 	printf("Reseting...\n");
    218 	ppc4xx_reset();
    219 }
    220 
    221 static void
    222 db_ppc4xx_tf(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
    223 {
    224 	struct trapframe *f;
    225 
    226 
    227 	if (have_addr) {
    228 		f = (struct trapframe *)addr;
    229 
    230 		db_printf("r0-r3:  \t%8.8x %8.8x %8.8x %8.8x\n",
    231 			f->fixreg[0], f->fixreg[1],
    232 			f->fixreg[2], f->fixreg[3]);
    233 		db_printf("r4-r7:  \t%8.8x %8.8x %8.8x %8.8x\n",
    234 			f->fixreg[4], f->fixreg[5],
    235 			f->fixreg[6], f->fixreg[7]);
    236 		db_printf("r8-r11: \t%8.8x %8.8x %8.8x %8.8x\n",
    237 			f->fixreg[8], f->fixreg[9],
    238 			f->fixreg[10], f->fixreg[11]);
    239 		db_printf("r12-r15:\t%8.8x %8.8x %8.8x %8.8x\n",
    240 			f->fixreg[12], f->fixreg[13],
    241 			f->fixreg[14], f->fixreg[15]);
    242 		db_printf("r16-r19:\t%8.8x %8.8x %8.8x %8.8x\n",
    243 			f->fixreg[16], f->fixreg[17],
    244 			f->fixreg[18], f->fixreg[19]);
    245 		db_printf("r20-r23:\t%8.8x %8.8x %8.8x %8.8x\n",
    246 			f->fixreg[20], f->fixreg[21],
    247 			f->fixreg[22], f->fixreg[23]);
    248 		db_printf("r24-r27:\t%8.8x %8.8x %8.8x %8.8x\n",
    249 			f->fixreg[24], f->fixreg[25],
    250 			f->fixreg[26], f->fixreg[27]);
    251 		db_printf("r28-r31:\t%8.8x %8.8x %8.8x %8.8x\n",
    252 			f->fixreg[28], f->fixreg[29],
    253 			f->fixreg[30], f->fixreg[31]);
    254 
    255 		db_printf("lr: %8.8x cr: %8.8x xer: %8.8x ctr: %8.8x\n",
    256 			f->lr, f->cr, f->xer, f->ctr);
    257 		db_printf("srr0(pc): %8.8x srr1(msr): %8.8x "
    258 			"dear: %8.8x esr: %8.8x\n",
    259 			f->srr0, f->srr1, f->dear, f->esr);
    260 		db_printf("exc: %8.8x pid: %8.8x\n",
    261 			f->exc, f->pid);
    262 	}
    263 	return;
    264 }
    265 
    266 static const char *const tlbsizes[] = {
    267 	  "1kB",
    268 	  "4kB",
    269 	 "16kB",
    270 	 "64kB",
    271 	"256kB",
    272 	  "1MB",
    273 	  "4MB",
    274 	 "16MB"
    275 };
    276 
    277 static void
    278 db_ppc4xx_dumptlb(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
    279 {
    280 	int i, zone, tlbsize;
    281 	u_int zpr, pid, opid, msr;
    282 	u_long tlblo, tlbhi, tlbmask;
    283 
    284 	zpr = mfspr(SPR_ZPR);
    285 	for (i = 0; i < NTLB; i++) {
    286 		asm volatile("mfmsr %3;"
    287 			"mfpid %4;"
    288 			"li %0,0;"
    289 			"mtmsr %0;"
    290 			"sync; isync;"
    291 			"tlbre %0,%5,1;"
    292 			"tlbre %1,%5,0;"
    293 			"mfpid %2;"
    294 			"mtpid %4;"
    295 			"mtmsr %3;"
    296 			"sync; isync"
    297 			: "=&r" (tlblo), "=&r" (tlbhi), "=r" (pid),
    298 			"=&r" (msr), "=&r" (opid) : "r" (i));
    299 
    300 		if (strchr(modif, 'v') && !(tlbhi & TLB_VALID))
    301 			continue;
    302 
    303 		tlbsize = (tlbhi & TLB_SIZE_MASK) >> TLB_SIZE_SHFT;
    304 		/* map tlbsize 0 .. 7 to masks for 1kB .. 16MB */
    305 		tlbmask = ~(1 << (tlbsize * 2 + 10)) + 1;
    306 
    307 		if (have_addr && ((tlbhi & tlbmask) != (addr & tlbmask)))
    308 			continue;
    309 
    310 		zone = (tlblo & TLB_ZSEL_MASK) >> TLB_ZSEL_SHFT;
    311 		db_printf("tlb%c%2d", tlbhi & TLB_VALID ? ' ' : '*', i);
    312 		db_printf("  PID %3d EPN 0x%08lx %-5s",
    313 		    pid,
    314 		    tlbhi & tlbmask,
    315 		    tlbsizes[tlbsize]);
    316 		db_printf("  RPN 0x%08lx  ZONE %2d%c  %s %s %c%c%c%c%c %s",
    317 		    tlblo & tlbmask,
    318 		    zone,
    319 		    "NTTA"[(zpr >> ((15 - zone) * 2)) & 3],
    320 		    tlblo & TLB_EX ? "EX" : "  ",
    321 		    tlblo & TLB_WR ? "WR" : "  ",
    322 		    tlblo & TLB_W ? 'W' : ' ',
    323 		    tlblo & TLB_I ? 'I' : ' ',
    324 		    tlblo & TLB_M ? 'M' : ' ',
    325 		    tlblo & TLB_G ? 'G' : ' ',
    326 		    tlbhi & TLB_ENDIAN ? 'E' : ' ',
    327 		    tlbhi & TLB_U0 ? "U0" : "  ");
    328 		db_printf("\n");
    329 	}
    330 }
    331 
    332 #ifdef USERACC
    333 static void
    334 db_ppc4xx_useracc(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
    335 {
    336 	static paddr_t oldaddr = -1;
    337 	int instr = 0;
    338 	int data;
    339 	extern vaddr_t opc_disasm(vaddr_t loc, int);
    340 
    341 
    342 	if (!have_addr) {
    343 		addr = oldaddr;
    344 	}
    345 	if (addr == -1) {
    346 		db_printf("no address\n");
    347 		return;
    348 	}
    349 	addr &= ~0x3; /* align */
    350 	{
    351 		register char c, *cp = modif;
    352 		while ((c = *cp++) != 0)
    353 			if (c == 'i')
    354 				instr = 1;
    355 	}
    356 	while (count--) {
    357 		if (db_print_position() == 0) {
    358 			/* Always print the address. */
    359 			db_printf("%8.4lx:\t", addr);
    360 		}
    361 		oldaddr=addr;
    362 		copyin((void *)addr, &data, sizeof(data));
    363 		if (instr) {
    364 			opc_disasm(addr, data);
    365 		} else {
    366 			db_printf("%4.4x\n", data);
    367 		}
    368 		addr += 4;
    369 		db_end_line();
    370 	}
    371 
    372 }
    373 #endif
    374 
    375 #endif /* PPC_IBM4XX */
    376