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