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  * isa-dependent portions of the kmdb target
  30  */
  31 
  32 #include <kmdb/kvm.h>
  33 #include <kmdb/kmdb_kdi.h>
  34 #include <kmdb/kmdb_asmutil.h>
  35 #include <mdb/mdb_debug.h>
  36 #include <mdb/mdb_err.h>
  37 #include <mdb/mdb_list.h>
  38 #include <mdb/mdb_target_impl.h>
  39 #include <mdb/mdb_isautil.h>
  40 #include <mdb/mdb_kreg_impl.h>
  41 #include <mdb/mdb.h>
  42 
  43 #include <sys/types.h>
  44 #include <sys/frame.h>
  45 #include <sys/trap.h>
  46 #include <sys/bitmap.h>
  47 #include <sys/pci_impl.h>
  48 
  49 /* Higher than the highest trap number for which we have a defined specifier */
  50 #define KMT_MAXTRAPNO   0x20
  51 
  52 #define IOPORTLIMIT     0xffff  /* XXX find a new home for this */
  53 
  54 const char *
  55 kmt_def_dismode(void)
  56 {
  57 #ifdef  __amd64
  58         return ("amd64");
  59 #else
  60         return ("ia32");
  61 #endif
  62 }
  63 
  64 int
  65 kmt_step_out_validate(mdb_tgt_t *t, uintptr_t pc)
  66 {
  67         kmt_data_t *kmt = t->t_data;
  68         int i;
  69 
  70         for (i = 0; i < sizeof (kmt->kmt_intrsyms) / sizeof (GElf_Sym); i++) {
  71                 GElf_Sym *sym = (GElf_Sym *)&kmt->kmt_intrsyms + i;
  72 
  73                 if (pc >= sym->st_value && pc < sym->st_value + sym->st_size)
  74                         return (0);
  75         }
  76 
  77         return (1);
  78 }
  79 
  80 /*
  81  * Determine the return address for the current frame.
  82  */
  83 int
  84 kmt_step_out(mdb_tgt_t *t, uintptr_t *p)
  85 {
  86         mdb_instr_t instr;
  87         kreg_t pc, sp, fp;
  88 
  89         (void) kmdb_dpi_get_register("pc", &pc);
  90         (void) kmdb_dpi_get_register("sp", &sp);
  91         (void) kmdb_dpi_get_register("fp", &fp);
  92 
  93         if (mdb_tgt_vread(t, &instr, sizeof (mdb_instr_t), pc) !=
  94             sizeof (mdb_instr_t))
  95                 return (-1); /* errno is set for us */
  96 
  97         if (!kmt_step_out_validate(t, pc))
  98                 return (set_errno(EMDB_TGTNOTSUP));
  99 
 100         return (mdb_isa_step_out(t, p, pc, fp, sp, instr));
 101 }
 102 
 103 /*
 104  * Return the address of the next instruction following a call, or return -1
 105  * and set errno to EAGAIN if the target should just single-step.
 106  */
 107 int
 108 kmt_next(mdb_tgt_t *t, uintptr_t *p)
 109 {
 110         kreg_t pc;
 111         mdb_instr_t instr;
 112 
 113         (void) kmdb_dpi_get_register("pc", &pc);
 114 
 115         if (mdb_tgt_vread(t, &instr, sizeof (mdb_instr_t), pc) !=
 116             sizeof (mdb_instr_t))
 117                 return (-1); /* errno is set for us */
 118 
 119         return (mdb_isa_next(t, p, pc, instr));
 120 }
 121 
 122 /*ARGSUSED*/
 123 static int
 124 kmt_stack_common(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv,
 125     int cpuid, mdb_tgt_stack_f *func)
 126 {
 127         const mdb_tgt_gregset_t *grp = NULL;
 128         mdb_tgt_gregset_t gregs;
 129         void *arg = (void *)(uintptr_t)mdb.m_nargs;
 130 
 131         if (flags & DCMD_ADDRSPEC) {
 132                 bzero(&gregs, sizeof (gregs));
 133                 gregs.kregs[KREG_FP] = addr;
 134                 grp = &gregs;
 135         } else
 136                 grp = kmdb_dpi_get_gregs(cpuid);
 137 
 138         if (grp == NULL) {
 139                 warn("failed to retrieve registers for cpu %d", cpuid);
 140                 return (DCMD_ERR);
 141         }
 142 
 143         if (argc != 0) {
 144                 if (argv->a_type == MDB_TYPE_CHAR || argc > 1)
 145                         return (DCMD_USAGE);
 146 
 147                 if (argv->a_type == MDB_TYPE_STRING)
 148                         arg = (void *)(uintptr_t)mdb_strtoull(argv->a_un.a_str);
 149                 else
 150                         arg = (void *)(uintptr_t)argv->a_un.a_val;
 151         }
 152 
 153         (void) mdb_isa_kvm_stack_iter(mdb.m_target, grp, func, arg);
 154 
 155         return (DCMD_OK);
 156 }
 157 
 158 int
 159 kmt_cpustack(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv,
 160     int cpuid, int verbose)
 161 {
 162         return (kmt_stack_common(addr, flags, argc, argv, cpuid,
 163             (verbose ? mdb_isa_kvm_framev : mdb_isa_kvm_frame)));
 164 }
 165 
 166 int
 167 kmt_stack(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
 168 {
 169         return (kmt_stack_common(addr, flags, argc, argv, DPI_MASTER_CPUID,
 170             mdb_isa_kvm_frame));
 171 }
 172 
 173 int
 174 kmt_stackv(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
 175 {
 176         return (kmt_stack_common(addr, flags, argc, argv, DPI_MASTER_CPUID,
 177             mdb_isa_kvm_framev));
 178 }
 179 
 180 int
 181 kmt_stackr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
 182 {
 183         return (kmt_stack_common(addr, flags, argc, argv, DPI_MASTER_CPUID,
 184             mdb_isa_kvm_framev));
 185 }
 186 
 187 /*ARGSUSED*/
 188 void
 189 kmt_printregs(const mdb_tgt_gregset_t *gregs)
 190 {
 191         mdb_isa_printregs(gregs);
 192 }
 193 
 194 #define IOCHECK_NOWARN  0
 195 #define IOCHECK_WARN    1
 196 
 197 static int
 198 kmt_io_check(uint64_t nbytes, uintptr_t addr, int dowarn)
 199 {
 200         if (addr > IOPORTLIMIT) {
 201                 if (dowarn)
 202                         warn("port address must be 0-%#x\n", IOPORTLIMIT);
 203                 return (set_errno(EINVAL));
 204         }
 205 
 206         if (nbytes != 1 && nbytes != 2 && nbytes != 4) {
 207                 if (dowarn)
 208                         warn("port access must be 1, 2, or 4 bytes\n");
 209                 return (set_errno(EINVAL));
 210         }
 211 
 212         if ((addr & (nbytes - 1)) != 0) {
 213                 if (dowarn) {
 214                         warn("address for %llu-byte access must be %llu-byte "
 215                             "aligned\n", (u_longlong_t)nbytes,
 216                             (u_longlong_t)nbytes);
 217                 }
 218                 return (set_errno(EINVAL));
 219         }
 220 
 221         return (0);
 222 }
 223 
 224 /*ARGSUSED1*/
 225 int
 226 kmt_in_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
 227 {
 228         uint64_t len = 0;
 229         uint32_t buf;
 230 
 231         if (mdb_getopts(argc, argv,
 232             'L', MDB_OPT_UINT64, &len,
 233             NULL) != argc)
 234                 return (DCMD_USAGE);
 235 
 236         if (len == 0)
 237                 len = mdb.m_dcount;
 238 
 239         if (kmt_io_check(len, addr, IOCHECK_WARN) < 0)
 240                 return (DCMD_ERR);
 241 
 242         if (mdb_tgt_ioread(mdb.m_target, &buf, len, addr) < 0) {
 243                 warn("failed to read from port 0x%llx", (u_longlong_t)addr);
 244                 return (DCMD_ERR);
 245         }
 246 
 247         mdb_printf("%x\n", buf);
 248 
 249         return (DCMD_OK);
 250 }
 251 
 252 static uint64_t
 253 kmt_numarg(const mdb_arg_t *arg)
 254 {
 255         if (arg->a_type == MDB_TYPE_STRING)
 256                 return (mdb_strtoull(arg->a_un.a_str));
 257         else
 258                 return (arg->a_un.a_val);
 259 }
 260 
 261 /*ARGSUSED1*/
 262 int
 263 kmt_out_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
 264 {
 265         uint64_t len = 0;
 266         uint64_t val;
 267 
 268         if (mdb_getopts(argc, argv,
 269             'L', MDB_OPT_UINT64, &len,
 270             NULL) != argc - 1)
 271                 return (DCMD_USAGE);
 272 
 273         if (len == 0)
 274                 len = mdb.m_dcount;
 275 
 276         argv += argc - 1;
 277         val = kmt_numarg(argv);
 278 
 279         if (kmt_io_check(len, addr, IOCHECK_WARN) < 0)
 280                 return (DCMD_ERR);
 281 
 282         if (val > (1ULL << (len * NBBY)) - 1) {
 283                 warn("value is out of range for port size\n");
 284                 return (DCMD_ERR);
 285         }
 286 
 287         if (mdb_tgt_iowrite(mdb.m_target, &val, len, addr) < 0) {
 288                 warn("failed to write to port %llx", (u_longlong_t)addr);
 289                 return (DCMD_ERR);
 290         }
 291 
 292         return (DCMD_OK);
 293 }
 294 
 295 static int
 296 kmt_rwmsr(uint32_t addr, uint64_t *valp, void (*rw)(uint32_t, uint64_t *))
 297 {
 298         jmp_buf pcb, *oldpcb = NULL;
 299 
 300         if (setjmp(pcb) != 0) {
 301                 kmdb_dpi_restore_fault_hdlr(oldpcb);
 302                 return (-1); /* errno is set for us */
 303         }
 304 
 305         oldpcb = kmdb_dpi_set_fault_hdlr(&pcb);
 306         rw(addr, valp);
 307         kmdb_dpi_restore_fault_hdlr(oldpcb);
 308 
 309         return (0);
 310 }
 311 
 312 /*ARGSUSED*/
 313 int
 314 kmt_rdmsr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
 315 {
 316         uint64_t val;
 317 
 318         if (!(flags & DCMD_ADDRSPEC))
 319                 return (DCMD_USAGE);
 320 
 321         if (kmt_rwmsr(addr, &val, rdmsr) < 0) {
 322                 warn("rdmsr failed");
 323                 return (DCMD_ERR);
 324         }
 325 
 326         mdb_printf("%llx\n", (u_longlong_t)val);
 327 
 328         return (DCMD_OK);
 329 }
 330 
 331 /*ARGSUSED*/
 332 int
 333 kmt_wrmsr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
 334 {
 335         uint64_t val;
 336 
 337         if (!(flags & DCMD_ADDRSPEC) || argc != 1)
 338                 return (DCMD_USAGE);
 339 
 340         val = kmt_numarg(argv);
 341 
 342         if (kmt_rwmsr(addr, &val, wrmsr)) {
 343                 warn("wrmsr failed");
 344                 return (DCMD_ERR);
 345         }
 346 
 347         return (DCMD_OK);
 348 }
 349 
 350 /*ARGSUSED*/
 351 ssize_t
 352 kmt_write(mdb_tgt_t *t, const void *buf, size_t nbytes, uintptr_t addr)
 353 {
 354         if (!(t->t_flags & MDB_TGT_F_ALLOWIO) &&
 355             (nbytes = kmdb_kdi_range_is_nontoxic(addr, nbytes, 1)) == 0)
 356                 return (set_errno(EMDB_NOMAP));
 357 
 358         /*
 359          * No writes to user space are allowed.  If we were to allow it, we'd
 360          * be in the unfortunate situation where kmdb could place a breakpoint
 361          * on a userspace executable page; this dirty page would end up being
 362          * flushed back to disk, incurring sadness when it's next executed.
 363          * Besides, we can't allow trapping in from userspace anyway.
 364          */
 365         if (addr < kmdb_kdi_get_userlimit())
 366                 return (set_errno(EMDB_TGTNOTSUP));
 367 
 368         return (kmt_rw(t, (void *)buf, nbytes, addr, kmt_writer));
 369 }
 370 
 371 /*ARGSUSED*/
 372 static ssize_t
 373 kmt_iorw(mdb_tgt_t *t, void *buf, size_t nbytes, uint64_t addr,
 374     void (*iorw)(void *, size_t, uintptr_t))
 375 {
 376         jmp_buf pcb, *oldpcb = NULL;
 377 
 378         if (kmt_io_check(nbytes, addr, IOCHECK_NOWARN) < 0)
 379                 return (-1); /* errno is set for us */
 380 
 381         if (setjmp(pcb) != 0) {
 382                 kmdb_dpi_restore_fault_hdlr(oldpcb);
 383                 return (-1); /* errno is set for us */
 384         }
 385 
 386         oldpcb = kmdb_dpi_set_fault_hdlr(&pcb);
 387         iorw(buf, nbytes, addr);
 388         kmdb_dpi_restore_fault_hdlr(oldpcb);
 389 
 390         return (nbytes);
 391 }
 392 
 393 /*ARGSUSED*/
 394 ssize_t
 395 kmt_ioread(mdb_tgt_t *t, void *buf, size_t nbytes, uintptr_t addr)
 396 {
 397         return (kmt_iorw(t, buf, nbytes, addr, kmt_in));
 398 }
 399 
 400 /*ARGSUSED*/
 401 ssize_t
 402 kmt_iowrite(mdb_tgt_t *t, const void *buf, size_t nbytes, uintptr_t addr)
 403 {
 404         return (kmt_iorw(t, (void *)buf, nbytes, addr, kmt_out));
 405 }
 406 
 407 static int
 408 kmt_pcicfg_common(uintptr_t off, uint32_t *valp, const mdb_arg_t *argv,
 409     void (*rw)(void *, size_t, uintptr_t))
 410 {
 411         uint32_t bus, dev, func;
 412         uint32_t addr;
 413 
 414         bus = kmt_numarg(&argv[0]);
 415         dev = kmt_numarg(&argv[1]);
 416         func = kmt_numarg(&argv[2]);
 417 
 418         if ((bus & 0xffff) != bus) {
 419                 warn("invalid bus number (must be 0-0xffff)\n");
 420                 return (DCMD_ERR);
 421         }
 422 
 423         if ((dev & 0x1f) != dev) {
 424                 warn("invalid device number (must be 0-0x1f)\n");
 425                 return (DCMD_ERR);
 426         }
 427 
 428         if ((func & 0x7) != func) {
 429                 warn("invalid function number (must be 0-7)\n");
 430                 return (DCMD_ERR);
 431         }
 432 
 433         if ((off & 0xfc) != off) {
 434                 warn("invalid register number (must be 0-0xff, and 4-byte "
 435                     "aligned\n");
 436                 return (DCMD_ERR);
 437         }
 438 
 439         addr = PCI_CADDR1(bus, dev, func, off);
 440 
 441         if (kmt_iowrite(mdb.m_target, &addr, sizeof (addr), PCI_CONFADD) !=
 442             sizeof (addr)) {
 443                 warn("write of PCI_CONFADD failed");
 444                 return (DCMD_ERR);
 445         }
 446 
 447         if (kmt_iorw(mdb.m_target, valp, sizeof (*valp), PCI_CONFDATA, rw) !=
 448             sizeof (*valp)) {
 449                 warn("access to PCI_CONFDATA failed");
 450                 return (DCMD_ERR);
 451         }
 452 
 453         return (DCMD_OK);
 454 }
 455 
 456 /*ARGSUSED*/
 457 int
 458 kmt_rdpcicfg(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
 459 {
 460         uint32_t val;
 461 
 462         if (argc != 3 || !(flags & DCMD_ADDRSPEC))
 463                 return (DCMD_USAGE);
 464 
 465         if (kmt_pcicfg_common(addr, &val, argv, kmt_in) != DCMD_OK)
 466                 return (DCMD_ERR);
 467 
 468         mdb_printf("%llx\n", (u_longlong_t)val);
 469 
 470         return (DCMD_OK);
 471 }
 472 
 473 /*ARGSUSED*/
 474 int
 475 kmt_wrpcicfg(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
 476 {
 477         uint32_t val;
 478 
 479         if (argc != 4 || !(flags & DCMD_ADDRSPEC))
 480                 return (DCMD_USAGE);
 481 
 482         val = (uint32_t)kmt_numarg(&argv[3]);
 483 
 484         if (kmt_pcicfg_common(addr, &val, argv, kmt_out) != DCMD_OK)
 485                 return (DCMD_ERR);
 486 
 487         return (DCMD_OK);
 488 }
 489 
 490 const char *
 491 kmt_trapname(int trapnum)
 492 {
 493         static char trapname[11];
 494 
 495         switch (trapnum) {
 496         case T_ZERODIV:
 497                 return ("division by zero (#de) trap");
 498         case T_SGLSTP:
 499                 return ("single-step (#db) trap");
 500         case T_NMIFLT:
 501                 return ("NMI");
 502         case T_BPTFLT:
 503                 return ("breakpoint (#bp) trap");
 504         case T_ILLINST:
 505                 return ("illegal instruction (#ud) trap");
 506         case T_SEGFLT:
 507                 return ("segment not present (#np) trap");
 508         case T_STKFLT:
 509                 return ("stack (#ss) trap");
 510         case T_GPFLT:
 511                 return ("general protection (#gp) trap");
 512         case T_PGFLT:
 513                 return ("page fault (#pf) trap");
 514         case T_ALIGNMENT:
 515                 return ("alignment check (#ac) trap");
 516         case T_MCE:
 517                 return ("machine check (#mc) trap");
 518         case T_SIMDFPE:
 519                 return ("SSE/SSE2 (#xm) trap");
 520         case T_DBGENTR:
 521                 return ("debugger entry trap");
 522         default:
 523                 (void) mdb_snprintf(trapname, sizeof (trapname), "trap %#x",
 524                     trapnum);
 525                 return (trapname);
 526         }
 527 }
 528 
 529 void
 530 kmt_init_isadep(mdb_tgt_t *t)
 531 {
 532         kmt_data_t *kmt = t->t_data;
 533 
 534         kmt->kmt_rds = mdb_isa_kregs;
 535 
 536         kmt->kmt_trapmax = KMT_MAXTRAPNO;
 537         kmt->kmt_trapmap = mdb_zalloc(BT_SIZEOFMAP(kmt->kmt_trapmax), UM_SLEEP);
 538 
 539         /* Traps for which we want to provide an explicit message */
 540         (void) mdb_tgt_add_fault(t, T_ZERODIV, MDB_TGT_SPEC_INTERNAL,
 541             no_se_f, NULL);
 542         (void) mdb_tgt_add_fault(t, T_ILLINST, MDB_TGT_SPEC_INTERNAL,
 543             no_se_f, NULL);
 544         (void) mdb_tgt_add_fault(t, T_SEGFLT, MDB_TGT_SPEC_INTERNAL,
 545             no_se_f, NULL);
 546         (void) mdb_tgt_add_fault(t, T_STKFLT, MDB_TGT_SPEC_INTERNAL,
 547             no_se_f, NULL);
 548         (void) mdb_tgt_add_fault(t, T_GPFLT, MDB_TGT_SPEC_INTERNAL,
 549             no_se_f, NULL);
 550         (void) mdb_tgt_add_fault(t, T_PGFLT, MDB_TGT_SPEC_INTERNAL,
 551             no_se_f, NULL);
 552         (void) mdb_tgt_add_fault(t, T_ALIGNMENT, MDB_TGT_SPEC_INTERNAL,
 553             no_se_f, NULL);
 554         (void) mdb_tgt_add_fault(t, T_MCE, MDB_TGT_SPEC_INTERNAL,
 555             no_se_f, NULL);
 556         (void) mdb_tgt_add_fault(t, T_SIMDFPE, MDB_TGT_SPEC_INTERNAL,
 557             no_se_f, NULL);
 558 
 559         /*
 560          * Traps which will be handled elsewhere, and which therefore don't
 561          * need the trap-based message.
 562          */
 563         BT_SET(kmt->kmt_trapmap, T_SGLSTP);
 564         BT_SET(kmt->kmt_trapmap, T_BPTFLT);
 565         BT_SET(kmt->kmt_trapmap, T_DBGENTR);
 566 
 567         /* Catch-all for traps not explicitly listed here */
 568         (void) mdb_tgt_add_fault(t, KMT_TRAP_NOTENUM, MDB_TGT_SPEC_INTERNAL,
 569             no_se_f, NULL);
 570 }
 571 
 572 void
 573 kmt_startup_isadep(mdb_tgt_t *t)
 574 {
 575         kmt_data_t *kmt = t->t_data;
 576 
 577         /*
 578          * The stack trace and ::step out code need to detect "interrupt"
 579          * frames.  The heuristic they use to detect said frames requires the
 580          * addresses of routines that can generate them.
 581          */
 582         (void) mdb_tgt_lookup_by_name(t, MDB_TGT_OBJ_EXEC,
 583             "cmnint", &kmt->kmt_intrsyms._kmt_cmnint, NULL);
 584         (void) mdb_tgt_lookup_by_name(t, MDB_TGT_OBJ_EXEC,
 585             "cmntrap", &kmt->kmt_intrsyms._kmt_cmntrap, NULL);
 586         (void) mdb_tgt_lookup_by_name(t, MDB_TGT_OBJ_EXEC,
 587             "sys_sysenter", &kmt->kmt_intrsyms._kmt_sysenter, NULL);
 588         (void) mdb_tgt_lookup_by_name(t, MDB_TGT_OBJ_EXEC,
 589             "brand_sys_sysenter", &kmt->kmt_intrsyms._kmt_brand_sysenter, NULL);
 590 #if defined(__amd64)
 591         (void) mdb_tgt_lookup_by_name(t, MDB_TGT_OBJ_EXEC,
 592             "sys_syscall", &kmt->kmt_intrsyms._kmt_syscall, NULL);
 593         (void) mdb_tgt_lookup_by_name(t, MDB_TGT_OBJ_EXEC,
 594             "brand_sys_syscall", &kmt->kmt_intrsyms._kmt_brand_syscall, NULL);
 595 #endif
 596 }