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