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 (&regs->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 == NULL) {
 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 != NULL) {
 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 };