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