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