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