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