Home | History | Annotate | Download | only in kmdb
      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