1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 * 25 * Copyright 2018 Joyent, Inc. 26 */ 27 28 /* 29 * The debugger/"PROM" interface layer 30 * 31 * It makes more sense on SPARC. In reality, these interfaces deal with three 32 * things: setting break/watchpoints, stepping, and interfacing with the KDI to 33 * set up kmdb's IDT handlers. 34 */ 35 36 #include <kmdb/kmdb_dpi_impl.h> 37 #include <kmdb/kmdb_kdi.h> 38 #include <kmdb/kmdb_umemglue.h> 39 #include <kmdb/kaif.h> 40 #include <kmdb/kmdb_io.h> 41 #include <kmdb/kaif_start.h> 42 #include <mdb/mdb_err.h> 43 #include <mdb/mdb_debug.h> 44 #include <mdb/mdb_isautil.h> 45 #include <mdb/mdb_io_impl.h> 46 #include <mdb/mdb_kreg_impl.h> 47 #include <mdb/mdb.h> 48 49 #include <sys/types.h> 50 #include <sys/bitmap.h> 51 #include <sys/termios.h> 52 #include <sys/kdi_impl.h> 53 #include <sys/sysmacros.h> 54 55 /* 56 * This is the area containing the saved state when we enter 57 * via kmdb's IDT entries. 58 */ 59 kdi_cpusave_t *kaif_cpusave; 60 int kaif_ncpusave; 61 kdi_drreg_t kaif_drreg; 62 63 uint32_t kaif_waptmap; 64 65 int kaif_trap_switch; 66 67 void (*kaif_modchg_cb)(struct modctl *, int); 68 69 enum { 70 M_SYSRET = 0x07, /* after M_ESC */ 71 M_ESC = 0x0f, 72 M_SYSEXIT = 0x35, /* after M_ESC */ 73 M_REX_LO = 0x40, /* first REX prefix */ 74 M_REX_HI = 0x4f, /* last REX prefix */ 75 M_PUSHF = 0x9c, /* pushfl and pushfq */ 76 M_POPF = 0x9d, /* popfl and popfq */ 77 M_INT3 = 0xcc, 78 M_INTX = 0xcd, 79 M_INTO = 0xce, 80 M_IRET = 0xcf, 81 M_CLI = 0xfa, 82 M_STI = 0xfb 83 }; 84 85 #define KAIF_BREAKPOINT_INSTR M_INT3 86 87 #define KAIF_WPPRIV2ID(wp) (int)(uintptr_t)((wp)->wp_priv) 88 89 #ifdef __amd64 90 #define FLAGS_REG_NAME "rflags" 91 #else 92 #define FLAGS_REG_NAME "eflags" 93 #endif 94 95 /* 96 * Called during normal debugger operation and during debugger faults. 97 */ 98 static void 99 kaif_enter_mon(void) 100 { 101 char c; 102 103 for (;;) { 104 mdb_iob_printf(mdb.m_out, 105 "%s: Do you really want to reboot? (y/n) ", 106 mdb.m_pname); 107 mdb_iob_flush(mdb.m_out); 108 mdb_iob_clearlines(mdb.m_out); 109 110 c = kmdb_getchar(); 111 112 if (c == 'n' || c == 'N' || c == CTRL('c')) 113 return; 114 else if (c == 'y' || c == 'Y') { 115 mdb_iob_printf(mdb.m_out, "Rebooting...\n"); 116 117 kmdb_dpi_reboot(); 118 } 119 } 120 } 121 122 static kaif_cpusave_t * 123 kaif_cpuid2save(int cpuid) 124 { 125 kaif_cpusave_t *save; 126 127 if (cpuid == DPI_MASTER_CPUID) 128 return (&kaif_cpusave[kaif_master_cpuid]); 129 130 if (cpuid < 0 || cpuid >= kaif_ncpusave) { 131 (void) set_errno(EINVAL); 132 return (NULL); 133 } 134 135 save = &kaif_cpusave[cpuid]; 136 137 if (save->krs_cpu_state != KAIF_CPU_STATE_MASTER && 138 save->krs_cpu_state != KAIF_CPU_STATE_SLAVE) { 139 (void) set_errno(EINVAL); 140 return (NULL); 141 } 142 143 return (save); 144 } 145 146 static int 147 kaif_get_cpu_state(int cpuid) 148 { 149 kaif_cpusave_t *save; 150 151 if ((save = kaif_cpuid2save(cpuid)) == NULL) 152 return (-1); /* errno is set for us */ 153 154 switch (save->krs_cpu_state) { 155 case KAIF_CPU_STATE_MASTER: 156 return (DPI_CPU_STATE_MASTER); 157 case KAIF_CPU_STATE_SLAVE: 158 return (DPI_CPU_STATE_SLAVE); 159 default: 160 return (set_errno(EINVAL)); 161 } 162 } 163 164 static int 165 kaif_get_master_cpuid(void) 166 { 167 return (kaif_master_cpuid); 168 } 169 170 static mdb_tgt_gregset_t * 171 kaif_kdi_to_gregs(int cpuid) 172 { 173 kaif_cpusave_t *save; 174 175 if ((save = kaif_cpuid2save(cpuid)) == NULL) 176 return (NULL); /* errno is set for us */ 177 178 /* 179 * The saved registers are actually identical to an mdb_tgt_gregset, 180 * so we can directly cast here. 181 */ 182 return ((mdb_tgt_gregset_t *)save->krs_gregs); 183 } 184 185 static const mdb_tgt_gregset_t * 186 kaif_get_gregs(int cpuid) 187 { 188 return (kaif_kdi_to_gregs(cpuid)); 189 } 190 191 typedef struct kaif_reg_synonyms { 192 const char *rs_syn; 193 const char *rs_name; 194 } kaif_reg_synonyms_t; 195 196 static kreg_t * 197 kaif_find_regp(const char *regname) 198 { 199 static const kaif_reg_synonyms_t synonyms[] = { 200 #ifdef __amd64 201 { "pc", "rip" }, 202 { "sp", "rsp" }, 203 { "fp", "rbp" }, 204 #else 205 { "pc", "eip" }, 206 { "sp", "esp" }, 207 { "fp", "ebp" }, 208 #endif 209 { "tt", "trapno" } 210 }; 211 mdb_tgt_gregset_t *regs; 212 int i; 213 214 if ((regs = kaif_kdi_to_gregs(DPI_MASTER_CPUID)) == NULL) 215 return (NULL); 216 217 for (i = 0; i < sizeof (synonyms) / sizeof (synonyms[0]); i++) { 218 if (strcmp(synonyms[i].rs_syn, regname) == 0) 219 regname = synonyms[i].rs_name; 220 } 221 222 for (i = 0; mdb_isa_kregs[i].rd_name != NULL; i++) { 223 const mdb_tgt_regdesc_t *rd = &mdb_isa_kregs[i]; 224 225 if (strcmp(rd->rd_name, regname) == 0) 226 return (®s->kregs[rd->rd_num]); 227 } 228 229 (void) set_errno(ENOENT); 230 return (NULL); 231 } 232 233 /*ARGSUSED*/ 234 static int 235 kaif_get_register(const char *regname, kreg_t *valp) 236 { 237 kreg_t *regp; 238 239 if ((regp = kaif_find_regp(regname)) == NULL) 240 return (-1); 241 242 *valp = *regp; 243 244 return (0); 245 } 246 247 static int 248 kaif_set_register(const char *regname, kreg_t val) 249 { 250 kreg_t *regp; 251 252 if ((regp = kaif_find_regp(regname)) == NULL) 253 return (-1); 254 255 *regp = val; 256 257 return (0); 258 } 259 260 /* 261 * Refuse to single-step or break within any stub that loads a user %cr3 value. 262 * As the KDI traps are not careful to restore such a %cr3, this can all go 263 * wrong, both spectacularly and subtly. 264 */ 265 static boolean_t 266 kaif_toxic_text(uintptr_t addr) 267 { 268 static GElf_Sym toxic_syms[2] = { 0, }; 269 size_t i; 270 271 if (toxic_syms[0].st_name == 0) { 272 if (mdb_tgt_lookup_by_name(mdb.m_target, MDB_TGT_OBJ_EXEC, 273 "tr_iret_user", &toxic_syms[0], NULL) != 0) 274 warn("couldn't find tr_iret_user\n"); 275 if (mdb_tgt_lookup_by_name(mdb.m_target, MDB_TGT_OBJ_EXEC, 276 "tr_mmu_flush_user_range", &toxic_syms[1], NULL) != 0) 277 warn("couldn't find tr_mmu_flush_user_range\n"); 278 } 279 280 for (i = 0; i < ARRAY_SIZE(toxic_syms); i++) { 281 if (addr >= toxic_syms[i].st_value && 282 addr - toxic_syms[i].st_value < toxic_syms[i].st_size) 283 return (B_TRUE); 284 } 285 286 return (B_FALSE); 287 } 288 289 static int 290 kaif_brkpt_arm(uintptr_t addr, mdb_instr_t *instrp) 291 { 292 mdb_instr_t bkpt = KAIF_BREAKPOINT_INSTR; 293 294 if (kaif_toxic_text(addr)) { 295 warn("%a cannot be a breakpoint target\n", addr); 296 return (set_errno(EMDB_TGTNOTSUP)); 297 } 298 299 if (mdb_tgt_vread(mdb.m_target, instrp, sizeof (mdb_instr_t), addr) != 300 sizeof (mdb_instr_t)) 301 return (-1); /* errno is set for us */ 302 303 if (mdb_tgt_vwrite(mdb.m_target, &bkpt, sizeof (mdb_instr_t), addr) != 304 sizeof (mdb_instr_t)) 305 return (-1); /* errno is set for us */ 306 307 return (0); 308 } 309 310 static int 311 kaif_brkpt_disarm(uintptr_t addr, mdb_instr_t instrp) 312 { 313 if (mdb_tgt_vwrite(mdb.m_target, &instrp, sizeof (mdb_instr_t), addr) != 314 sizeof (mdb_instr_t)) 315 return (-1); /* errno is set for us */ 316 317 return (0); 318 } 319 320 /* 321 * Intel watchpoints are even more fun than SPARC ones. The Intel architecture 322 * manuals refer to watchpoints as breakpoints. For consistency with the 323 * terminology used in other portions of kmdb, we will, however, refer to them 324 * as watchpoints. 325 * 326 * Execute, data write, I/O read/write, and data read/write watchpoints are 327 * supported by the hardware. Execute watchpoints must be one byte in length, 328 * and must be placed on the first byte of the instruction to be watched. 329 * Lengths of other watchpoints are more varied. 330 * 331 * Given that we already have a breakpoint facility, and given the restrictions 332 * placed on execute watchpoints, we're going to disallow the creation of 333 * execute watchpoints. The others will be fully supported. See the Debugging 334 * chapter in both the IA32 and AMD64 System Programming books for more details. 335 */ 336 337 #ifdef __amd64 338 #define WAPT_DATA_MAX_SIZE 8 339 #define WAPT_DATA_SIZES_MSG "1, 2, 4, or 8" 340 #else 341 #define WAPT_DATA_MAX_SIZE 4 342 #define WAPT_DATA_SIZES_MSG "1, 2, or 4" 343 #endif 344 345 static int 346 kaif_wapt_validate(kmdb_wapt_t *wp) 347 { 348 if (wp->wp_type == DPI_WAPT_TYPE_IO) { 349 if (wp->wp_wflags != (MDB_TGT_WA_R | MDB_TGT_WA_W)) { 350 warn("I/O port watchpoints must be read/write\n"); 351 return (set_errno(EINVAL)); 352 } 353 354 if (wp->wp_size != 1 && wp->wp_size != 2 && wp->wp_size != 4) { 355 warn("I/O watchpoint size must be 1, 2, or 4 bytes\n"); 356 return (set_errno(EINVAL)); 357 } 358 359 } else if (wp->wp_type == DPI_WAPT_TYPE_PHYS) { 360 warn("physical address watchpoints are not supported on this " 361 "platform\n"); 362 return (set_errno(EMDB_TGTHWNOTSUP)); 363 364 } else { 365 if (wp->wp_wflags != (MDB_TGT_WA_R | MDB_TGT_WA_W) && 366 wp->wp_wflags != MDB_TGT_WA_W) { 367 warn("watchpoints must be read/write or write-only\n"); 368 return (set_errno(EINVAL)); 369 } 370 371 if ((wp->wp_size & -(wp->wp_size)) != wp->wp_size || 372 wp->wp_size > WAPT_DATA_MAX_SIZE) { 373 warn("data watchpoint size must be " WAPT_DATA_SIZES_MSG 374 " bytes\n"); 375 return (set_errno(EINVAL)); 376 } 377 378 } 379 380 if (wp->wp_addr & (wp->wp_size - 1)) { 381 warn("%lu-byte watchpoints must be %lu-byte aligned\n", 382 (ulong_t)wp->wp_size, (ulong_t)wp->wp_size); 383 return (set_errno(EINVAL)); 384 } 385 386 return (0); 387 } 388 389 static int 390 kaif_wapt_reserve(kmdb_wapt_t *wp) 391 { 392 int id; 393 394 for (id = 0; id <= KDI_MAXWPIDX; id++) { 395 if (!BT_TEST(&kaif_waptmap, id)) { 396 /* found one */ 397 BT_SET(&kaif_waptmap, id); 398 wp->wp_priv = (void *)(uintptr_t)id; 399 return (0); 400 } 401 } 402 403 return (set_errno(EMDB_WPTOOMANY)); 404 } 405 406 static void 407 kaif_wapt_release(kmdb_wapt_t *wp) 408 { 409 int id = KAIF_WPPRIV2ID(wp); 410 411 ASSERT(BT_TEST(&kaif_waptmap, id)); 412 BT_CLEAR(&kaif_waptmap, id); 413 } 414 415 /*ARGSUSED*/ 416 static void 417 kaif_wapt_arm(kmdb_wapt_t *wp) 418 { 419 uint_t rw; 420 int hwid = KAIF_WPPRIV2ID(wp); 421 422 ASSERT(BT_TEST(&kaif_waptmap, hwid)); 423 424 if (wp->wp_type == DPI_WAPT_TYPE_IO) 425 rw = KREG_DRCTL_WP_IORW; 426 else if (wp->wp_wflags & MDB_TGT_WA_R) 427 rw = KREG_DRCTL_WP_RW; 428 else if (wp->wp_wflags & MDB_TGT_WA_X) 429 rw = KREG_DRCTL_WP_EXEC; 430 else 431 rw = KREG_DRCTL_WP_WONLY; 432 433 kaif_drreg.dr_addr[hwid] = wp->wp_addr; 434 435 kaif_drreg.dr_ctl &= ~KREG_DRCTL_WP_MASK(hwid); 436 kaif_drreg.dr_ctl |= KREG_DRCTL_WP_LENRW(hwid, wp->wp_size - 1, rw); 437 kaif_drreg.dr_ctl |= KREG_DRCTL_WPEN(hwid); 438 kmdb_kdi_update_drreg(&kaif_drreg); 439 } 440 441 /*ARGSUSED*/ 442 static void 443 kaif_wapt_disarm(kmdb_wapt_t *wp) 444 { 445 int hwid = KAIF_WPPRIV2ID(wp); 446 447 ASSERT(BT_TEST(&kaif_waptmap, hwid)); 448 449 kaif_drreg.dr_addr[hwid] = 0; 450 kaif_drreg.dr_ctl &= ~(KREG_DRCTL_WP_MASK(hwid) | 451 KREG_DRCTL_WPEN_MASK(hwid)); 452 kmdb_kdi_update_drreg(&kaif_drreg); 453 } 454 455 /*ARGSUSED*/ 456 static int 457 kaif_wapt_match(kmdb_wapt_t *wp) 458 { 459 int hwid = KAIF_WPPRIV2ID(wp); 460 uint32_t mask = KREG_DRSTAT_WP_MASK(hwid); 461 int n = 0; 462 int i; 463 464 ASSERT(BT_TEST(&kaif_waptmap, hwid)); 465 466 for (i = 0; i < kaif_ncpusave; i++) 467 n += (kaif_cpusave[i].krs_dr.dr_stat & mask) != 0; 468 469 return (n); 470 } 471 472 static int 473 kaif_step(void) 474 { 475 kreg_t pc, fl, oldfl, newfl, sp; 476 mdb_tgt_addr_t npc; 477 mdb_instr_t instr; 478 int emulated = 0, rchk = 0; 479 size_t pcoff = 0; 480 481 (void) kmdb_dpi_get_register("pc", &pc); 482 483 if (kaif_toxic_text(pc)) { 484 warn("%a cannot be stepped\n", pc); 485 return (set_errno(EMDB_TGTNOTSUP)); 486 } 487 488 if ((npc = mdb_dis_nextins(mdb.m_disasm, mdb.m_target, 489 MDB_TGT_AS_VIRT, pc)) == pc) { 490 warn("failed to decode instruction at %a for step\n", pc); 491 return (set_errno(EINVAL)); 492 } 493 494 /* 495 * Stepping behavior depends on the type of instruction. It does not 496 * depend on the presence of a REX prefix, as the action we take for a 497 * given instruction doesn't currently vary for 32-bit instructions 498 * versus their 64-bit counterparts. 499 */ 500 do { 501 if (mdb_tgt_vread(mdb.m_target, &instr, sizeof (mdb_instr_t), 502 pc + pcoff) != sizeof (mdb_instr_t)) { 503 warn("failed to read at %p for step", 504 (void *)(pc + pcoff)); 505 return (-1); 506 } 507 } while (pcoff++, (instr >= M_REX_LO && instr <= M_REX_HI && !rchk++)); 508 509 switch (instr) { 510 case M_IRET: 511 warn("iret cannot be stepped\n"); 512 return (set_errno(EMDB_TGTNOTSUP)); 513 514 case M_INT3: 515 case M_INTX: 516 case M_INTO: 517 warn("int cannot be stepped\n"); 518 return (set_errno(EMDB_TGTNOTSUP)); 519 520 case M_ESC: 521 if (mdb_tgt_vread(mdb.m_target, &instr, sizeof (mdb_instr_t), 522 pc + pcoff) != sizeof (mdb_instr_t)) { 523 warn("failed to read at %p for step", 524 (void *)(pc + pcoff)); 525 return (-1); 526 } 527 528 switch (instr) { 529 case M_SYSRET: 530 warn("sysret cannot be stepped\n"); 531 return (set_errno(EMDB_TGTNOTSUP)); 532 case M_SYSEXIT: 533 warn("sysexit cannot be stepped\n"); 534 return (set_errno(EMDB_TGTNOTSUP)); 535 } 536 break; 537 538 /* 539 * Some instructions need to be emulated. We need to prevent direct 540 * manipulations of EFLAGS, so we'll emulate cli, sti. pushfl and 541 * popfl also receive special handling, as they manipulate both EFLAGS 542 * and %esp. 543 */ 544 case M_CLI: 545 (void) kmdb_dpi_get_register(FLAGS_REG_NAME, &fl); 546 fl &= ~KREG_EFLAGS_IF_MASK; 547 (void) kmdb_dpi_set_register(FLAGS_REG_NAME, fl); 548 549 emulated = 1; 550 break; 551 552 case M_STI: 553 (void) kmdb_dpi_get_register(FLAGS_REG_NAME, &fl); 554 fl |= (1 << KREG_EFLAGS_IF_SHIFT); 555 (void) kmdb_dpi_set_register(FLAGS_REG_NAME, fl); 556 557 emulated = 1; 558 break; 559 560 case M_POPF: 561 /* 562 * popfl will restore a pushed EFLAGS from the stack, and could 563 * in so doing cause IF to be turned on, if only for a brief 564 * period. To avoid this, we'll secretly replace the stack's 565 * EFLAGS with our decaffeinated brand. We'll then manually 566 * load our EFLAGS copy with the real verion after the step. 567 */ 568 (void) kmdb_dpi_get_register("sp", &sp); 569 (void) kmdb_dpi_get_register(FLAGS_REG_NAME, &fl); 570 571 if (mdb_tgt_vread(mdb.m_target, &newfl, sizeof (kreg_t), 572 sp) != sizeof (kreg_t)) { 573 warn("failed to read " FLAGS_REG_NAME 574 " at %p for popfl step\n", (void *)sp); 575 return (set_errno(EMDB_TGTNOTSUP)); /* XXX ? */ 576 } 577 578 fl = (fl & ~KREG_EFLAGS_IF_MASK) | KREG_EFLAGS_TF_MASK; 579 580 if (mdb_tgt_vwrite(mdb.m_target, &fl, sizeof (kreg_t), 581 sp) != sizeof (kreg_t)) { 582 warn("failed to update " FLAGS_REG_NAME 583 " at %p for popfl step\n", (void *)sp); 584 return (set_errno(EMDB_TGTNOTSUP)); /* XXX ? */ 585 } 586 break; 587 } 588 589 if (emulated) { 590 (void) kmdb_dpi_set_register("pc", npc); 591 return (0); 592 } 593 594 /* Do the step with IF off, and TF (step) on */ 595 (void) kmdb_dpi_get_register(FLAGS_REG_NAME, &oldfl); 596 (void) kmdb_dpi_set_register(FLAGS_REG_NAME, 597 ((oldfl | (1 << KREG_EFLAGS_TF_SHIFT)) & ~KREG_EFLAGS_IF_MASK)); 598 599 kmdb_dpi_resume_master(); /* ... there and back again ... */ 600 601 /* EFLAGS has now changed, and may require tuning */ 602 603 switch (instr) { 604 case M_POPF: 605 /* 606 * Use the EFLAGS we grabbed before the pop - see the pre-step 607 * M_POPFL comment. 608 */ 609 (void) kmdb_dpi_set_register(FLAGS_REG_NAME, newfl); 610 return (0); 611 612 case M_PUSHF: 613 /* 614 * We pushed our modified EFLAGS (with IF and TF turned off) 615 * onto the stack. Replace the pushed version with our 616 * unmodified one. 617 */ 618 (void) kmdb_dpi_get_register("sp", &sp); 619 620 if (mdb_tgt_vwrite(mdb.m_target, &oldfl, sizeof (kreg_t), 621 sp) != sizeof (kreg_t)) { 622 warn("failed to update pushed " FLAGS_REG_NAME 623 " at %p after pushfl step\n", (void *)sp); 624 return (set_errno(EMDB_TGTNOTSUP)); /* XXX ? */ 625 } 626 627 /* Go back to using the EFLAGS we were using before the step */ 628 (void) kmdb_dpi_set_register(FLAGS_REG_NAME, oldfl); 629 return (0); 630 631 default: 632 /* 633 * The stepped instruction may have altered EFLAGS. We only 634 * really care about the value of IF, and we know the stepped 635 * instruction didn't alter it, so we can simply copy the 636 * pre-step value. We'll also need to turn TF back off. 637 */ 638 (void) kmdb_dpi_get_register(FLAGS_REG_NAME, &fl); 639 (void) kmdb_dpi_set_register(FLAGS_REG_NAME, 640 ((fl & ~(KREG_EFLAGS_TF_MASK|KREG_EFLAGS_IF_MASK)) | 641 (oldfl & KREG_EFLAGS_IF_MASK))); 642 return (0); 643 } 644 } 645 646 /*ARGSUSED*/ 647 static uintptr_t 648 kaif_call(uintptr_t funcva, uint_t argc, const uintptr_t argv[]) 649 { 650 return (kaif_invoke(funcva, argc, argv)); 651 } 652 653 static void 654 dump_crumb(kdi_crumb_t *krmp) 655 { 656 kdi_crumb_t krm; 657 658 if (mdb_vread(&krm, sizeof (kdi_crumb_t), (uintptr_t)krmp) != 659 sizeof (kdi_crumb_t)) { 660 warn("failed to read crumb at %p", krmp); 661 return; 662 } 663 664 mdb_printf("state: "); 665 switch (krm.krm_cpu_state) { 666 case KAIF_CPU_STATE_MASTER: 667 mdb_printf("M"); 668 break; 669 case KAIF_CPU_STATE_SLAVE: 670 mdb_printf("S"); 671 break; 672 default: 673 mdb_printf("%d", krm.krm_cpu_state); 674 } 675 676 mdb_printf(" trapno %3d sp %08x flag %d pc %p %A\n", 677 krm.krm_trapno, krm.krm_sp, krm.krm_flag, krm.krm_pc, krm.krm_pc); 678 } 679 680 static void 681 dump_crumbs(kaif_cpusave_t *save) 682 { 683 int i; 684 685 for (i = KDI_NCRUMBS; i > 0; i--) { 686 uint_t idx = (save->krs_curcrumbidx + i) % KDI_NCRUMBS; 687 dump_crumb(&save->krs_crumbs[idx]); 688 } 689 } 690 691 static void 692 kaif_dump_crumbs(uintptr_t addr, int cpuid) 693 { 694 int i; 695 696 if (addr != 0) { 697 /* dump_crumb will protect us against bogus addresses */ 698 dump_crumb((kdi_crumb_t *)addr); 699 700 } else if (cpuid != -1) { 701 if (cpuid < 0 || cpuid >= kaif_ncpusave) 702 return; 703 704 dump_crumbs(&kaif_cpusave[cpuid]); 705 706 } else { 707 for (i = 0; i < kaif_ncpusave; i++) { 708 kaif_cpusave_t *save = &kaif_cpusave[i]; 709 710 if (save->krs_cpu_state == KAIF_CPU_STATE_NONE) 711 continue; 712 713 mdb_printf("%sCPU %d crumbs: (curidx %d)\n", 714 (i == 0 ? "" : "\n"), i, save->krs_curcrumbidx); 715 716 dump_crumbs(save); 717 } 718 } 719 } 720 721 static void 722 kaif_modchg_register(void (*func)(struct modctl *, int)) 723 { 724 kaif_modchg_cb = func; 725 } 726 727 static void 728 kaif_modchg_cancel(void) 729 { 730 ASSERT(kaif_modchg_cb != NULL); 731 732 kaif_modchg_cb = NULL; 733 } 734 735 void 736 kaif_trap_set_debugger(void) 737 { 738 kmdb_kdi_idt_switch(NULL); 739 } 740 741 void 742 kaif_trap_set_saved(kaif_cpusave_t *cpusave) 743 { 744 kmdb_kdi_idt_switch(cpusave); 745 } 746 747 static void 748 kaif_vmready(void) 749 { 750 } 751 752 void 753 kaif_memavail(caddr_t base, size_t len) 754 { 755 int ret; 756 /* 757 * In the unlikely event that someone is stepping through this routine, 758 * we need to make sure that the KDI knows about the new range before 759 * umem gets it. That way the entry code can recognize stacks 760 * allocated from the new region. 761 */ 762 kmdb_kdi_memrange_add(base, len); 763 ret = mdb_umem_add(base, len); 764 ASSERT(ret == 0); 765 } 766 767 void 768 kaif_mod_loaded(struct modctl *modp) 769 { 770 if (kaif_modchg_cb != NULL) 771 kaif_modchg_cb(modp, 1); 772 } 773 774 void 775 kaif_mod_unloading(struct modctl *modp) 776 { 777 if (kaif_modchg_cb != NULL) 778 kaif_modchg_cb(modp, 0); 779 } 780 781 void 782 kaif_handle_fault(greg_t trapno, greg_t pc, greg_t sp, int cpuid) 783 { 784 kmdb_dpi_handle_fault((kreg_t)trapno, (kreg_t)pc, 785 (kreg_t)sp, cpuid); 786 } 787 788 static kdi_debugvec_t kaif_dvec = { 789 NULL, /* dv_kctl_vmready */ 790 NULL, /* dv_kctl_memavail */ 791 NULL, /* dv_kctl_modavail */ 792 NULL, /* dv_kctl_thravail */ 793 kaif_vmready, 794 kaif_memavail, 795 kaif_mod_loaded, 796 kaif_mod_unloading, 797 kaif_handle_fault 798 }; 799 800 void 801 kaif_kdi_entry(kdi_cpusave_t *cpusave) 802 { 803 int ret = kaif_main_loop(cpusave); 804 ASSERT(ret == KAIF_CPU_CMD_RESUME || 805 ret == KAIF_CPU_CMD_RESUME_MASTER); 806 } 807 808 /*ARGSUSED*/ 809 void 810 kaif_activate(kdi_debugvec_t **dvecp, uint_t flags) 811 { 812 kmdb_kdi_activate(kaif_kdi_entry, kaif_cpusave, kaif_ncpusave); 813 *dvecp = &kaif_dvec; 814 } 815 816 static int 817 kaif_init(kmdb_auxv_t *kav) 818 { 819 /* Allocate the per-CPU save areas */ 820 kaif_cpusave = mdb_zalloc(sizeof (kaif_cpusave_t) * kav->kav_ncpu, 821 UM_SLEEP); 822 kaif_ncpusave = kav->kav_ncpu; 823 824 kaif_modchg_cb = NULL; 825 826 kaif_waptmap = 0; 827 828 kaif_trap_switch = (kav->kav_flags & KMDB_AUXV_FL_NOTRPSWTCH) == 0; 829 830 return (0); 831 } 832 833 dpi_ops_t kmdb_dpi_ops = { 834 kaif_init, 835 kaif_activate, 836 kmdb_kdi_deactivate, 837 kaif_enter_mon, 838 kaif_modchg_register, 839 kaif_modchg_cancel, 840 kaif_get_cpu_state, 841 kaif_get_master_cpuid, 842 kaif_get_gregs, 843 kaif_get_register, 844 kaif_set_register, 845 kaif_brkpt_arm, 846 kaif_brkpt_disarm, 847 kaif_wapt_validate, 848 kaif_wapt_reserve, 849 kaif_wapt_release, 850 kaif_wapt_arm, 851 kaif_wapt_disarm, 852 kaif_wapt_match, 853 kaif_step, 854 kaif_call, 855 kaif_dump_crumbs, 856 }; 857