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