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 }