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