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