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