diff options
Diffstat (limited to 'usr/src/cmd/mdb')
30 files changed, 1976 insertions, 157 deletions
diff --git a/usr/src/cmd/mdb/common/kmdb/kmdb_kvm.c b/usr/src/cmd/mdb/common/kmdb/kmdb_kvm.c index 90fd098d1c..628503d179 100644 --- a/usr/src/cmd/mdb/common/kmdb/kmdb_kvm.c +++ b/usr/src/cmd/mdb/common/kmdb/kmdb_kvm.c @@ -286,6 +286,8 @@ kmt_vtop(mdb_tgt_t *t, mdb_tgt_as_t as, uintptr_t va, physaddr_t *pap) case (uintptr_t)MDB_TGT_AS_IO: return (set_errno(EINVAL)); case (uintptr_t)MDB_TGT_AS_VIRT: + case (uintptr_t)MDB_TGT_AS_VIRT_I: + case (uintptr_t)MDB_TGT_AS_VIRT_S: if ((asp = (struct as *)kmt_read_kas(t)) == NULL) return (-1); /* errno is set for us */ break; diff --git a/usr/src/cmd/mdb/common/mdb/mdb_cmds.c b/usr/src/cmd/mdb/common/mdb/mdb_cmds.c index b7b15aa507..10c622443a 100644 --- a/usr/src/cmd/mdb/common/mdb/mdb_cmds.c +++ b/usr/src/cmd/mdb/common/mdb/mdb_cmds.c @@ -2090,7 +2090,7 @@ cmd_dis(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) if (opt_f) as = MDB_TGT_AS_FILE; else - as = MDB_TGT_AS_VIRT; + as = MDB_TGT_AS_VIRT_I; if (opt_w == FALSE) { n++; @@ -2635,8 +2635,9 @@ tgt_status(const mdb_tgt_status_t *tsp) return (DCMD_OK); if (tsp->st_pc != 0) { - if (mdb_dis_ins2str(mdb.m_disasm, mdb.m_target, MDB_TGT_AS_VIRT, - buf, sizeof (buf), tsp->st_pc) != tsp->st_pc) + if (mdb_dis_ins2str(mdb.m_disasm, mdb.m_target, + MDB_TGT_AS_VIRT_I, buf, sizeof (buf), tsp->st_pc) != + tsp->st_pc) format = "target stopped at:\n%-#16a%8T%s\n"; else format = "target stopped at %a:\n"; diff --git a/usr/src/cmd/mdb/common/mdb/mdb_create.c b/usr/src/cmd/mdb/common/mdb/mdb_create.c index ea30457ef0..86490bf825 100644 --- a/usr/src/cmd/mdb/common/mdb/mdb_create.c +++ b/usr/src/cmd/mdb/common/mdb/mdb_create.c @@ -24,7 +24,9 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" +/* + * Copyright 2018 Joyent, Inc. + */ #include <mdb/mdb.h> #include <mdb/mdb_conf.h> @@ -51,6 +53,11 @@ mdb_create_builtin_tgts(void) if ((mp = mdb_module_load_builtin("mdb_raw")) != NULL) mp->mod_tgt_ctor = mdb_rawfile_tgt_create; + +#ifdef __amd64 + if ((mp = mdb_module_load_builtin("mdb_bhyve")) != NULL) + mp->mod_tgt_ctor = mdb_bhyve_tgt_create; +#endif } void diff --git a/usr/src/cmd/mdb/common/mdb/mdb_fmt.c b/usr/src/cmd/mdb/common/mdb/mdb_fmt.c index 662cf7bea5..6a745b2ac4 100644 --- a/usr/src/cmd/mdb/common/mdb/mdb_fmt.c +++ b/usr/src/cmd/mdb/common/mdb/mdb_fmt.c @@ -411,6 +411,9 @@ fmt_instr(mdb_tgt_t *t, mdb_tgt_as_t as, mdb_tgt_addr_t addr, size_t cnt) char buf[BUFSIZ]; uintptr_t naddr; + if (as == MDB_TGT_AS_VIRT) + as = MDB_TGT_AS_VIRT_I; + while (cnt-- != 0) { naddr = mdb_dis_ins2str(mdb.m_disasm, t, as, buf, sizeof (buf), addr); @@ -431,6 +434,9 @@ fmt_dotinstr(mdb_tgt_t *t, mdb_tgt_as_t as, mdb_tgt_addr_t addr, size_t cnt) uintptr_t naddr; uint32_t i; + if (as == MDB_TGT_AS_VIRT) + as = MDB_TGT_AS_VIRT_I; + for (mdb_iob_clrflags(mdb.m_out, oflags); cnt-- != 0; addr = naddr) { if (mdb_tgt_aread(t, as, &i, sizeof (i), addr) != sizeof (i)) { warn("failed to read data from target"); diff --git a/usr/src/cmd/mdb/common/mdb/mdb_kproc.c b/usr/src/cmd/mdb/common/mdb/mdb_kproc.c index e13dcea53f..4eeb8ac708 100644 --- a/usr/src/cmd/mdb/common/mdb/mdb_kproc.c +++ b/usr/src/cmd/mdb/common/mdb/mdb_kproc.c @@ -553,7 +553,8 @@ kp_vtop(mdb_tgt_t *t, mdb_tgt_as_t as, uintptr_t va, physaddr_t *pap) kp_data_t *kp = t->t_data; physaddr_t pa; - if (as != MDB_TGT_AS_VIRT) + if (as != MDB_TGT_AS_VIRT && as != MDB_TGT_AS_VIRT_I && + as != MDB_TGT_AS_VIRT_S) return (set_errno(EINVAL)); if ((pa = kvm_physaddr(kp->kp_cookie, kp->kp_as, va)) != -1ULL) { diff --git a/usr/src/cmd/mdb/common/mdb/mdb_kvm.c b/usr/src/cmd/mdb/common/mdb/mdb_kvm.c index fe280c05c7..27ca238ca9 100644 --- a/usr/src/cmd/mdb/common/mdb/mdb_kvm.c +++ b/usr/src/cmd/mdb/common/mdb/mdb_kvm.c @@ -814,6 +814,8 @@ kt_vtop(mdb_tgt_t *t, mdb_tgt_as_t as, uintptr_t va, physaddr_t *pap) case (uintptr_t)MDB_TGT_AS_IO: return (set_errno(EINVAL)); case (uintptr_t)MDB_TGT_AS_VIRT: + case (uintptr_t)MDB_TGT_AS_VIRT_I: + case (uintptr_t)MDB_TGT_AS_VIRT_S: asp = kt->k_as; break; default: diff --git a/usr/src/cmd/mdb/common/mdb/mdb_main.c b/usr/src/cmd/mdb/common/mdb/mdb_main.c index eea4b5b60e..8747464328 100644 --- a/usr/src/cmd/mdb/common/mdb/mdb_main.c +++ b/usr/src/cmd/mdb/common/mdb/mdb_main.c @@ -322,12 +322,13 @@ static void usage(int status) { mdb_iob_printf(mdb.m_err, "Usage: %s [-fkmuwyAFKMSUW] [+/-o option] " - "[-p pid] [-s dist] [-I path] [-L path]\n\t[-P prompt] " + "[-b VM] [-p pid] [-s dist] [-I path] [-L path]\n\t[-P prompt] " "[-R root] [-V dis-version] [-e expr] " "[object [core] | core | suffix]\n\n", mdb.m_pname); mdb_iob_puts(mdb.m_err, + "\t-b attach to specified bhyve VM\n" "\t-e evaluate expr and return status\n" "\t-f force raw file debugging mode\n" "\t-k force kernel debugging mode\n" @@ -405,6 +406,19 @@ identify_xvm_file(const char *file, int *longmode) } #endif /* __x86 */ +#ifndef __amd64 +/* + * There is no bhyve target in a 32bit x86 or any SPARC mdb. This dummy helps + * keep the code simpler. + */ +/*ARGSUSED*/ +static int +mdb_bhyve_tgt_create(mdb_tgt_t *t, int argc, const char *argv[]) +{ + return (set_errno(EINVAL)); +} +#endif + int main(int argc, char *argv[], char *envp[]) { @@ -424,6 +438,7 @@ main(int argc, char *argv[], char *envp[]) const char *Iflag = NULL, *Lflag = NULL, *Vflag = NULL, *pidarg = NULL; const char *eflag = NULL; int fflag = 0, Kflag = 0, Rflag = 0, Sflag = 0, Oflag = 0, Uflag = 0; + int bflag = 0; int ttylike; int longmode = 0; @@ -513,8 +528,12 @@ main(int argc, char *argv[], char *envp[]) while (optind < argc) { while ((c = getopt(argc, argv, - "e:fkmo:p:s:uwyACD:FI:KL:MOP:R:SUV:W")) != (int)EOF) { + "be:fkmo:p:s:uwyACD:FI:KL:MOP:R:SUV:W")) != (int)EOF) { switch (c) { + case 'b': + bflag++; + tgt_ctor = mdb_bhyve_tgt_create; + break; case 'e': if (eflag != NULL) { warn("-e already specified\n"); @@ -830,6 +849,15 @@ main(int argc, char *argv[], char *envp[]) if (fflag) goto tcreate; /* skip re-exec and just create target */ + /* bhyve: directly create target, or re-exec in case of 32bit */ + if (bflag) { +#ifndef __amd64 + goto reexec; +#else + goto tcreate; +#endif + } + /* * If we just have an object file name, and that file doesn't * exist, and it's a string of digits, infer it to be a diff --git a/usr/src/cmd/mdb/common/mdb/mdb_rawfile.c b/usr/src/cmd/mdb/common/mdb/mdb_rawfile.c index 086639de74..d21ad0f38a 100644 --- a/usr/src/cmd/mdb/common/mdb/mdb_rawfile.c +++ b/usr/src/cmd/mdb/common/mdb/mdb_rawfile.c @@ -143,6 +143,8 @@ rf_aread(mdb_tgt_t *t, mdb_tgt_as_t as, void *buf, { switch ((uintptr_t)as) { case (uintptr_t)MDB_TGT_AS_VIRT: + case (uintptr_t)MDB_TGT_AS_VIRT_I: + case (uintptr_t)MDB_TGT_AS_VIRT_S: case (uintptr_t)MDB_TGT_AS_PHYS: if (RF_CORE(t->t_data) != NULL) return (rf_read(RF_CORE(t->t_data), buf, len, addr)); @@ -160,6 +162,8 @@ rf_awrite(mdb_tgt_t *t, mdb_tgt_as_t as, const void *buf, { switch ((uintptr_t)as) { case (uintptr_t)MDB_TGT_AS_VIRT: + case (uintptr_t)MDB_TGT_AS_VIRT_I: + case (uintptr_t)MDB_TGT_AS_VIRT_S: case (uintptr_t)MDB_TGT_AS_PHYS: if (RF_CORE(t->t_data) != NULL) return (rf_write(RF_CORE(t->t_data), buf, len, addr)); diff --git a/usr/src/cmd/mdb/common/mdb/mdb_target.c b/usr/src/cmd/mdb/common/mdb/mdb_target.c index 17aef0aac1..e0ae29bd99 100644 --- a/usr/src/cmd/mdb/common/mdb/mdb_target.c +++ b/usr/src/cmd/mdb/common/mdb/mdb_target.c @@ -398,6 +398,8 @@ mdb_tgt_aread(mdb_tgt_t *t, mdb_tgt_as_t as, switch ((uintptr_t)as) { case (uintptr_t)MDB_TGT_AS_VIRT: + case (uintptr_t)MDB_TGT_AS_VIRT_I: + case (uintptr_t)MDB_TGT_AS_VIRT_S: return (t->t_ops->t_vread(t, buf, n, addr)); case (uintptr_t)MDB_TGT_AS_PHYS: return (t->t_ops->t_pread(t, buf, n, addr)); @@ -421,6 +423,8 @@ mdb_tgt_awrite(mdb_tgt_t *t, mdb_tgt_as_t as, switch ((uintptr_t)as) { case (uintptr_t)MDB_TGT_AS_VIRT: + case (uintptr_t)MDB_TGT_AS_VIRT_I: + case (uintptr_t)MDB_TGT_AS_VIRT_S: return (t->t_ops->t_vwrite(t, buf, n, addr)); case (uintptr_t)MDB_TGT_AS_PHYS: return (t->t_ops->t_pwrite(t, buf, n, addr)); diff --git a/usr/src/cmd/mdb/common/mdb/mdb_target.h b/usr/src/cmd/mdb/common/mdb/mdb_target.h index c36b85e2f3..e385caa38e 100644 --- a/usr/src/cmd/mdb/common/mdb/mdb_target.h +++ b/usr/src/cmd/mdb/common/mdb/mdb_target.h @@ -64,6 +64,9 @@ extern int mdb_kvm_tgt_create(mdb_tgt_t *, int, const char *[]); extern int mdb_proc_tgt_create(mdb_tgt_t *, int, const char *[]); extern int mdb_kproc_tgt_create(mdb_tgt_t *, int, const char *[]); extern int mdb_rawfile_tgt_create(mdb_tgt_t *, int, const char *[]); +#ifdef __amd64 +extern int mdb_bhyve_tgt_create(mdb_tgt_t *, int, const char *[]); +#endif #else extern int kmdb_kvm_create(mdb_tgt_t *, int, const char *[]); #endif @@ -139,10 +142,12 @@ typedef void * mdb_tgt_as_t; /* Opaque address space id */ typedef uint64_t mdb_tgt_addr_t; /* Generic unsigned address */ typedef uint64_t physaddr_t; /* Physical memory address */ -#define MDB_TGT_AS_VIRT ((mdb_tgt_as_t)-1L) /* Virtual address space */ -#define MDB_TGT_AS_PHYS ((mdb_tgt_as_t)-2L) /* Physical address space */ -#define MDB_TGT_AS_FILE ((mdb_tgt_as_t)-3L) /* Object file address space */ -#define MDB_TGT_AS_IO ((mdb_tgt_as_t)-4L) /* I/o address space */ +#define MDB_TGT_AS_VIRT ((mdb_tgt_as_t)-1L) /* Virtual address space: */ +#define MDB_TGT_AS_VIRT_I ((mdb_tgt_as_t)-2L) /* special case for code */ +#define MDB_TGT_AS_VIRT_S ((mdb_tgt_as_t)-3L) /* special case for stack */ +#define MDB_TGT_AS_PHYS ((mdb_tgt_as_t)-4L) /* Physical address space */ +#define MDB_TGT_AS_FILE ((mdb_tgt_as_t)-5L) /* Object file address space */ +#define MDB_TGT_AS_IO ((mdb_tgt_as_t)-6L) /* I/o address space */ extern ssize_t mdb_tgt_aread(mdb_tgt_t *, mdb_tgt_as_t, void *, size_t, mdb_tgt_addr_t); diff --git a/usr/src/cmd/mdb/i86pc/modules/unix/amd64/Makefile b/usr/src/cmd/mdb/i86pc/modules/unix/amd64/Makefile index efcfad5375..54bc62a086 100644 --- a/usr/src/cmd/mdb/i86pc/modules/unix/amd64/Makefile +++ b/usr/src/cmd/mdb/i86pc/modules/unix/amd64/Makefile @@ -22,7 +22,7 @@ # Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -# Copyright 2018 Joyent, Inc. +# Copyright 2019 Joyent, Inc. MODULE = unix.so MDBTGT = kvm @@ -38,6 +38,7 @@ include ../../../../Makefile.module CPPFLAGS += -DMP -D_MACHDEP CPPFLAGS += -I../../../../common +CPPFLAGS += -I../../../../intel CPPFLAGS += -I$(SRC)/uts/i86pc CPPFLAGS += -I$(SRC)/uts/intel diff --git a/usr/src/cmd/mdb/i86pc/modules/unix/unix.c b/usr/src/cmd/mdb/i86pc/modules/unix/unix.c index e91321b235..c3b7e809e4 100644 --- a/usr/src/cmd/mdb/i86pc/modules/unix/unix.c +++ b/usr/src/cmd/mdb/i86pc/modules/unix/unix.c @@ -20,11 +20,13 @@ */ /* * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright 2018 Joyent, Inc. + * Copyright 2018 OmniOS Community Edition (OmniOSce) Association. + * Copyright 2019 Joyent, Inc. */ #include <mdb/mdb_modapi.h> #include <mdb/mdb_ctf.h> +#include <mdb/mdb_x86util.h> #include <sys/cpuvar.h> #include <sys/systm.h> #include <sys/traptrace.h> @@ -963,73 +965,24 @@ x86_featureset_dcmd(uintptr_t addr, uint_t flags, int argc, static int sysregs_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) { - ulong_t cr0, cr2, cr3, cr4; + struct sysregs sregs = { 0 }; desctbr_t gdtr; + boolean_t longmode = B_FALSE; - static const mdb_bitmask_t cr0_flag_bits[] = { - { "PE", CR0_PE, CR0_PE }, - { "MP", CR0_MP, CR0_MP }, - { "EM", CR0_EM, CR0_EM }, - { "TS", CR0_TS, CR0_TS }, - { "ET", CR0_ET, CR0_ET }, - { "NE", CR0_NE, CR0_NE }, - { "WP", CR0_WP, CR0_WP }, - { "AM", CR0_AM, CR0_AM }, - { "NW", CR0_NW, CR0_NW }, - { "CD", CR0_CD, CR0_CD }, - { "PG", CR0_PG, CR0_PG }, - { NULL, 0, 0 } - }; - - static const mdb_bitmask_t cr3_flag_bits[] = { - { "PCD", CR3_PCD, CR3_PCD }, - { "PWT", CR3_PWT, CR3_PWT }, - { NULL, 0, 0, } - }; - - static const mdb_bitmask_t cr4_flag_bits[] = { - { "VME", CR4_VME, CR4_VME }, - { "PVI", CR4_PVI, CR4_PVI }, - { "TSD", CR4_TSD, CR4_TSD }, - { "DE", CR4_DE, CR4_DE }, - { "PSE", CR4_PSE, CR4_PSE }, - { "PAE", CR4_PAE, CR4_PAE }, - { "MCE", CR4_MCE, CR4_MCE }, - { "PGE", CR4_PGE, CR4_PGE }, - { "PCE", CR4_PCE, CR4_PCE }, - { "OSFXSR", CR4_OSFXSR, CR4_OSFXSR }, - { "OSXMMEXCPT", CR4_OSXMMEXCPT, CR4_OSXMMEXCPT }, - { "VMXE", CR4_VMXE, CR4_VMXE }, - { "SMXE", CR4_SMXE, CR4_SMXE }, - { "PCIDE", CR4_PCIDE, CR4_PCIDE }, - { "OSXSAVE", CR4_OSXSAVE, CR4_OSXSAVE }, - { "SMEP", CR4_SMEP, CR4_SMEP }, - { "SMAP", CR4_SMAP, CR4_SMAP }, - { NULL, 0, 0 } - }; - - cr0 = kmdb_unix_getcr0(); - cr2 = kmdb_unix_getcr2(); - cr3 = kmdb_unix_getcr3(); - cr4 = kmdb_unix_getcr4(); - - kmdb_unix_getgdtr(&gdtr); +#ifdef __amd64 + longmode = B_TRUE; +#endif - mdb_printf("%%cr0 = 0x%lx <%b>\n", cr0, cr0, cr0_flag_bits); - mdb_printf("%%cr2 = 0x%lx <%a>\n", cr2, cr2); + sregs.sr_cr0 = kmdb_unix_getcr0(); + sregs.sr_cr2 = kmdb_unix_getcr2(); + sregs.sr_cr3 = kmdb_unix_getcr3(); + sregs.sr_cr4 = kmdb_unix_getcr4(); - if ((cr4 & CR4_PCIDE)) { - mdb_printf("%%cr3 = 0x%lx <pfn:0x%lx pcid:%lu>\n", cr3, - cr3 >> MMU_PAGESHIFT, cr3 & MMU_PAGEOFFSET); - } else { - mdb_printf("%%cr3 = 0x%lx <pfn:0x%lx flags:%b>\n", cr3, - cr3 >> MMU_PAGESHIFT, cr3, cr3_flag_bits); - } - - mdb_printf("%%cr4 = 0x%lx <%b>\n", cr4, cr4, cr4_flag_bits); + kmdb_unix_getgdtr(&gdtr); + sregs.sr_gdtr.d_base = gdtr.dtr_base; + sregs.sr_gdtr.d_lim = gdtr.dtr_limit; - mdb_printf("%%gdtr.base = 0x%lx, %%gdtr.limit = 0x%hx\n", - gdtr.dtr_base, gdtr.dtr_limit); + mdb_x86_print_sysregs(&sregs, longmode); return (DCMD_OK); } diff --git a/usr/src/cmd/mdb/i86xpv/modules/unix/amd64/Makefile b/usr/src/cmd/mdb/i86xpv/modules/unix/amd64/Makefile index 32c1fe33fd..5854a1610e 100644 --- a/usr/src/cmd/mdb/i86xpv/modules/unix/amd64/Makefile +++ b/usr/src/cmd/mdb/i86xpv/modules/unix/amd64/Makefile @@ -22,7 +22,7 @@ # Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -# Copyright 2018 Joyent, Inc. +# Copyright 2019 Joyent, Inc. MODULE = unix.so MDBTGT = kvm @@ -40,6 +40,7 @@ MODSRCS_DIR = ../../../../i86pc/modules/unix/ CPPFLAGS += -DMP -D_MACHDEP -D__xpv CPPFLAGS += -I../../../../common +CPPFLAGS += -I../../../../intel CPPFLAGS += -I$(SRC)/uts/common CPPFLAGS += -I$(SRC)/uts/i86xpv CPPFLAGS += -I$(SRC)/uts/i86pc diff --git a/usr/src/cmd/mdb/intel/Makefile.kmdb b/usr/src/cmd/mdb/intel/Makefile.kmdb index 1e9efcbc83..6151a2e46a 100644 --- a/usr/src/cmd/mdb/intel/Makefile.kmdb +++ b/usr/src/cmd/mdb/intel/Makefile.kmdb @@ -22,7 +22,7 @@ # Copyright 2009 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -# Copyright 2019, Joyent, Inc. +# Copyright 2019 Joyent, Inc. # PROMSRCS += \ @@ -68,6 +68,7 @@ KMDBLIBS = $(STANDLIBS) ../mdb_ks/kmod/mdb_ks MAPFILE_SOURCES = \ $(MAPFILE_SOURCES_COMMON) \ ../../kmdb/kmdb_dpi_isadep.h \ + ../../mdb/mdb_x86util.h \ $(MAPFILE_SOURCES_$(MACH)) %.o: ../../../../../uts/intel/promif/%.c diff --git a/usr/src/cmd/mdb/intel/amd64/Makefile.kmdb b/usr/src/cmd/mdb/intel/amd64/Makefile.kmdb index 61cf1541a2..8cee9ff049 100644 --- a/usr/src/cmd/mdb/intel/amd64/Makefile.kmdb +++ b/usr/src/cmd/mdb/intel/amd64/Makefile.kmdb @@ -22,6 +22,8 @@ # Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # +# Copyright 2019 Joyent, Inc. +# KMDBML += \ kaif_invoke.s \ @@ -29,6 +31,7 @@ KMDBML += \ KMDBSRCS += \ kmdb_makecontext.c \ - mdb_amd64util.c + mdb_amd64util.c \ + mdb_x86util.c SACPPFLAGS = -D__$(MACH64) -U__$(MACH) diff --git a/usr/src/cmd/mdb/intel/amd64/mdb/Makefile b/usr/src/cmd/mdb/intel/amd64/mdb/Makefile index 3dfa7a34d5..918aa71ea1 100644 --- a/usr/src/cmd/mdb/intel/amd64/mdb/Makefile +++ b/usr/src/cmd/mdb/intel/amd64/mdb/Makefile @@ -22,10 +22,15 @@ # Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # +# Copyright 2019 Joyent, Inc. +# SRCS = kvm_amd64dep.c \ kvm_isadep.c \ mdb_amd64util.c \ + mdb_ia32util.c \ + mdb_x86util.c \ + mdb_bhyve.c \ proc_amd64dep.c %.o: %.c @@ -42,12 +47,14 @@ SRCS = kvm_amd64dep.c \ %.ln: ../../mdb/%.c $(LINT.c) -c $< -include ../../../../Makefile.cmd -include ../../../../Makefile.cmd.64 -include ../../Makefile.amd64 -include ../../../Makefile.mdb +include $(SRC)/cmd/Makefile.cmd +include $(SRC)/cmd/Makefile.cmd.64 +include $(SRC)/cmd/mdb/intel/Makefile.amd64 +include $(SRC)/cmd/mdb/Makefile.mdb +include $(SRC)/Makefile.psm CPPFLAGS += -I../../mdb -LDLIBS += -lsaveargs + +LDLIBS += -lsaveargs -lvmm install: all $(ISAEXEC) $(ROOTPROG64) $(ROOTLINK64) diff --git a/usr/src/cmd/mdb/intel/kmdb/kaif.c b/usr/src/cmd/mdb/intel/kmdb/kaif.c index 39cc9b620a..e4f80ad228 100644 --- a/usr/src/cmd/mdb/intel/kmdb/kaif.c +++ b/usr/src/cmd/mdb/intel/kmdb/kaif.c @@ -296,12 +296,12 @@ kaif_brkpt_arm(uintptr_t addr, mdb_instr_t *instrp) return (set_errno(EMDB_TGTNOTSUP)); } - if (mdb_tgt_vread(mdb.m_target, instrp, sizeof (mdb_instr_t), addr) != - sizeof (mdb_instr_t)) + if (mdb_tgt_aread(mdb.m_target, MDB_TGT_AS_VIRT_I, instrp, + sizeof (mdb_instr_t), addr) != sizeof (mdb_instr_t)) return (-1); /* errno is set for us */ - if (mdb_tgt_vwrite(mdb.m_target, &bkpt, sizeof (mdb_instr_t), addr) != - sizeof (mdb_instr_t)) + if (mdb_tgt_awrite(mdb.m_target, MDB_TGT_AS_VIRT_I, &bkpt, + sizeof (mdb_instr_t), addr) != sizeof (mdb_instr_t)) return (-1); /* errno is set for us */ return (0); @@ -310,8 +310,8 @@ kaif_brkpt_arm(uintptr_t addr, mdb_instr_t *instrp) static int kaif_brkpt_disarm(uintptr_t addr, mdb_instr_t instrp) { - if (mdb_tgt_vwrite(mdb.m_target, &instrp, sizeof (mdb_instr_t), addr) != - sizeof (mdb_instr_t)) + if (mdb_tgt_awrite(mdb.m_target, MDB_TGT_AS_VIRT_I, &instrp, + sizeof (mdb_instr_t), addr) != sizeof (mdb_instr_t)) return (-1); /* errno is set for us */ return (0); @@ -486,7 +486,7 @@ kaif_step(void) } if ((npc = mdb_dis_nextins(mdb.m_disasm, mdb.m_target, - MDB_TGT_AS_VIRT, pc)) == pc) { + MDB_TGT_AS_VIRT_I, pc)) == pc) { warn("failed to decode instruction at %a for step\n", pc); return (set_errno(EINVAL)); } @@ -498,8 +498,8 @@ kaif_step(void) * versus their 64-bit counterparts. */ do { - if (mdb_tgt_vread(mdb.m_target, &instr, sizeof (mdb_instr_t), - pc + pcoff) != sizeof (mdb_instr_t)) { + if (mdb_tgt_aread(mdb.m_target, MDB_TGT_AS_VIRT_I, &instr, + sizeof (mdb_instr_t), pc + pcoff) != sizeof (mdb_instr_t)) { warn("failed to read at %p for step", (void *)(pc + pcoff)); return (-1); @@ -518,8 +518,8 @@ kaif_step(void) return (set_errno(EMDB_TGTNOTSUP)); case M_ESC: - if (mdb_tgt_vread(mdb.m_target, &instr, sizeof (mdb_instr_t), - pc + pcoff) != sizeof (mdb_instr_t)) { + if (mdb_tgt_aread(mdb.m_target, MDB_TGT_AS_VIRT_I, &instr, + sizeof (mdb_instr_t), pc + pcoff) != sizeof (mdb_instr_t)) { warn("failed to read at %p for step", (void *)(pc + pcoff)); return (-1); @@ -568,8 +568,8 @@ kaif_step(void) (void) kmdb_dpi_get_register("sp", &sp); (void) kmdb_dpi_get_register(FLAGS_REG_NAME, &fl); - if (mdb_tgt_vread(mdb.m_target, &newfl, sizeof (kreg_t), - sp) != sizeof (kreg_t)) { + if (mdb_tgt_aread(mdb.m_target, MDB_TGT_AS_VIRT_S, &newfl, + sizeof (kreg_t), sp) != sizeof (kreg_t)) { warn("failed to read " FLAGS_REG_NAME " at %p for popfl step\n", (void *)sp); return (set_errno(EMDB_TGTNOTSUP)); /* XXX ? */ @@ -577,8 +577,8 @@ kaif_step(void) fl = (fl & ~KREG_EFLAGS_IF_MASK) | KREG_EFLAGS_TF_MASK; - if (mdb_tgt_vwrite(mdb.m_target, &fl, sizeof (kreg_t), - sp) != sizeof (kreg_t)) { + if (mdb_tgt_awrite(mdb.m_target, MDB_TGT_AS_VIRT_S, &fl, + sizeof (kreg_t), sp) != sizeof (kreg_t)) { warn("failed to update " FLAGS_REG_NAME " at %p for popfl step\n", (void *)sp); return (set_errno(EMDB_TGTNOTSUP)); /* XXX ? */ @@ -617,8 +617,8 @@ kaif_step(void) */ (void) kmdb_dpi_get_register("sp", &sp); - if (mdb_tgt_vwrite(mdb.m_target, &oldfl, sizeof (kreg_t), - sp) != sizeof (kreg_t)) { + if (mdb_tgt_awrite(mdb.m_target, MDB_TGT_AS_VIRT_S, &oldfl, + sizeof (kreg_t), sp) != sizeof (kreg_t)) { warn("failed to update pushed " FLAGS_REG_NAME " at %p after pushfl step\n", (void *)sp); return (set_errno(EMDB_TGTNOTSUP)); /* XXX ? */ diff --git a/usr/src/cmd/mdb/intel/mdb/kvm_amd64dep.c b/usr/src/cmd/mdb/intel/mdb/kvm_amd64dep.c index f3352b6e21..0382c7e0fb 100644 --- a/usr/src/cmd/mdb/intel/mdb/kvm_amd64dep.c +++ b/usr/src/cmd/mdb/intel/mdb/kvm_amd64dep.c @@ -46,6 +46,7 @@ #include <mdb/mdb_modapi.h> #include <mdb/mdb_conf.h> #include <mdb/mdb_kreg_impl.h> +#include <mdb/mdb_isautil.h> #include <mdb/mdb_amd64util.h> #include <mdb/kvm_isadep.h> #include <mdb/mdb_kvm.h> diff --git a/usr/src/cmd/mdb/intel/mdb/kvm_ia32dep.c b/usr/src/cmd/mdb/intel/mdb/kvm_ia32dep.c index 2dfced82d3..7a6ecaeb6b 100644 --- a/usr/src/cmd/mdb/intel/mdb/kvm_ia32dep.c +++ b/usr/src/cmd/mdb/intel/mdb/kvm_ia32dep.c @@ -45,6 +45,7 @@ #include <mdb/mdb_modapi.h> #include <mdb/mdb_conf.h> #include <mdb/mdb_kreg_impl.h> +#include <mdb/mdb_isautil.h> #include <mdb/mdb_ia32util.h> #include <mdb/kvm_isadep.h> #include <mdb/mdb_kvm.h> diff --git a/usr/src/cmd/mdb/intel/mdb/mdb_amd64util.c b/usr/src/cmd/mdb/intel/mdb/mdb_amd64util.c index 14c81f47fd..7740a82d8f 100644 --- a/usr/src/cmd/mdb/intel/mdb/mdb_amd64util.c +++ b/usr/src/cmd/mdb/intel/mdb/mdb_amd64util.c @@ -39,6 +39,7 @@ #include <mdb/mdb_kreg_impl.h> #include <mdb/mdb_debug.h> #include <mdb/mdb_modapi.h> +#include <mdb/mdb_isautil.h> #include <mdb/mdb_amd64util.h> #include <mdb/mdb_ctf.h> #include <mdb/mdb_err.h> @@ -244,7 +245,8 @@ mdb_amd64_kvm_stack_iter(mdb_tgt_t *t, const mdb_tgt_gregset_t *gsp, while (fp != 0) { int args_style = 0; - if (mdb_tgt_vread(t, &fr, sizeof (fr), fp) != sizeof (fr)) { + if (mdb_tgt_aread(t, MDB_TGT_AS_VIRT_S, &fr, sizeof (fr), fp) != + sizeof (fr)) { err = EMDB_NOMAP; goto badfp; } @@ -259,8 +261,9 @@ mdb_amd64_kvm_stack_iter(mdb_tgt_t *t, const mdb_tgt_gregset_t *gsp, if (advance_tortoise != 0) { struct fr tfr; - if (mdb_tgt_vread(t, &tfr, sizeof (tfr), - tortoise_fp) != sizeof (tfr)) { + if (mdb_tgt_aread(t, MDB_TGT_AS_VIRT_S, &tfr, + sizeof (tfr), tortoise_fp) != + sizeof (tfr)) { err = EMDB_NOMAP; goto badfp; } @@ -330,7 +333,8 @@ mdb_amd64_kvm_stack_iter(mdb_tgt_t *t, const mdb_tgt_gregset_t *gsp, insnsize = MIN(MIN(s.st_size, SAVEARGS_INSN_SEQ_LEN), pc - s.st_value); - if (mdb_tgt_vread(t, ins, insnsize, s.st_value) != insnsize) + if (mdb_tgt_aread(t, MDB_TGT_AS_VIRT_I, ins, insnsize, + s.st_value) != insnsize) argc = 0; if ((argc != 0) && @@ -349,8 +353,8 @@ mdb_amd64_kvm_stack_iter(mdb_tgt_t *t, const mdb_tgt_gregset_t *gsp, if (args_style == SAVEARGS_STRUCT_ARGS) size += sizeof (long); - if (mdb_tgt_vread(t, fr_argv, size, (fp - size)) - != size) + if (mdb_tgt_aread(t, MDB_TGT_AS_VIRT_S, fr_argv, size, + (fp - size)) != size) return (-1); /* errno has been set for us */ /* @@ -369,7 +373,8 @@ mdb_amd64_kvm_stack_iter(mdb_tgt_t *t, const mdb_tgt_gregset_t *gsp, sizeof (fr_argv) - (reg_argc * sizeof (long))); - if (mdb_tgt_vread(t, &fr_argv[reg_argc], size, + if (mdb_tgt_aread(t, MDB_TGT_AS_VIRT_S, + &fr_argv[reg_argc], size, fp + sizeof (fr)) != size) return (-1); /* errno has been set */ } @@ -434,14 +439,15 @@ mdb_amd64_step_out(mdb_tgt_t *t, uintptr_t *p, kreg_t pc, kreg_t fp, kreg_t sp, if (pc == s.st_value && curinstr == M_PUSHQ_RBP) fp = sp - 8; else if (pc == s.st_value + 1 && curinstr == M_REX_W) { - if (mdb_tgt_vread(t, &curinstr, sizeof (curinstr), - pc + 1) == sizeof (curinstr) && curinstr == - M_MOVL_RBP) + if (mdb_tgt_aread(t, MDB_TGT_AS_VIRT_I, &curinstr, + sizeof (curinstr), pc + 1) == sizeof (curinstr) && + curinstr == M_MOVL_RBP) fp = sp; } } - if (mdb_tgt_vread(t, &fr, sizeof (fr), fp) == sizeof (fr)) { + if (mdb_tgt_aread(t, MDB_TGT_AS_VIRT_S, &fr, sizeof (fr), fp) == + sizeof (fr)) { *p = fr.fr_savpc; return (0); } @@ -476,8 +482,8 @@ mdb_amd64_next(mdb_tgt_t *t, uintptr_t *p, kreg_t pc, mdb_instr_t curinstr) /* Skip the rex prefix, if any */ callpc = pc; while (curinstr >= M_REX_LO && curinstr <= M_REX_HI) { - if (mdb_tgt_vread(t, &curinstr, sizeof (curinstr), ++callpc) != - sizeof (curinstr)) + if (mdb_tgt_aread(t, MDB_TGT_AS_VIRT_I, &curinstr, + sizeof (curinstr), ++callpc) != sizeof (curinstr)) return (-1); /* errno is set for us */ } @@ -486,7 +492,8 @@ mdb_amd64_next(mdb_tgt_t *t, uintptr_t *p, kreg_t pc, mdb_instr_t curinstr) return (set_errno(EAGAIN)); } - if ((npc = mdb_dis_nextins(mdb.m_disasm, t, MDB_TGT_AS_VIRT, pc)) == pc) + npc = mdb_dis_nextins(mdb.m_disasm, t, MDB_TGT_AS_VIRT_I, pc); + if (npc == pc) return (-1); /* errno is set for us */ *p = npc; diff --git a/usr/src/cmd/mdb/intel/mdb/mdb_amd64util.h b/usr/src/cmd/mdb/intel/mdb/mdb_amd64util.h index f8c6097cef..b3f060bf05 100644 --- a/usr/src/cmd/mdb/intel/mdb/mdb_amd64util.h +++ b/usr/src/cmd/mdb/intel/mdb/mdb_amd64util.h @@ -22,12 +22,13 @@ * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ +/* + * Copyright (c) 2018, Joyent, Inc. All rights reserved. + */ #ifndef _MDB_AMD64UTIL_H #define _MDB_AMD64UTIL_H -#pragma ident "%Z%%M% %I% %E% SMI" - #include <mdb/mdb_kreg.h> #include <mdb/mdb_target_impl.h> @@ -35,8 +36,6 @@ extern "C" { #endif -typedef uchar_t mdb_instr_t; - extern const mdb_tgt_regdesc_t mdb_amd64_kregs[]; extern void mdb_amd64_printregs(const mdb_tgt_gregset_t *); diff --git a/usr/src/cmd/mdb/intel/mdb/mdb_bhyve.c b/usr/src/cmd/mdb/intel/mdb/mdb_bhyve.c new file mode 100644 index 0000000000..9477bf5056 --- /dev/null +++ b/usr/src/cmd/mdb/intel/mdb/mdb_bhyve.c @@ -0,0 +1,1461 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright 2019 Joyent, Inc. + */ + +/* + * bhyve target + * + * The bhyve target is used to examine and manipulate a bhyve VM. Access to + * a bhyve VM is provided by libvmm, which itself uses libvmmapi, which uses + * the vmm driver's ioctl interface to carry out requests. + * + * The bhyve target does not know about threads or processes, but it handles + * multiple vCPUs and can switch between them. Execution control is currently + * limited to completely stopping or resuming all vCPUs of a VM, or single- + * stepping a particular vCPU while all other vCPUs remain stopped. Breakpoints + * are not implemented yet, and as such step-out and step-over don't work yet. + * All known x86 instruction sets are support, legacy IA-16, IA-32 and AMD64. + * The current CPU instruction set is automatically determined by parsing the + * code segment (CS) attributes in the current vCPU. + * + * All of the VMs physical memory and device memory segments are mapped R/W + * into mdb's address space by libvmm. All accesses to those memory are + * facilitated through libvmm calls, which may include virtual address + * translation according to the current vCPU mode. Both real-mode and protected- + * mode segmentation are understood and used for translating virtual addresses + * into linear addresses, which may further be translated using 2-level, 3-level + * or 4-level paging. + * + * To handle disassembly and stack tracing properly when segmentation is used by + * a vCPU (always in real mode, sometimes in protected mode) the bhyve target + * has a notion of three virtual address spaces used for reading/writing memory: + * - MDB_TGT_AS_VIRT, the default virtual address space uses the DS segment + * by default, but this default can be changed with the ::defseg dcmd. + * - MDB_TGT_AS_VIRT_I, the virtual address space for instructions always + * uses the code segment (CS) for translation + * - MDB_TGT_AS_VIRT_S, the virtual address space for the stack always uses + * the stack segment (SS) for translation + * + * Register printing and stack tracing is using the common x86 ISA-specific code + * in IA-32 and AMD64 modes. There is no stack tracing for IA-16 mode yet. + * + * Todo: + * - support for breakpoint, step-out, and step-over + * - support for x86 stack tracing + */ +#include <mdb/mdb_conf.h> +#include <mdb/mdb_err.h> +#include <mdb/mdb_signal.h> +#include <mdb/mdb_modapi.h> +#include <mdb/mdb_io_impl.h> +#include <mdb/mdb_kreg_impl.h> +#include <mdb/mdb_target_impl.h> +#include <mdb/mdb_isautil.h> +#include <mdb/mdb_amd64util.h> +#include <mdb/mdb_ia32util.h> +#include <mdb/mdb_x86util.h> +#include <mdb/mdb.h> + +#include <sys/controlregs.h> +#include <sys/debugreg.h> +#include <sys/sysmacros.h> +#include <sys/note.h> +#include <unistd.h> +#include <inttypes.h> + +#include <libvmm.h> + +#define MDB_DEF_PROMPT "[%<_cpuid>]> " + +typedef struct bhyve_data { + vmm_t *bd_vmm; + uint_t bd_curcpu; + int bd_defseg; + + /* must be last */ + char bd_name[]; +} bhyve_data_t; + + +const mdb_tgt_regdesc_t bhyve_kregs[] = { + { "rdi", KREG_RDI, MDB_TGT_R_EXPORT }, + { "edi", KREG_RDI, MDB_TGT_R_EXPORT | MDB_TGT_R_32 }, + { "di", KREG_RDI, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, + { "dil", KREG_RDI, MDB_TGT_R_EXPORT | MDB_TGT_R_8L }, + { "rsi", KREG_RSI, MDB_TGT_R_EXPORT }, + { "esi", KREG_RSI, MDB_TGT_R_EXPORT | MDB_TGT_R_32 }, + { "si", KREG_RSI, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, + { "sil", KREG_RSI, MDB_TGT_R_EXPORT | MDB_TGT_R_8L }, + { "rdx", KREG_RDX, MDB_TGT_R_EXPORT }, + { "edx", KREG_RDX, MDB_TGT_R_EXPORT | MDB_TGT_R_32 }, + { "dx", KREG_RDX, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, + { "dh", KREG_RDX, MDB_TGT_R_EXPORT | MDB_TGT_R_8H }, + { "dl", KREG_RDX, MDB_TGT_R_EXPORT | MDB_TGT_R_8L }, + { "rcx", KREG_RCX, MDB_TGT_R_EXPORT }, + { "ecx", KREG_RCX, MDB_TGT_R_EXPORT | MDB_TGT_R_32 }, + { "cx", KREG_RCX, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, + { "ch", KREG_RCX, MDB_TGT_R_EXPORT | MDB_TGT_R_8H }, + { "cl", KREG_RCX, MDB_TGT_R_EXPORT | MDB_TGT_R_8L }, + { "r8", KREG_R8, MDB_TGT_R_EXPORT }, + { "r8d", KREG_R8, MDB_TGT_R_EXPORT | MDB_TGT_R_32 }, + { "r8w", KREG_R8, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, + { "r8l", KREG_R8, MDB_TGT_R_EXPORT | MDB_TGT_R_8L }, + { "r9", KREG_R9, MDB_TGT_R_EXPORT }, + { "r9d", KREG_R8, MDB_TGT_R_EXPORT | MDB_TGT_R_32 }, + { "r9w", KREG_R8, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, + { "r9l", KREG_R8, MDB_TGT_R_EXPORT | MDB_TGT_R_8L }, + { "rax", KREG_RAX, MDB_TGT_R_EXPORT }, + { "eax", KREG_RAX, MDB_TGT_R_EXPORT | MDB_TGT_R_32 }, + { "ax", KREG_RAX, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, + { "ah", KREG_RAX, MDB_TGT_R_EXPORT | MDB_TGT_R_8H }, + { "al", KREG_RAX, MDB_TGT_R_EXPORT | MDB_TGT_R_8L }, + { "rbx", KREG_RBX, MDB_TGT_R_EXPORT }, + { "ebx", KREG_RBX, MDB_TGT_R_EXPORT | MDB_TGT_R_32 }, + { "bx", KREG_RBX, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, + { "bh", KREG_RBX, MDB_TGT_R_EXPORT | MDB_TGT_R_8H }, + { "bl", KREG_RBX, MDB_TGT_R_EXPORT | MDB_TGT_R_8L }, + { "rbp", KREG_RBP, MDB_TGT_R_EXPORT }, + { "ebp", KREG_RBP, MDB_TGT_R_EXPORT | MDB_TGT_R_32 }, + { "bp", KREG_RBP, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, + { "bpl", KREG_RBP, MDB_TGT_R_EXPORT | MDB_TGT_R_8L }, + { "r10", KREG_R10, MDB_TGT_R_EXPORT }, + { "r10d", KREG_R10, MDB_TGT_R_EXPORT | MDB_TGT_R_32 }, + { "r10w", KREG_R10, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, + { "r10l", KREG_R10, MDB_TGT_R_EXPORT | MDB_TGT_R_8L }, + { "r11", KREG_R11, MDB_TGT_R_EXPORT }, + { "r11d", KREG_R11, MDB_TGT_R_EXPORT | MDB_TGT_R_32 }, + { "r11w", KREG_R11, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, + { "r11l", KREG_R11, MDB_TGT_R_EXPORT | MDB_TGT_R_8L }, + { "r12", KREG_R12, MDB_TGT_R_EXPORT }, + { "r12d", KREG_R12, MDB_TGT_R_EXPORT | MDB_TGT_R_32 }, + { "r12w", KREG_R12, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, + { "r12l", KREG_R12, MDB_TGT_R_EXPORT | MDB_TGT_R_8L }, + { "r13", KREG_R13, MDB_TGT_R_EXPORT }, + { "r13d", KREG_R13, MDB_TGT_R_EXPORT | MDB_TGT_R_32 }, + { "r13w", KREG_R13, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, + { "r13l", KREG_R13, MDB_TGT_R_EXPORT | MDB_TGT_R_8L }, + { "r14", KREG_R14, MDB_TGT_R_EXPORT }, + { "r14d", KREG_R14, MDB_TGT_R_EXPORT | MDB_TGT_R_32 }, + { "r14w", KREG_R14, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, + { "r14l", KREG_R14, MDB_TGT_R_EXPORT | MDB_TGT_R_8L }, + { "r15", KREG_R15, MDB_TGT_R_EXPORT }, + { "r15d", KREG_R15, MDB_TGT_R_EXPORT | MDB_TGT_R_32 }, + { "r15w", KREG_R15, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, + { "r15l", KREG_R15, MDB_TGT_R_EXPORT | MDB_TGT_R_8L }, + { "ds", KREG_DS, MDB_TGT_R_EXPORT }, + { "es", KREG_ES, MDB_TGT_R_EXPORT }, + { "fs", KREG_FS, MDB_TGT_R_EXPORT }, + { "gs", KREG_GS, MDB_TGT_R_EXPORT }, + { "rip", KREG_RIP, MDB_TGT_R_EXPORT }, + { "cs", KREG_CS, MDB_TGT_R_EXPORT }, + { "rflags", KREG_RFLAGS, MDB_TGT_R_EXPORT }, + { "eflags", KREG_RFLAGS, MDB_TGT_R_EXPORT | MDB_TGT_R_32 }, + { "rsp", KREG_RSP, MDB_TGT_R_EXPORT }, + { "esp", KREG_RSP, MDB_TGT_R_EXPORT | MDB_TGT_R_32 }, + { "sp", KREG_RSP, MDB_TGT_R_EXPORT | MDB_TGT_R_16 }, + { "spl", KREG_RSP, MDB_TGT_R_EXPORT | MDB_TGT_R_8L }, + { "ss", KREG_SS, MDB_TGT_R_EXPORT }, + { "cr2", KREG_CR2, MDB_TGT_R_EXPORT }, + { "cr3", KREG_CR3, MDB_TGT_R_EXPORT }, + { NULL, 0, 0 } +}; + +static const char *segments[] = { "CS", "DS", "ES", "FS", "GS", "SS" }; + + +/*ARGSUSED*/ +static uintmax_t +bhyve_cpuid_get(const mdb_var_t *v) +{ + bhyve_data_t *bd = mdb.m_target->t_data; + + return (bd->bd_curcpu); +} + +static const mdb_nv_disc_t bhyve_cpuid_disc = { + .disc_get = bhyve_cpuid_get +}; + + +static uintmax_t +bhyve_reg_get(const mdb_var_t *v) +{ + mdb_tgt_reg_t r = 0; + + if (mdb_tgt_getareg(MDB_NV_COOKIE(v), 0, mdb_nv_get_name(v), &r) == -1) + mdb_warn("failed to get %%%s register", mdb_nv_get_name(v)); + + return (r); +} + +static void +bhyve_reg_set(mdb_var_t *v, uintmax_t r) +{ + if (mdb_tgt_putareg(MDB_NV_COOKIE(v), 0, mdb_nv_get_name(v), r) == -1) + mdb_warn("failed to modify %%%s register", mdb_nv_get_name(v)); +} + +static const mdb_nv_disc_t bhyve_reg_disc = { + .disc_set = bhyve_reg_set, + .disc_get = bhyve_reg_get +}; + +static int +bhyve_get_gregset(bhyve_data_t *bd, int cpu, mdb_tgt_gregset_t *gregs) +{ + vmm_desc_t fs, gs; + + /* + * Register numbers to get, the order must match the definitions of + * KREG_* in mdb_kreg.h so that we get a proper mdb_tgt_gregset_t + * that the register printing functions will understand. + * + * There are a few fields in mdb_tgt_gregset_t that can't be accessed + * with vmm_get_regset(), either because they don't exist in bhyve or + * or because they need to be accessed with vmm_get_desc(). For these + * cases we ask for RAX instead and fill it with 0 or the real value, + * respectively. + */ + static const int regnums[] = { + KREG_RAX, /* dummy for SAVFP */ + KREG_RAX, /* dummy for SAVFP */ + KREG_RDI, + KREG_RSI, + KREG_RDX, + KREG_RCX, + KREG_R8, + KREG_R9, + KREG_RAX, + KREG_RBX, + KREG_RBP, + KREG_R10, + KREG_R11, + KREG_R12, + KREG_R13, + KREG_R14, + KREG_R15, + KREG_RAX, /* dummy for FSBASE */ + KREG_RAX, /* dummy for GSBASE */ + KREG_RAX, /* dummy for KGSBASE */ + KREG_CR2, + KREG_CR3, + KREG_DS, + KREG_ES, + KREG_FS, + KREG_GS, + KREG_RAX, /* dummy for TRAPNO */ + KREG_RAX, /* dummy for ERR */ + KREG_RIP, + KREG_CS, + KREG_RFLAGS, + KREG_RSP, + KREG_SS + }; + + if (vmm_get_regset(bd->bd_vmm, cpu, KREG_NGREG, regnums, + &gregs->kregs[0]) != 0) { + mdb_warn("failed to get general-purpose registers for CPU %d", + cpu); + return (-1); + } + + if (vmm_get_desc(bd->bd_vmm, cpu, VMM_DESC_FS, &fs) != 0 || + vmm_get_desc(bd->bd_vmm, cpu, VMM_DESC_GS, &gs) != 0) { + mdb_warn("failed to get FS/GS descriptors for CPU %d", cpu); + return (-1); + } + + gregs->kregs[KREG_SAVFP] = 0; + gregs->kregs[KREG_SAVPC] = 0; + gregs->kregs[KREG_KGSBASE] = 0; + gregs->kregs[KREG_TRAPNO] = 0; + gregs->kregs[KREG_ERR] = 0; + + gregs->kregs[KREG_FSBASE] = fs.vd_base; + gregs->kregs[KREG_GSBASE] = gs.vd_base; + + return (0); +} + +static int +bhyve_cpuregs_dcmd(uintptr_t addr, uint_t flags, int argc, + const mdb_arg_t *argv) +{ + bhyve_data_t *bd = mdb.m_target->t_data; + uint64_t cpu = bd->bd_curcpu; + mdb_tgt_gregset_t gregs; + int i; + + + if (flags & DCMD_ADDRSPEC) { + if (argc != 0) + return (DCMD_USAGE); + + cpu = (uint64_t)addr; + } + + i = mdb_getopts(argc, argv, 'c', MDB_OPT_UINT64, &cpu, NULL); + + argc -= i; + argv += i; + + if (argc != 0) + return (DCMD_USAGE); + + if (cpu >= vmm_ncpu(bd->bd_vmm)) { + mdb_warn("no such CPU\n"); + return (DCMD_ERR); + } + + if (bhyve_get_gregset(bd, cpu, &gregs) != 0) + return (DCMD_ERR); + + + switch (vmm_vcpu_isa(bd->bd_vmm, cpu)) { + case VMM_ISA_64: + mdb_amd64_printregs(&gregs); + break; + case VMM_ISA_32: + case VMM_ISA_16: + mdb_ia32_printregs(&gregs); + break; + default: + mdb_warn("CPU %d mode unknown", cpu); + return (DCMD_ERR); + } + + return (0); +} + +static int +bhyve_regs_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) +{ + if ((flags & DCMD_ADDRSPEC) || argc != 0) + return (DCMD_USAGE); + + return (bhyve_cpuregs_dcmd(addr, flags, argc, argv)); +} + +static int +bhyve_stack_common(uintptr_t addr, uint_t flags, int argc, + const mdb_arg_t *argv, int vcpu, boolean_t verbose) +{ + bhyve_data_t *bd = mdb.m_target->t_data; + void *arg = (void *)(uintptr_t)mdb.m_nargs; + + mdb_tgt_gregset_t gregs; + mdb_tgt_stack_f *func; + + if (vcpu == -1) + vcpu = bd->bd_curcpu; + + if (flags & DCMD_ADDRSPEC) { + bzero(&gregs, sizeof (gregs)); + gregs.kregs[KREG_RBP] = addr; + } else if (bhyve_get_gregset(bd, vcpu, &gregs) != 0) + return (DCMD_ERR); + + switch (vmm_vcpu_isa(bd->bd_vmm, vcpu)) { + case VMM_ISA_64: + func = verbose ? mdb_amd64_kvm_framev : mdb_amd64_kvm_frame; + (void) mdb_amd64_kvm_stack_iter(mdb.m_target, &gregs, func, + arg); + break; + case VMM_ISA_32: + func = verbose ? mdb_ia32_kvm_framev : mdb_amd64_kvm_frame; + (void) mdb_ia32_kvm_stack_iter(mdb.m_target, &gregs, func, arg); + break; + case VMM_ISA_16: + mdb_warn("IA16 stack tracing not implemented\n"); + return (DCMD_ERR); + default: + mdb_warn("CPU %d mode unknown", vcpu); + return (DCMD_ERR); + } + + return (DCMD_OK); +} + +static int +bhyve_cpustack_dcmd(uintptr_t addr, uint_t flags, int argc, + const mdb_arg_t *argv) +{ + bhyve_data_t *bd = mdb.m_target->t_data; + uint64_t cpu = bd->bd_curcpu; + boolean_t verbose; + int i; + + if (flags & DCMD_ADDRSPEC) { + if (argc != 0) + return (DCMD_USAGE); + + if (addr < vmm_ncpu(bd->bd_vmm)) { + cpu = (uint64_t)addr; + flags &= ~DCMD_ADDRSPEC; + } + } + + i = mdb_getopts(argc, argv, + 'c', MDB_OPT_UINT64, &cpu, + 'v', MDB_OPT_SETBITS, 1, &verbose, + NULL); + + argc -= i; + argv += i; + + if (argc != 0) + return (DCMD_USAGE); + + return (bhyve_stack_common(addr, flags, argc, argv, cpu, verbose)); +} + +static int +bhyve_stack_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) +{ + return (bhyve_stack_common(addr, flags, argc, argv, -1, B_FALSE)); +} + +static int +bhyve_stackv_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) +{ + return (bhyve_stack_common(addr, flags, argc, argv, -1, B_TRUE)); +} + +static int +bhyve_stackr_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) +{ + return (bhyve_stack_common(addr, flags, argc, argv, -1, B_TRUE)); +} + +static int +bhyve_status_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) +{ + bhyve_data_t *bd = mdb.m_target->t_data; + vmm_mode_t mode; + vmm_isa_t isa; + + static const char *modes[] = { + "unknown mode", + "real mode", + "protected mode, no PAE", + "protected mode, PAE", + "long mode" + }; + static const char *isas[] = { + "unknown ISA", + "IA16", + "IA32", + "AMD64" + }; + + if ((flags & DCMD_ADDRSPEC) || argc != 0) + return (DCMD_USAGE); + + mode = vmm_vcpu_mode(bd->bd_vmm, bd->bd_curcpu); + isa = vmm_vcpu_isa(bd->bd_vmm, bd->bd_curcpu); + + mdb_printf("debugging live VM '%s'\n", bd->bd_name); + mdb_printf("VM memory size: %d MB\n", + vmm_memsize(bd->bd_vmm) / 1024 / 1024); + mdb_printf("vCPUs: %d\n", vmm_ncpu(bd->bd_vmm)); + mdb_printf("current CPU: %d (%s, %s)\n", bd->bd_curcpu, modes[mode], + isas[isa]); + mdb_printf("default segment: %s", + segments[bd->bd_defseg - VMM_DESC_CS]); + + return (DCMD_OK); +} + + +static int +bhyve_sysregs_dcmd(uintptr_t addr, uint_t flags, int argc, + const mdb_arg_t *argv) +{ + bhyve_data_t *bd = mdb.m_target->t_data; + uint64_t cpu = bd->bd_curcpu; + int ret = DCMD_ERR; + struct sysregs sregs; + int i; + + /* + * This array must use the order of the elements of struct sysregs. + */ + static const int regnums[] = { + VMM_REG_CR0, + VMM_REG_CR2, + VMM_REG_CR3, + VMM_REG_CR4, + VMM_REG_DR0, + VMM_REG_DR1, + VMM_REG_DR2, + VMM_REG_DR3, + VMM_REG_DR6, + VMM_REG_DR7, + VMM_REG_EFER, + VMM_REG_PDPTE0, + VMM_REG_PDPTE1, + VMM_REG_PDPTE2, + VMM_REG_PDPTE3, + VMM_REG_INTR_SHADOW + }; + + if (flags & DCMD_ADDRSPEC) { + if (argc != 0) + return (DCMD_USAGE); + + cpu = (uint64_t)addr; + } + + i = mdb_getopts(argc, argv, 'c', MDB_OPT_UINT64, &cpu, NULL); + + argc -= i; + argv += i; + + if (argc != 0) + return (DCMD_USAGE); + + if (cpu >= vmm_ncpu(bd->bd_vmm)) { + mdb_warn("no such CPU\n"); + return (DCMD_ERR); + } + + if (vmm_get_regset(bd->bd_vmm, cpu, ARRAY_SIZE(regnums), regnums, + (uint64_t *)&sregs) != 0) + goto fail; + + if (vmm_get_desc(bd->bd_vmm, cpu, VMM_DESC_GDTR, + (vmm_desc_t *)&sregs.sr_gdtr) != 0 || + vmm_get_desc(bd->bd_vmm, cpu, VMM_DESC_IDTR, + (vmm_desc_t *)&sregs.sr_idtr) != 0 || + vmm_get_desc(bd->bd_vmm, cpu, VMM_DESC_LDTR, + (vmm_desc_t *)&sregs.sr_ldtr) != 0 || + vmm_get_desc(bd->bd_vmm, cpu, VMM_DESC_TR, + (vmm_desc_t *)&sregs.sr_tr) != 0 || + vmm_get_desc(bd->bd_vmm, cpu, VMM_DESC_CS, + (vmm_desc_t *)&sregs.sr_cs) != 0 || + vmm_get_desc(bd->bd_vmm, cpu, VMM_DESC_DS, + (vmm_desc_t *)&sregs.sr_ds) != 0 || + vmm_get_desc(bd->bd_vmm, cpu, VMM_DESC_ES, + (vmm_desc_t *)&sregs.sr_es) != 0 || + vmm_get_desc(bd->bd_vmm, cpu, VMM_DESC_FS, + (vmm_desc_t *)&sregs.sr_fs) != 0 || + vmm_get_desc(bd->bd_vmm, cpu, VMM_DESC_GS, + (vmm_desc_t *)&sregs.sr_gs) != 0 || + vmm_get_desc(bd->bd_vmm, cpu, VMM_DESC_SS, + (vmm_desc_t *)&sregs.sr_ss) != 0) + goto fail; + + mdb_x86_print_sysregs(&sregs, vmm_vcpu_mode(bd->bd_vmm, cpu) == + VMM_MODE_LONG); + + ret = DCMD_OK; + +fail: + if (ret != DCMD_OK) + mdb_warn("failed to get system registers for CPU %d\n", cpu); + return (ret); +} + +static int +bhyve_dbgregs_dcmd(uintptr_t addr, uint_t flags, int argc, + const mdb_arg_t *argv) +{ + bhyve_data_t *bd = mdb.m_target->t_data; + uint64_t cpu = bd->bd_curcpu; + int ret = DCMD_ERR; + vmm_desc_t gdtr, ldtr, idtr, tr, cs, ds, es, fs, gs, ss; + uint64_t *regvals; + int i; + + /* + * This array must use the order of definitions set in libvmm.h + * to make GETREG() work. + */ +#define GETREG(r) (regvals[r - VMM_REG_DR0]) + static const int regnums[] = { + VMM_REG_DR0, + VMM_REG_DR1, + VMM_REG_DR2, + VMM_REG_DR3, + VMM_REG_DR6, + VMM_REG_DR7, + }; + + static const mdb_bitmask_t dr6_flag_bits[] = { + { "DR0", DR_TRAP0, DR_TRAP0 }, + { "DR1", DR_TRAP1, DR_TRAP1 }, + { "DR2", DR_TRAP2, DR_TRAP2 }, + { "DR3", DR_TRAP3, DR_TRAP3 }, + { "debug reg", DR_ICEALSO, DR_ICEALSO }, + { "single step", DR_SINGLESTEP, DR_SINGLESTEP }, + { "task switch", DR_TASKSWITCH, DR_TASKSWITCH }, + { NULL, 0, 0 } + }; + +#define DR_RW(x, m) \ + ((DR_RW_MASK & (m)) << (DR_CONTROL_SHIFT + (x) * DR_CONTROL_SIZE)) +#define DR_LEN(x, m) \ + ((DR_LEN_MASK & (m)) << (DR_CONTROL_SHIFT + (x) * DR_CONTROL_SIZE)) + + static const mdb_bitmask_t dr7_flag_bits[] = { + { "L0", DR_ENABLE0, DR_LOCAL_ENABLE_MASK & DR_ENABLE0 }, + { "G0", DR_ENABLE0, DR_GLOBAL_ENABLE_MASK & DR_ENABLE0 }, + { "L1", DR_ENABLE1, DR_LOCAL_ENABLE_MASK & DR_ENABLE1 }, + { "G1", DR_ENABLE1, DR_GLOBAL_ENABLE_MASK & DR_ENABLE1 }, + { "L2", DR_ENABLE2, DR_LOCAL_ENABLE_MASK & DR_ENABLE2 }, + { "G2", DR_ENABLE2, DR_GLOBAL_ENABLE_MASK & DR_ENABLE2 }, + { "L3", DR_ENABLE3, DR_LOCAL_ENABLE_MASK & DR_ENABLE3 }, + { "G3", DR_ENABLE3, DR_GLOBAL_ENABLE_MASK & DR_ENABLE3 }, + { "LE", DR_LOCAL_SLOWDOWN, DR_LOCAL_SLOWDOWN }, + { "GE", DR_GLOBAL_SLOWDOWN, DR_GLOBAL_SLOWDOWN }, + { "RTM", DR_RTM, DR_RTM }, + { "GD", DR_GENERAL_DETECT, DR_GENERAL_DETECT }, + { "0:X", DR_RW(0, DR_RW_MASK), DR_RW(0, DR_RW_EXECUTE) }, + { "0:W", DR_RW(0, DR_RW_MASK), DR_RW(0, DR_RW_WRITE) }, + { "0:IO", DR_RW(0, DR_RW_MASK), DR_RW(0, DR_RW_IO_RW) }, + { "0:RW", DR_RW(0, DR_RW_MASK), DR_RW(0, DR_RW_READ) }, + { "1:X", DR_RW(1, DR_RW_MASK), DR_RW(1, DR_RW_EXECUTE) }, + { "1:W", DR_RW(1, DR_RW_MASK), DR_RW(1, DR_RW_WRITE) }, + { "1:IO", DR_RW(1, DR_RW_MASK), DR_RW(1, DR_RW_IO_RW) }, + { "1:RW", DR_RW(1, DR_RW_MASK), DR_RW(1, DR_RW_READ) }, + { "2:X", DR_RW(2, DR_RW_MASK), DR_RW(2, DR_RW_EXECUTE) }, + { "2:W", DR_RW(2, DR_RW_MASK), DR_RW(2, DR_RW_WRITE) }, + { "2:IO", DR_RW(2, DR_RW_MASK), DR_RW(2, DR_RW_IO_RW) }, + { "2:RW", DR_RW(2, DR_RW_MASK), DR_RW(2, DR_RW_READ) }, + { "3:X", DR_RW(3, DR_RW_MASK), DR_RW(3, DR_RW_EXECUTE) }, + { "3:W", DR_RW(3, DR_RW_MASK), DR_RW(3, DR_RW_WRITE) }, + { "3:IO", DR_RW(3, DR_RW_MASK), DR_RW(3, DR_RW_IO_RW) }, + { "3:RW", DR_RW(3, DR_RW_MASK), DR_RW(3, DR_RW_READ) }, + { "0:1", DR_LEN(0, DR_LEN_MASK), DR_LEN(0, DR_LEN_1) }, + { "0:2", DR_LEN(0, DR_LEN_MASK), DR_LEN(0, DR_LEN_2) }, + { "0:4", DR_LEN(0, DR_LEN_MASK), DR_LEN(0, DR_LEN_4) }, + { "0:8", DR_LEN(0, DR_LEN_MASK), DR_LEN(0, DR_LEN_8) }, + { "1:1", DR_LEN(1, DR_LEN_MASK), DR_LEN(1, DR_LEN_1) }, + { "1:2", DR_LEN(1, DR_LEN_MASK), DR_LEN(1, DR_LEN_2) }, + { "1:4", DR_LEN(1, DR_LEN_MASK), DR_LEN(1, DR_LEN_4) }, + { "1:8", DR_LEN(1, DR_LEN_MASK), DR_LEN(1, DR_LEN_8) }, + { "2:1", DR_LEN(2, DR_LEN_MASK), DR_LEN(2, DR_LEN_1) }, + { "2:2", DR_LEN(2, DR_LEN_MASK), DR_LEN(2, DR_LEN_2) }, + { "2:4", DR_LEN(2, DR_LEN_MASK), DR_LEN(2, DR_LEN_4) }, + { "2:8", DR_LEN(2, DR_LEN_MASK), DR_LEN(2, DR_LEN_8) }, + { "3:1", DR_LEN(3, DR_LEN_MASK), DR_LEN(3, DR_LEN_1) }, + { "3:2", DR_LEN(3, DR_LEN_MASK), DR_LEN(3, DR_LEN_2) }, + { "3:4", DR_LEN(3, DR_LEN_MASK), DR_LEN(3, DR_LEN_4) }, + { "3:8", DR_LEN(3, DR_LEN_MASK), DR_LEN(3, DR_LEN_8) }, + { NULL, 0, 0 }, + }; + + + if (flags & DCMD_ADDRSPEC) { + if (argc != 0) + return (DCMD_USAGE); + + cpu = (uint64_t)addr; + } + + i = mdb_getopts(argc, argv, 'c', MDB_OPT_UINT64, &cpu, NULL); + + argc -= i; + argv += i; + + if (argc != 0) + return (DCMD_USAGE); + + if (cpu >= vmm_ncpu(bd->bd_vmm)) { + mdb_warn("no such CPU\n"); + return (DCMD_ERR); + } + + regvals = mdb_zalloc(ARRAY_SIZE(regnums) * sizeof (uint64_t), UM_SLEEP); + + if (vmm_get_regset(bd->bd_vmm, cpu, ARRAY_SIZE(regnums), regnums, + regvals) != 0) + goto fail; + + mdb_printf("%%dr0 = 0x%0?p %A\n", + GETREG(VMM_REG_DR0), GETREG(VMM_REG_DR0)); + mdb_printf("%%dr1 = 0x%0?p %A\n", + GETREG(VMM_REG_DR1), GETREG(VMM_REG_DR1)); + mdb_printf("%%dr2 = 0x%0?p %A\n", + GETREG(VMM_REG_DR2), GETREG(VMM_REG_DR2)); + mdb_printf("%%dr3 = 0x%0?p %A\n", + GETREG(VMM_REG_DR3), GETREG(VMM_REG_DR3)); + mdb_printf("%%dr6 = 0x%0lx <%b>\n", + GETREG(VMM_REG_DR6), GETREG(VMM_REG_DR6), dr6_flag_bits); + mdb_printf("%%dr7 = 0x%0lx <%b>\n", + GETREG(VMM_REG_DR7), GETREG(VMM_REG_DR7), dr7_flag_bits); +#undef GETREG + + ret = DCMD_OK; + +fail: + if (ret != DCMD_OK) + mdb_warn("failed to get debug registers for CPU %d\n", cpu); + mdb_free(regvals, ARRAY_SIZE(regnums) * sizeof (uint64_t)); + return (ret); +} + +static int +bhyve_switch_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) +{ + bhyve_data_t *bd = mdb.m_target->t_data; + size_t cpu = (int)addr; + + if (!(flags & DCMD_ADDRSPEC) || argc != 0) + return (DCMD_USAGE); + + if (cpu >= vmm_ncpu(bd->bd_vmm)) { + mdb_warn("no such CPU\n"); + return (DCMD_ERR); + } + + bd->bd_curcpu = cpu; + return (DCMD_OK); + +} + +static int +bhyve_seg2reg(const char *seg) +{ + if (strcasecmp(seg, "cs") == 0) + return (VMM_DESC_CS); + else if (strcasecmp(seg, "ds") == 0) + return (VMM_DESC_DS); + else if (strcasecmp(seg, "es") == 0) + return (VMM_DESC_ES); + else if (strcasecmp(seg, "fs") == 0) + return (VMM_DESC_FS); + else if (strcasecmp(seg, "gs") == 0) + return (VMM_DESC_GS); + else if (strcasecmp(seg, "ss") == 0) + return (VMM_DESC_SS); + else + return (-1); +} + +static int +bhyve_vtol_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) +{ + bhyve_data_t *bd = mdb.m_target->t_data; + int segreg = bd->bd_defseg; + char *seg = ""; + uint64_t laddr; + int i; + + if (!(flags & DCMD_ADDRSPEC)) + return (DCMD_USAGE); + + i = mdb_getopts(argc, argv, 's', MDB_OPT_STR, &seg, NULL); + + argc -= i; + argv += i; + + if (i != 0) { + if (argc != 0) + return (DCMD_USAGE); + + segreg = bhyve_seg2reg(seg); + if (segreg == -1) + return (DCMD_USAGE); + } + + if (vmm_vtol(bd->bd_vmm, bd->bd_curcpu, segreg, addr, &laddr) != 0) { + if (errno == EFAULT) + (void) set_errno(EMDB_NOMAP); + return (DCMD_ERR); + } + + if (flags & DCMD_PIPE_OUT) + mdb_printf("%llr\n", laddr); + else + mdb_printf("virtual %lr mapped to linear %llr\n", addr, laddr); + + return (DCMD_OK); +} + +static int +bhyve_vtop_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) +{ + bhyve_data_t *bd = mdb.m_target->t_data; + int segreg = bd->bd_defseg; + char *seg = ""; + physaddr_t pa; + int i; + + if (!(flags & DCMD_ADDRSPEC)) + return (DCMD_USAGE); + + i = mdb_getopts(argc, argv, 's', MDB_OPT_STR, &seg, NULL); + + argc -= i; + argv += i; + + if (i != 0) { + segreg = bhyve_seg2reg(seg); + if (segreg == -1) + return (DCMD_USAGE); + } + + if (vmm_vtop(bd->bd_vmm, bd->bd_curcpu, segreg, addr, &pa) == -1) { + mdb_warn("failed to get physical mapping"); + return (DCMD_ERR); + } + + if (flags & DCMD_PIPE_OUT) + mdb_printf("%llr\n", pa); + else + mdb_printf("virtual %lr mapped to physical %llr\n", addr, pa); + return (DCMD_OK); +} + +static int +bhyve_defseg_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) +{ + bhyve_data_t *bd = mdb.m_target->t_data; + int segreg = bd->bd_defseg; + char *seg = ""; + int i; + + if (flags & DCMD_ADDRSPEC) + return (DCMD_USAGE); + + i = mdb_getopts(argc, argv, 's', MDB_OPT_STR, &seg, NULL); + + argc -= i; + argv += i; + + if (i != 0) { + if (argc != 0) + return (DCMD_USAGE); + + segreg = bhyve_seg2reg(seg); + if (segreg == -1) + return (DCMD_USAGE); + + bd->bd_defseg = segreg; + } + + mdb_printf("using segment %s for virtual to linear address translation", + segments[bd->bd_defseg - VMM_DESC_CS]); + + return (DCMD_OK); +} + +static const mdb_dcmd_t bhyve_dcmds[] = { + { "$c", NULL, "print stack backtrace", bhyve_stack_dcmd }, + { "$C", NULL, "print stack backtrace", bhyve_stackv_dcmd }, + { "$r", NULL, "print general-purpose registers", bhyve_regs_dcmd }, + { "$?", NULL, "print status and registers", bhyve_regs_dcmd }, + { ":x", ":", "change the active CPU", bhyve_switch_dcmd }, + { "cpustack", "?[-v] [-c cpuid] [cnt]", "print stack backtrace for a " + "specific CPU", bhyve_cpustack_dcmd }, + { "cpuregs", "?[-c cpuid]", "print general-purpose registers for a " + "specific CPU", bhyve_cpuregs_dcmd }, + { "dbgregs", "?[-c cpuid]", "print debug registers for a specific CPU", + bhyve_dbgregs_dcmd }, + { "defseg", "?[-s segment]", "change the default segment used to " + "translate addresses", bhyve_defseg_dcmd }, + { "regs", NULL, "print general-purpose registers", bhyve_regs_dcmd }, + { "stack", NULL, "print stack backtrace", bhyve_stack_dcmd }, + { "stackregs", NULL, "print stack backtrace and registers", + bhyve_stackr_dcmd }, + { "status", NULL, "print summary of current target", + bhyve_status_dcmd }, + { "sysregs", "?[-c cpuid]", "print system registers for a specific CPU", + bhyve_sysregs_dcmd }, + { "switch", ":", "change the active CPU", bhyve_switch_dcmd }, + { "vtol", ":[-s segment]", "print linear mapping of virtual address", + bhyve_vtol_dcmd }, + { "vtop", ":[-s segment]", "print physical mapping of virtual " + "address", bhyve_vtop_dcmd }, + { NULL } +}; + + +/* + * t_setflags: change target flags + */ +static int +bhyve_setflags(mdb_tgt_t *tgt, int flags) +{ + bhyve_data_t *bd = tgt->t_data; + + if (((tgt->t_flags ^ flags) & MDB_TGT_F_RDWR) != 0) { + boolean_t writable = (flags & MDB_TGT_F_RDWR) != 0; + + vmm_unmap(bd->bd_vmm); + if (vmm_map(bd->bd_vmm, writable) != 0) { + mdb_warn("failed to map guest memory"); + return (set_errno(EMDB_TGT)); + } + } + + tgt->t_flags = flags; + + return (0); +} + +/* + * t_activate: activate target + */ +static void +bhyve_activate(mdb_tgt_t *tgt) +{ + mdb_tgt_status_t *tsp = &tgt->t_status; + bhyve_data_t *bd = tgt->t_data; + const char *format; + char buf[BUFSIZ]; + + (void) mdb_set_prompt(MDB_DEF_PROMPT); + + (void) mdb_tgt_register_dcmds(tgt, bhyve_dcmds, MDB_MOD_FORCE); + mdb_tgt_register_regvars(tgt, bhyve_kregs, &bhyve_reg_disc, 0); + + (void) vmm_stop(bd->bd_vmm); + + if (mdb_tgt_status(tgt, tsp) != 0) + return; + + if (tsp->st_pc != 0) { + if (mdb_dis_ins2str(mdb.m_disasm, mdb.m_target, + MDB_TGT_AS_VIRT_I, buf, sizeof (buf), tsp->st_pc) != + tsp->st_pc) + format = "target stopped at:\n%-#16a%8T%s\n"; + else + format = "target stopped at %a:\n"; + mdb_warn(format, tsp->st_pc, buf); + } +} + +/* + * t_deactivate: deactivate target + */ +static void +bhyve_deactivate(mdb_tgt_t *tgt) +{ + bhyve_data_t *bd = tgt->t_data; + const mdb_tgt_regdesc_t *rd; + const mdb_dcmd_t *dc; + + for (rd = bhyve_kregs; rd->rd_name != NULL; rd++) { + mdb_var_t *var; + + if (!(rd->rd_flags & MDB_TGT_R_EXPORT)) + continue; /* didn't export register as variable */ + + if ((var = mdb_nv_lookup(&mdb.m_nv, rd->rd_name)) != NULL) { + var->v_flags &= ~MDB_NV_PERSIST; + mdb_nv_remove(&mdb.m_nv, var); + } + } + + for (dc = bhyve_dcmds; dc->dc_name != NULL; dc++) + if (mdb_module_remove_dcmd(tgt->t_module, dc->dc_name) == -1) + mdb_warn("failed to remove dcmd %s", dc->dc_name); + + (void) vmm_cont(bd->bd_vmm); +} + +/* + * t_name: return name of target + */ +static const char * +bhyve_name(mdb_tgt_t *tgt) +{ + _NOTE(ARGUNUSED(tgt)); + + return ("bhyve"); +} + +/* + * t_destroy: cleanup target private resources + */ +static void +bhyve_destroy(mdb_tgt_t *tgt) +{ + bhyve_data_t *bd = tgt->t_data; + + (void) vmm_cont(bd->bd_vmm); + vmm_unmap(bd->bd_vmm); + vmm_close_vm(bd->bd_vmm); + mdb_free(bd, sizeof (bhyve_data_t)); + tgt->t_data = NULL; +} + +/* + * t_isa: return name of target ISA + */ +const char * +bhyve_isa(mdb_tgt_t *tgt) +{ + _NOTE(ARGUNUSED(tgt)); + + return ("amd64"); +} + +/* + * t_dmodel: return target data model + */ +static int +bhyve_dmodel(mdb_tgt_t *tgt) +{ + _NOTE(ARGUNUSED(tgt)); + + return (MDB_TGT_MODEL_LP64); +} + +/*ARGSUSED*/ +static ssize_t +bhyve_aread(mdb_tgt_t *tgt, mdb_tgt_as_t as, void *buf, size_t nbytes, + mdb_tgt_addr_t addr) +{ + bhyve_data_t *bd = tgt->t_data; + ssize_t cnt; + + switch ((uintptr_t)as) { + case (uintptr_t)MDB_TGT_AS_VIRT: + cnt = vmm_vread(bd->bd_vmm, bd->bd_curcpu, bd->bd_defseg, buf, + nbytes, addr); + break; + + case (uintptr_t)MDB_TGT_AS_VIRT_I: + cnt = vmm_vread(bd->bd_vmm, bd->bd_curcpu, VMM_DESC_CS, buf, + nbytes, addr); + break; + + case (uintptr_t)MDB_TGT_AS_VIRT_S: + cnt = vmm_vread(bd->bd_vmm, bd->bd_curcpu, VMM_DESC_SS, buf, + nbytes, addr); + break; + + case (uintptr_t)MDB_TGT_AS_PHYS: + cnt = vmm_pread(bd->bd_vmm, buf, nbytes, addr); + break; + + case (uintptr_t)MDB_TGT_AS_FILE: + case (uintptr_t)MDB_TGT_AS_IO: + return (set_errno(EMDB_TGTNOTSUP)); + } + + if (errno == EFAULT) + return (set_errno(EMDB_NOMAP)); + + return (cnt); +} + +/*ARGSUSED*/ +static ssize_t +bhyve_awrite(mdb_tgt_t *tgt, mdb_tgt_as_t as, const void *buf, size_t nbytes, + mdb_tgt_addr_t addr) +{ + bhyve_data_t *bd = tgt->t_data; + ssize_t cnt; + + switch ((uintptr_t)as) { + case (uintptr_t)MDB_TGT_AS_VIRT: + cnt = vmm_vwrite(bd->bd_vmm, bd->bd_curcpu, bd->bd_defseg, buf, + nbytes, addr); + break; + + case (uintptr_t)MDB_TGT_AS_VIRT_I: + cnt = vmm_vwrite(bd->bd_vmm, bd->bd_curcpu, VMM_DESC_CS, buf, + nbytes, addr); + break; + + case (uintptr_t)MDB_TGT_AS_VIRT_S: + cnt = vmm_vwrite(bd->bd_vmm, bd->bd_curcpu, VMM_DESC_SS, buf, + nbytes, addr); + break; + + case (uintptr_t)MDB_TGT_AS_PHYS: + cnt = vmm_pwrite(bd->bd_vmm, buf, nbytes, addr); + break; + + case (uintptr_t)MDB_TGT_AS_FILE: + case (uintptr_t)MDB_TGT_AS_IO: + return (set_errno(EMDB_TGTNOTSUP)); + } + + if (errno == EFAULT) + return (set_errno(EMDB_NOMAP)); + + return (cnt); +} + +/* + * t_vread: read from virtual memory + */ +/*ARGSUSED*/ +static ssize_t +bhyve_vread(mdb_tgt_t *tgt, void *buf, size_t nbytes, uintptr_t addr) +{ + return (bhyve_aread(tgt, MDB_TGT_AS_VIRT, buf, nbytes, addr)); +} + +/* + * t_vwrite: write to virtual memory + */ +/*ARGSUSED*/ +static ssize_t +bhyve_vwrite(mdb_tgt_t *tgt, const void *buf, size_t nbytes, uintptr_t addr) +{ + return (bhyve_awrite(tgt, MDB_TGT_AS_VIRT, buf, nbytes, addr)); +} + +/* + * t_pread: read from physical memory + */ +/*ARGSUSED*/ +static ssize_t +bhyve_pread(mdb_tgt_t *tgt, void *buf, size_t nbytes, physaddr_t addr) +{ + return (bhyve_aread(tgt, MDB_TGT_AS_PHYS, buf, nbytes, addr)); +} + +/* + * t_pwrite: write to physical memory + */ +/*ARGSUSED*/ +static ssize_t +bhyve_pwrite(mdb_tgt_t *tgt, const void *buf, size_t nbytes, physaddr_t addr) +{ + return (bhyve_awrite(tgt, MDB_TGT_AS_PHYS, buf, nbytes, addr)); +} + +/* + * t_fread: read from core/object file + */ +/*ARGSUSED*/ +static ssize_t +bhyve_fread(mdb_tgt_t *tgt, void *buf, size_t nbytes, uintptr_t addr) +{ + return (bhyve_aread(tgt, MDB_TGT_AS_FILE, buf, nbytes, addr)); +} + +/* + * t_fwrite: write to core/object file + */ +/*ARGSUSED*/ +static ssize_t +bhyve_fwrite(mdb_tgt_t *tgt, const void *buf, size_t nbytes, uintptr_t addr) +{ + return (bhyve_awrite(tgt, MDB_TGT_AS_FILE, buf, nbytes, addr)); +} + +/* + * t_ioread: read from I/O space + */ +/*ARGSUSED*/ +static ssize_t +bhyve_ioread(mdb_tgt_t *tgt, void *buf, size_t nbytes, uintptr_t addr) +{ + return (bhyve_aread(tgt, MDB_TGT_AS_IO, buf, nbytes, addr)); +} + +/* + * t_iowrite: write to I/O space + */ +/*ARGSUSED*/ +static ssize_t +bhyve_iowrite(mdb_tgt_t *tgt, const void *buf, size_t nbytes, uintptr_t addr) +{ + return (bhyve_awrite(tgt, MDB_TGT_AS_IO, buf, nbytes, addr)); +} + +/* + * t_vtop: translate virtual to physical address + */ +static int +bhyve_vtop(mdb_tgt_t *tgt, mdb_tgt_as_t as, uintptr_t va, physaddr_t *pa) +{ + bhyve_data_t *bd = tgt->t_data; + int seg; + + switch ((uintptr_t)as) { + case (uintptr_t)MDB_TGT_AS_VIRT: + seg = bd->bd_defseg; + break; + + case (uintptr_t)MDB_TGT_AS_VIRT_I: + seg = VMM_DESC_CS; + break; + + case (uintptr_t)MDB_TGT_AS_VIRT_S: + seg = VMM_DESC_SS; + break; + + default: + return (set_errno(EINVAL)); + } + + if (vmm_vtop(bd->bd_vmm, bd->bd_curcpu, seg, va, pa) != 0) { + if (errno == EFAULT) + return (set_errno(EMDB_NOMAP)); + else + return (-1); + } + + return (0); +} + +/* + * t_status: get target status + */ +static int +bhyve_status(mdb_tgt_t *tgt, mdb_tgt_status_t *tsp) +{ + bhyve_data_t *bd = tgt->t_data; + mdb_tgt_reg_t rip; + vmm_desc_t cs; + int ret; + + bzero(tsp, sizeof (mdb_tgt_status_t)); + + ret = vmm_getreg(bd->bd_vmm, bd->bd_curcpu, KREG_RIP, &rip); + if (ret != 0) { + tsp->st_state = MDB_TGT_UNDEAD; + } else { + tsp->st_state = MDB_TGT_STOPPED; + tsp->st_pc = rip; + } + + switch (vmm_vcpu_isa(bd->bd_vmm, bd->bd_curcpu)) { + case VMM_ISA_16: + (void) mdb_dis_select("ia16"); + break; + case VMM_ISA_32: + (void) mdb_dis_select("ia32"); + break; + case VMM_ISA_64: + (void) mdb_dis_select("amd64"); + break; + default: + break; + } + + return (0); +} + +static void +bhyve_sighdl(int sig, siginfo_t *sip, ucontext_t *ucp, mdb_tgt_t *tgt) +{ + mdb_tgt_status_t *tsp = &tgt->t_status; + bhyve_data_t *bd = tgt->t_data; + + switch (sig) { + case SIGINT: + /* + * vmm_stop() may fail if the VM was destroyed while we were + * waiting. This will be handled by mdb_tgt_status(). + */ + (void) vmm_stop(bd->bd_vmm); + (void) mdb_tgt_status(tgt, tsp); + break; + } +} + +/* + * t_step: single-step target + */ +static int +bhyve_step(mdb_tgt_t *tgt, mdb_tgt_status_t *tsp) +{ + bhyve_data_t *bd = tgt->t_data; + int ret; + + ret = vmm_step(bd->bd_vmm, bd->bd_curcpu); + (void) mdb_tgt_status(tgt, tsp); + + return (ret); +} + +/* + * t_cont: continue target execution + * + * Catch SIGINT so that the target can be stopped with Ctrl-C. + */ +static int +bhyve_cont(mdb_tgt_t *tgt, mdb_tgt_status_t *tsp) +{ + bhyve_data_t *bd = tgt->t_data; + mdb_signal_f *intf; + void *intd; + int ret; + + intf = mdb_signal_gethandler(SIGINT, &intd); + (void) mdb_signal_sethandler(SIGINT, (mdb_signal_f *)bhyve_sighdl, tgt); + + if (ret = vmm_cont(bd->bd_vmm) != 0) { + mdb_warn("failed to continue target execution: %d", ret); + return (set_errno(EMDB_TGT)); + } + + tsp->st_state = MDB_TGT_RUNNING; + (void) pause(); + + (void) mdb_signal_sethandler(SIGINT, intf, intd); + (void) mdb_tgt_status(tgt, tsp); + + return (ret); +} + +static int +bhyve_lookup_reg(mdb_tgt_t *tgt, const char *rname) +{ + bhyve_data_t *bd = tgt->t_data; + const mdb_tgt_regdesc_t *rd; + + for (rd = bhyve_kregs; rd->rd_name != NULL; rd++) + if (strcmp(rd->rd_name, rname) == 0) + return (rd->rd_num); + + return (-1); +} + +/* + * t_getareg: get the value of a single register + */ +static int +bhyve_getareg(mdb_tgt_t *tgt, mdb_tgt_tid_t tid, const char *rname, + mdb_tgt_reg_t *rp) +{ + bhyve_data_t *bd = tgt->t_data; + int reg = bhyve_lookup_reg(tgt, rname); + int ret; + + if (reg == -1) + return (set_errno(EMDB_BADREG)); + + ret = vmm_getreg(bd->bd_vmm, bd->bd_curcpu, reg, rp); + if (ret == -1) + return (set_errno(EMDB_BADREG)); + + return (0); +} + +/* + * t_putareg: set the value of a single register + */ +static int +bhyve_putareg(mdb_tgt_t *tgt, mdb_tgt_tid_t tid, const char *rname, + mdb_tgt_reg_t r) +{ + bhyve_data_t *bd = tgt->t_data; + int reg = bhyve_lookup_reg(tgt, rname); + int ret; + + if ((tgt->t_flags & MDB_TGT_F_RDWR) == 0) + return (set_errno(EMDB_TGTRDONLY)); + + if (reg == -1) + return (set_errno(EMDB_BADREG)); + + ret = vmm_setreg(bd->bd_vmm, bd->bd_curcpu, reg, r); + if (ret == -1) + return (set_errno(EMDB_BADREG)); + + return (0); +} + +static const mdb_tgt_ops_t bhyve_ops = { + .t_setflags = bhyve_setflags, + .t_setcontext = (int (*)()) mdb_tgt_notsup, + .t_activate = bhyve_activate, + .t_deactivate = bhyve_deactivate, + .t_periodic = (void (*)()) mdb_tgt_nop, + .t_destroy = bhyve_destroy, + .t_name = bhyve_name, + .t_isa = bhyve_isa, + .t_platform = (const char *(*)()) mdb_conf_platform, + .t_uname = (int (*)()) mdb_tgt_notsup, + .t_dmodel = bhyve_dmodel, + .t_aread = bhyve_aread, + .t_awrite = bhyve_awrite, + .t_vread = bhyve_vread, + .t_vwrite = bhyve_vwrite, + .t_pread = bhyve_pread, + .t_pwrite = bhyve_pwrite, + .t_fread = bhyve_fread, + .t_fwrite = bhyve_fwrite, + .t_ioread = bhyve_ioread, + .t_iowrite = bhyve_iowrite, + .t_vtop = bhyve_vtop, + .t_lookup_by_name = (int (*)()) mdb_tgt_notsup, + .t_lookup_by_addr = (int (*)()) mdb_tgt_notsup, + .t_symbol_iter = (int (*)()) mdb_tgt_notsup, + .t_mapping_iter = (int (*)()) mdb_tgt_notsup, + .t_object_iter = (int (*)()) mdb_tgt_notsup, + .t_addr_to_map = (const mdb_map_t *(*)()) mdb_tgt_null, + .t_name_to_map = (const mdb_map_t *(*)()) mdb_tgt_null, + .t_addr_to_ctf = (struct ctf_file *(*)()) mdb_tgt_null, + .t_name_to_ctf = (struct ctf_file *(*)()) mdb_tgt_null, + .t_status = bhyve_status, + .t_run = (int (*)()) mdb_tgt_notsup, + .t_step = bhyve_step, + .t_step_out = (int (*)()) mdb_tgt_notsup, + .t_next = (int (*)()) mdb_tgt_notsup, + .t_cont = bhyve_cont, + .t_signal = (int (*)()) mdb_tgt_notsup, + .t_add_vbrkpt = (int (*)()) mdb_tgt_null, + .t_add_sbrkpt = (int (*)()) mdb_tgt_null, + .t_add_pwapt = (int (*)()) mdb_tgt_null, + .t_add_vwapt = (int (*)()) mdb_tgt_null, + .t_add_iowapt = (int (*)()) mdb_tgt_null, + .t_add_sysenter = (int (*)()) mdb_tgt_null, + .t_add_sysexit = (int (*)()) mdb_tgt_null, + .t_add_signal = (int (*)()) mdb_tgt_null, + .t_add_fault = (int (*)()) mdb_tgt_null, + .t_getareg = bhyve_getareg, + .t_putareg = bhyve_putareg, + .t_stack_iter = (int (*)()) mdb_tgt_notsup, + .t_auxv = (int (*)()) mdb_tgt_notsup +}; + +int +mdb_bhyve_tgt_create(mdb_tgt_t *tgt, int argc, const char *argv[]) +{ + bhyve_data_t *bd; + vmm_t *vmm = NULL; + boolean_t writable = (tgt->t_flags & MDB_TGT_F_RDWR) != 0; + + if (argc != 1) + return (set_errno(EINVAL)); + + vmm = vmm_open_vm(argv[0]); + if (vmm == NULL) { + mdb_warn("failed to open %s", argv[0]); + return (set_errno(EMDB_TGT)); + } + + if (vmm_map(vmm, writable) != 0) { + mdb_warn("failed to map %s", argv[0]); + vmm_close_vm(vmm); + return (set_errno(EMDB_TGT)); + } + + bd = mdb_zalloc(sizeof (bhyve_data_t) + strlen(argv[0]) + 1, UM_SLEEP); + (void) strcpy(bd->bd_name, argv[0]); + bd->bd_vmm = vmm; + bd->bd_curcpu = 0; + bd->bd_defseg = VMM_DESC_DS; + + tgt->t_ops = &bhyve_ops; + tgt->t_data = bd; + tgt->t_flags |= MDB_TGT_F_ASIO; + + (void) mdb_nv_insert(&mdb.m_nv, "cpuid", &bhyve_cpuid_disc, 0, + MDB_NV_PERSIST | MDB_NV_RDONLY); + + return (0); +} diff --git a/usr/src/cmd/mdb/intel/mdb/mdb_ia32util.c b/usr/src/cmd/mdb/intel/mdb/mdb_ia32util.c index d6db4811b2..22e56a0eda 100644 --- a/usr/src/cmd/mdb/intel/mdb/mdb_ia32util.c +++ b/usr/src/cmd/mdb/intel/mdb/mdb_ia32util.c @@ -23,16 +23,18 @@ * Use is subject to license terms. */ /* - * Copyright (c) 2012, Joyent, Inc. All rights reserved. + * Copyright (c) 2018, Joyent, Inc. All rights reserved. * Copyright 2014 Nexenta Systems, Inc. All rights reserved. */ #include <sys/types.h> +#include <sys/types32.h> #include <sys/reg.h> #include <sys/privregs.h> #include <sys/stack.h> #include <sys/frame.h> +#include <mdb/mdb_isautil.h> #include <mdb/mdb_ia32util.h> #include <mdb/mdb_target_impl.h> #include <mdb/mdb_kreg_impl.h> @@ -41,10 +43,14 @@ #include <mdb/mdb_err.h> #include <mdb/mdb.h> +#ifndef __amd64 /* * We also define an array of register names and their corresponding * array indices. This is used by the getareg and putareg entry points, * and also by our register variable discipline. + * + * When built into an amd64 mdb this won't be used as it's only a subset of + * mdb_amd64_kregs, hence the #ifdef. */ const mdb_tgt_regdesc_t mdb_ia32_kregs[] = { { "savfp", KREG_SAVFP, MDB_TGT_R_EXPORT }, @@ -87,6 +93,7 @@ const mdb_tgt_regdesc_t mdb_ia32_kregs[] = { { "err", KREG_ERR, MDB_TGT_R_EXPORT | MDB_TGT_R_PRIV }, { NULL, 0, 0 } }; +#endif void mdb_ia32_printregs(const mdb_tgt_gregset_t *gregs) @@ -94,27 +101,27 @@ mdb_ia32_printregs(const mdb_tgt_gregset_t *gregs) const kreg_t *kregs = &gregs->kregs[0]; kreg_t eflags = kregs[KREG_EFLAGS]; - mdb_printf("%%cs = 0x%04x\t\t%%eax = 0x%0?p %A\n", + mdb_printf("%%cs = 0x%04x\t\t%%eax = 0x%08p %A\n", kregs[KREG_CS], kregs[KREG_EAX], kregs[KREG_EAX]); - mdb_printf("%%ds = 0x%04x\t\t%%ebx = 0x%0?p %A\n", + mdb_printf("%%ds = 0x%04x\t\t%%ebx = 0x%08p %A\n", kregs[KREG_DS], kregs[KREG_EBX], kregs[KREG_EBX]); - mdb_printf("%%ss = 0x%04x\t\t%%ecx = 0x%0?p %A\n", + mdb_printf("%%ss = 0x%04x\t\t%%ecx = 0x%08p %A\n", kregs[KREG_SS], kregs[KREG_ECX], kregs[KREG_ECX]); - mdb_printf("%%es = 0x%04x\t\t%%edx = 0x%0?p %A\n", + mdb_printf("%%es = 0x%04x\t\t%%edx = 0x%08p %A\n", kregs[KREG_ES], kregs[KREG_EDX], kregs[KREG_EDX]); - mdb_printf("%%fs = 0x%04x\t\t%%esi = 0x%0?p %A\n", + mdb_printf("%%fs = 0x%04x\t\t%%esi = 0x%08p %A\n", kregs[KREG_FS], kregs[KREG_ESI], kregs[KREG_ESI]); - mdb_printf("%%gs = 0x%04x\t\t%%edi = 0x%0?p %A\n\n", + mdb_printf("%%gs = 0x%04x\t\t%%edi = 0x%08p %A\n\n", kregs[KREG_GS], kregs[KREG_EDI], kregs[KREG_EDI]); - mdb_printf("%%eip = 0x%0?p %A\n", kregs[KREG_EIP], kregs[KREG_EIP]); - mdb_printf("%%ebp = 0x%0?p\n", kregs[KREG_EBP]); - mdb_printf("%%esp = 0x%0?p\n\n", kregs[KREG_ESP]); + mdb_printf("%%eip = 0x%08p %A\n", kregs[KREG_EIP], kregs[KREG_EIP]); + mdb_printf("%%ebp = 0x%08p\n", kregs[KREG_EBP]); + mdb_printf("%%esp = 0x%08p\n\n", kregs[KREG_ESP]); mdb_printf("%%eflags = 0x%08x\n", eflags); mdb_printf(" id=%u vip=%u vif=%u ac=%u vm=%u rf=%u nt=%u iopl=0x%x\n", @@ -138,8 +145,8 @@ mdb_ia32_printregs(const mdb_tgt_gregset_t *gregs) (eflags & KREG_EFLAGS_PF_MASK) ? "PF" : "pf", (eflags & KREG_EFLAGS_CF_MASK) ? "CF" : "cf"); -#ifndef _KMDB - mdb_printf(" %%uesp = 0x%0?x\n", kregs[KREG_UESP]); +#if !defined(__amd64) && !defined(_KMDB) + mdb_printf(" %%uesp = 0x%08x\n", kregs[KREG_UESP]); #endif mdb_printf("%%trapno = 0x%x\n", kregs[KREG_TRAPNO]); mdb_printf(" %%err = 0x%x\n", kregs[KREG_ERR]); @@ -166,7 +173,8 @@ kvm_argcount(mdb_tgt_t *t, uintptr_t eip, ssize_t size) M_ADD_IMM8 = 0x83 /* ADD imm8 to r/m32 */ }; - if (mdb_tgt_vread(t, ins, sizeof (ins), eip) != sizeof (ins)) + if (mdb_tgt_aread(t, MDB_TGT_AS_VIRT_I, ins, sizeof (ins), eip) != + sizeof (ins)) return (0); if (ins[1] != M_MODRM_ESP) @@ -185,7 +193,7 @@ kvm_argcount(mdb_tgt_t *t, uintptr_t eip, ssize_t size) n = 0; } - return (MIN((ssize_t)n, size) / sizeof (long)); + return (MIN((ssize_t)n, size) / sizeof (uint32_t)); } int @@ -198,9 +206,9 @@ mdb_ia32_kvm_stack_iter(mdb_tgt_t *t, const mdb_tgt_gregset_t *gsp, int err; struct fr { - uintptr_t fr_savfp; - uintptr_t fr_savpc; - long fr_argv[32]; + uintptr32_t fr_savfp; + uintptr32_t fr_savpc; + uint32_t fr_argv[32]; } fr; uintptr_t fp = gsp->kregs[KREG_EBP]; @@ -226,9 +234,9 @@ mdb_ia32_kvm_stack_iter(mdb_tgt_t *t, const mdb_tgt_gregset_t *gsp, err = EMDB_STKALIGN; goto badfp; } - if ((size = mdb_tgt_vread(t, &fr, sizeof (fr), fp)) >= - (ssize_t)(2 * sizeof (uintptr_t))) { - size -= (ssize_t)(2 * sizeof (uintptr_t)); + if ((size = mdb_tgt_aread(t, MDB_TGT_AS_VIRT_S, &fr, + sizeof (fr), fp)) >= (ssize_t)(2 * sizeof (uintptr32_t))) { + size -= (ssize_t)(2 * sizeof (uintptr32_t)); argc = kvm_argcount(t, fr.fr_savpc, size); } else { err = EMDB_NOMAP; @@ -245,8 +253,9 @@ mdb_ia32_kvm_stack_iter(mdb_tgt_t *t, const mdb_tgt_gregset_t *gsp, if (advance_tortoise != 0) { struct fr tfr; - if (mdb_tgt_vread(t, &tfr, sizeof (tfr), - tortoise_fp) != sizeof (tfr)) { + if (mdb_tgt_aread(t, MDB_TGT_AS_VIRT_S, &tfr, + sizeof (tfr), tortoise_fp) != + sizeof (tfr)) { err = EMDB_NOMAP; goto badfp; } @@ -262,7 +271,8 @@ mdb_ia32_kvm_stack_iter(mdb_tgt_t *t, const mdb_tgt_gregset_t *gsp, advance_tortoise = !advance_tortoise; - if (got_pc && func(arg, pc, argc, fr.fr_argv, &gregs) != 0) + if (got_pc && + func(arg, pc, argc, (const long *)fr.fr_argv, &gregs) != 0) break; kregs[KREG_ESP] = kregs[KREG_EBP]; @@ -294,6 +304,12 @@ badfp: return (set_errno(err)); } +#ifndef __amd64 +/* + * The functions mdb_ia32_step_out and mdb_ia32_next haven't yet been adapted + * to work when built for an amd64 mdb. They are unused by the amd64-only bhyve + * target, hence the #ifdef. + */ /* * Determine the return address for the current frame. Typically this is the * fr_savpc value from the current frame, but we also perform some special @@ -321,7 +337,8 @@ mdb_ia32_step_out(mdb_tgt_t *t, uintptr_t *p, kreg_t pc, kreg_t fp, kreg_t sp, fp = sp; } - if (mdb_tgt_vread(t, &fr, sizeof (fr), fp) == sizeof (fr)) { + if (mdb_tgt_aread(t, MDB_TGT_AS_VIRT_S, &fr, sizeof (fr), fp) == + sizeof (fr)) { *p = fr.fr_savpc; return (0); } @@ -372,7 +389,8 @@ mdb_ia32_next(mdb_tgt_t *t, uintptr_t *p, kreg_t pc, mdb_instr_t curinstr) * read the subsequent Mod/RM byte to perform additional decoding. */ if (curinstr == M_CALL_REG) { - if (mdb_tgt_vread(t, &m, sizeof (m), pc + 1) != sizeof (m)) + if (mdb_tgt_aread(t, MDB_TGT_AS_VIRT_I, &m, sizeof (m), pc + 1) + != sizeof (m)) return (-1); /* errno is set for us */ /* @@ -404,13 +422,16 @@ mdb_ia32_next(mdb_tgt_t *t, uintptr_t *p, kreg_t pc, mdb_instr_t curinstr) return (set_errno(EAGAIN)); } +#endif /*ARGSUSED*/ int -mdb_ia32_kvm_frame(void *arglim, uintptr_t pc, uint_t argc, const long *argv, +mdb_ia32_kvm_frame(void *arglim, uintptr_t pc, uint_t argc, const long *largv, const mdb_tgt_gregset_t *gregs) { - argc = MIN(argc, (uint_t)arglim); + const uint32_t *argv = (const uint32_t *)largv; + + argc = MIN(argc, (uintptr_t)arglim); mdb_printf("%a(", pc); if (argc != 0) { @@ -424,11 +445,13 @@ mdb_ia32_kvm_frame(void *arglim, uintptr_t pc, uint_t argc, const long *argv, } int -mdb_ia32_kvm_framev(void *arglim, uintptr_t pc, uint_t argc, const long *argv, +mdb_ia32_kvm_framev(void *arglim, uintptr_t pc, uint_t argc, const long *largv, const mdb_tgt_gregset_t *gregs) { - argc = MIN(argc, (uint_t)arglim); - mdb_printf("%0?lr %a(", gregs->kregs[KREG_EBP], pc); + const uint32_t *argv = (const uint32_t *)largv; + + argc = MIN(argc, (uintptr_t)arglim); + mdb_printf("%08lr %a(", gregs->kregs[KREG_EBP], pc); if (argc != 0) { mdb_printf("%lr", *argv++); diff --git a/usr/src/cmd/mdb/intel/mdb/mdb_ia32util.h b/usr/src/cmd/mdb/intel/mdb/mdb_ia32util.h index 597b234b3e..1645b86d8d 100644 --- a/usr/src/cmd/mdb/intel/mdb/mdb_ia32util.h +++ b/usr/src/cmd/mdb/intel/mdb/mdb_ia32util.h @@ -22,12 +22,13 @@ * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ +/* + * Copyright (c) 2018, Joyent, Inc. All rights reserved. + */ #ifndef _MDB_IA32UTIL_H #define _MDB_IA32UTIL_H -#pragma ident "%Z%%M% %I% %E% SMI" - #include <mdb/mdb_kreg.h> #include <mdb/mdb_target_impl.h> @@ -35,8 +36,6 @@ extern "C" { #endif -typedef uchar_t mdb_instr_t; - extern const mdb_tgt_regdesc_t mdb_ia32_kregs[]; extern void mdb_ia32_printregs(const mdb_tgt_gregset_t *); diff --git a/usr/src/cmd/mdb/intel/mdb/mdb_isautil.h b/usr/src/cmd/mdb/intel/mdb/mdb_isautil.h index b6d17e1045..237e6663ae 100644 --- a/usr/src/cmd/mdb/intel/mdb/mdb_isautil.h +++ b/usr/src/cmd/mdb/intel/mdb/mdb_isautil.h @@ -23,16 +23,19 @@ * Copyright 2004 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ +/* + * Copyright (c) 2018, Joyent, Inc. All rights reserved. + */ #ifndef _MDB_ISAUTIL_H #define _MDB_ISAUTIL_H -#pragma ident "%Z%%M% %I% %E% SMI" - #ifdef __cplusplus extern "C" { #endif +typedef uchar_t mdb_instr_t; + #ifdef __amd64 #include <mdb/mdb_amd64util.h> diff --git a/usr/src/cmd/mdb/intel/mdb/mdb_kreg.h b/usr/src/cmd/mdb/intel/mdb/mdb_kreg.h index a3edf864d7..3db7d6a1d6 100644 --- a/usr/src/cmd/mdb/intel/mdb/mdb_kreg.h +++ b/usr/src/cmd/mdb/intel/mdb/mdb_kreg.h @@ -75,6 +75,7 @@ typedef uint32_t kreg_t; #define KREG_ES KDIREG_ES #define KREG_FS KDIREG_FS #define KREG_GS KDIREG_GS +#define KREG_FSBASE KDIREG_FSBASE #define KREG_GSBASE KDIREG_GSBASE #define KREG_KGSBASE KDIREG_KGSBASE #define KREG_TRAPNO KDIREG_TRAPNO @@ -91,6 +92,17 @@ typedef uint32_t kreg_t; #define KREG_SP KREG_RSP #define KREG_FP KREG_RBP +#define KREG_EAX KREG_RAX +#define KREG_EBX KREG_RBX +#define KREG_ECX KREG_RCX +#define KREG_EDX KREG_RDX +#define KREG_ESI KREG_RSI +#define KREG_EDI KREG_RDI +#define KREG_EBP KREG_RBP +#define KREG_ESP KREG_RSP +#define KREG_EFLAGS KREG_RFLAGS +#define KREG_EIP KREG_RIP + #else /* __amd64 */ #define KREG_SAVFP KDIREG_SAVFP diff --git a/usr/src/cmd/mdb/intel/mdb/mdb_x86util.c b/usr/src/cmd/mdb/intel/mdb/mdb_x86util.c new file mode 100644 index 0000000000..a01ee6cffb --- /dev/null +++ b/usr/src/cmd/mdb/intel/mdb/mdb_x86util.c @@ -0,0 +1,215 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright 2019 Joyent, Inc. + */ + +/* + * ISA-independent utility functions for the x86 architecture + */ + +#include <mdb/mdb_modapi.h> +#include <mdb/mdb_x86util.h> + +#include <sys/controlregs.h> +#include <inttypes.h> + +#define MMU_PAGESHIFT 12 +#define MMU_PAGESIZE (1 << MMU_PAGESHIFT) +#define MMU_PAGEOFFSET (MMU_PAGESIZE - 1) +#define MMU_PAGEMASK (~MMU_PAGEOFFSET) + +#ifndef _KMDB +static void +mdb_x86_print_desc(const char *name, const mdb_x86_desc_t *desc, uint_t width) +{ + const char *type; + const mdb_bitmask_t *bits; + + static const mdb_bitmask_t mem_desc_flag_bits[] = { + { "P", 0x80, 0x80 }, + { "16b", 0x6000, 0x0 }, + { "32b", 0x6000, 0x4000 }, + { "64b", 0x6000, 0x2000 }, + { "G", 0x8000, 0x8000 }, + { "A", 0x1, 0x1 }, + { NULL, 0, 0 }, + }; + + static const char *mem_desc_types[] = { + "data, up, read-only", + "data, up, read-write", + "data, down, read-only", + "data, down, read-write", + "code, non-conforming, execute-only", + "code, non-conforming, execute-read", + "code, conforming, execute-only", + "code, conforming, execute-read" + }; + + static const mdb_bitmask_t sys_desc_flag_bits[] = { + { "P", 0x80, 0x80 }, + { "16b", 0x6000, 0x0 }, + { "32b", 0x6000, 0x4000 }, + { "64b", 0x6000, 0x2000 }, + { "G", 0x8000, 0x8000 }, + { NULL, 0, 0 }, + }; + + static const char *sys_desc_types[] = { + "reserved", + "16b TSS, available", + "LDT", + "16b TSS, busy", + "16b call gate", + "task gate", + "16b interrupt gate", + "16b trap gate", + "reserved", + "32b/64b TSS, available", + "reserved", + "32b/64b TSS, busy", + "32b/64b call gate", + "reserved", + "32b/64b interrupt gate" + "32b/64b trap gate", + }; + + if (desc->d_acc & 0x10) { + type = mem_desc_types[(desc->d_acc >> 1) & 7]; + bits = mem_desc_flag_bits; + } else { + type = sys_desc_types[desc->d_acc & 0xf]; + bits = sys_desc_flag_bits; + } + + mdb_printf("%%%s = 0x%0*lx/0x%0*x 0x%05x " + "<%susable, %s, dpl %d, flags: %b>\n", + name, width, desc->d_base, width / 2, desc->d_lim, desc->d_acc, + (desc->d_acc >> 16) & 1 ? "un" : "", type, + (desc->d_acc >> 5) & 3, desc->d_acc, bits); +} +#endif + +void +mdb_x86_print_sysregs(struct sysregs *sregs, boolean_t long_mode) +{ + const uint_t width = + 2 * (long_mode ? sizeof (uint64_t) : sizeof (uint32_t)); + + +#ifndef _KMDB + static const mdb_bitmask_t efer_flag_bits[] = { + { "SCE", AMD_EFER_SCE, AMD_EFER_SCE }, + { "LME", AMD_EFER_LME, AMD_EFER_LME }, + { "LMA", AMD_EFER_LMA, AMD_EFER_LMA }, + { "NXE", AMD_EFER_NXE, AMD_EFER_NXE }, + { "SVME", AMD_EFER_SVME, AMD_EFER_SVME }, + { "LMSLE", AMD_EFER_LMSLE, AMD_EFER_LMSLE }, + { "FFXSR", AMD_EFER_FFXSR, AMD_EFER_FFXSR }, + { "TCE", AMD_EFER_TCE, AMD_EFER_TCE }, + { NULL, 0, 0 } + }; +#endif + + static const mdb_bitmask_t cr0_flag_bits[] = { + { "PE", CR0_PE, CR0_PE }, + { "MP", CR0_MP, CR0_MP }, + { "EM", CR0_EM, CR0_EM }, + { "TS", CR0_TS, CR0_TS }, + { "ET", CR0_ET, CR0_ET }, + { "NE", CR0_NE, CR0_NE }, + { "WP", CR0_WP, CR0_WP }, + { "AM", CR0_AM, CR0_AM }, + { "NW", CR0_NW, CR0_NW }, + { "CD", CR0_CD, CR0_CD }, + { "PG", CR0_PG, CR0_PG }, + { NULL, 0, 0 } + }; + + static const mdb_bitmask_t cr3_flag_bits[] = { + { "PCD", CR3_PCD, CR3_PCD }, + { "PWT", CR3_PWT, CR3_PWT }, + { NULL, 0, 0, } + }; + + static const mdb_bitmask_t cr4_flag_bits[] = { + { "VME", CR4_VME, CR4_VME }, + { "PVI", CR4_PVI, CR4_PVI }, + { "TSD", CR4_TSD, CR4_TSD }, + { "DE", CR4_DE, CR4_DE }, + { "PSE", CR4_PSE, CR4_PSE }, + { "PAE", CR4_PAE, CR4_PAE }, + { "MCE", CR4_MCE, CR4_MCE }, + { "PGE", CR4_PGE, CR4_PGE }, + { "PCE", CR4_PCE, CR4_PCE }, + { "OSFXSR", CR4_OSFXSR, CR4_OSFXSR }, + { "OSXMMEXCPT", CR4_OSXMMEXCPT, CR4_OSXMMEXCPT }, + { "UMIP", CR4_UMIP, CR4_UMIP }, + { "VMXE", CR4_VMXE, CR4_VMXE }, + { "SMXE", CR4_SMXE, CR4_SMXE }, + { "FSGSBASE", CR4_FSGSBASE, CR4_FSGSBASE }, + { "PCIDE", CR4_PCIDE, CR4_PCIDE }, + { "OSXSAVE", CR4_OSXSAVE, CR4_OSXSAVE }, + { "SMEP", CR4_SMEP, CR4_SMEP }, + { "SMAP", CR4_SMAP, CR4_SMAP }, + { "PKE", CR4_PKE, CR4_PKE }, + { NULL, 0, 0 } + }; + +#ifndef _KMDB + mdb_printf("%%efer = 0x%0lx <%b>\n", + sregs->sr_efer, sregs->sr_efer, efer_flag_bits); +#endif + mdb_printf("%%cr0 = 0x%0lx <%b>\n", + sregs->sr_cr0, sregs->sr_cr0, cr0_flag_bits); + mdb_printf("%%cr2 = 0x%0*x <%a>\n", width, + sregs->sr_cr2, sregs->sr_cr2); + mdb_printf("%%cr3 = 0x%0lx <pfn:0x%lx ", + sregs->sr_cr3, sregs->sr_cr3 >> MMU_PAGESHIFT); + if (sregs->sr_cr4 & CR4_PCIDE) + mdb_printf("pcid:%lu>\n", sregs->sr_cr3 & MMU_PAGEOFFSET); + else + mdb_printf("flags:%b>\n", sregs->sr_cr3, cr3_flag_bits); + mdb_printf("%%cr4 = 0x%0lx <%b>\n", + sregs->sr_cr4, sregs->sr_cr4, cr4_flag_bits); + +#ifndef _KMDB + mdb_printf("\n"); + mdb_printf("%%pdpte0 = 0x%0?lx\t%%pdpte2 = 0x%0?lx\n", + sregs->sr_pdpte0, sregs->sr_pdpte2); + mdb_printf("%%pdpte1 = 0x%0?lx\t%%pdpte3 = 0x%0?lx\n", + sregs->sr_pdpte1, sregs->sr_pdpte3); + mdb_printf("\n"); + + mdb_printf("%%gdtr = 0x%0*lx/0x%hx\n", + width, sregs->sr_gdtr.d_base, sregs->sr_gdtr.d_lim); +#else + mdb_printf("%%gdtr.base = 0x%0*lx, %%gdtr.limit = 0x%hx\n", + width, sregs->sr_gdtr.d_base, sregs->sr_gdtr.d_lim); +#endif +#ifndef _KMDB + mdb_printf("%%idtr = 0x%0*lx/0x%hx\n", + width, sregs->sr_idtr.d_base, sregs->sr_idtr.d_lim); + mdb_x86_print_desc("ldtr", &sregs->sr_ldtr, width); + mdb_x86_print_desc("tr ", &sregs->sr_tr, width); + mdb_x86_print_desc("cs ", &sregs->sr_cs, width); + mdb_x86_print_desc("ss ", &sregs->sr_ss, width); + mdb_x86_print_desc("ds ", &sregs->sr_ds, width); + mdb_x86_print_desc("es ", &sregs->sr_es, width); + mdb_x86_print_desc("fs ", &sregs->sr_fs, width); + mdb_x86_print_desc("gs ", &sregs->sr_gs, width); + + mdb_printf("%%intr_shadow = 0x%lx\n", + sregs->sr_intr_shadow); +#endif +} diff --git a/usr/src/cmd/mdb/intel/mdb/mdb_x86util.h b/usr/src/cmd/mdb/intel/mdb/mdb_x86util.h new file mode 100644 index 0000000000..7641595d2a --- /dev/null +++ b/usr/src/cmd/mdb/intel/mdb/mdb_x86util.h @@ -0,0 +1,68 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright 2019 Joyent, Inc. + */ + +#ifndef _MDB_X86UTIL_H +#define _MDB_X86UTIL_H + +#include <sys/types.h> +#include <inttypes.h> + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct mdb_x86_desc { + uint64_t d_base; + uint32_t d_lim; + uint32_t d_acc; +} mdb_x86_desc_t; + +struct sysregs { + uint64_t sr_cr0; + uint64_t sr_cr2; + uint64_t sr_cr3; + uint64_t sr_cr4; + uint64_t sr_dr0; + uint64_t sr_dr1; + uint64_t sr_dr2; + uint64_t sr_dr3; + uint64_t sr_dr6; + uint64_t sr_dr7; + uint64_t sr_efer; + uint64_t sr_pdpte0; + uint64_t sr_pdpte1; + uint64_t sr_pdpte2; + uint64_t sr_pdpte3; + uint64_t sr_intr_shadow; + mdb_x86_desc_t sr_gdtr; + mdb_x86_desc_t sr_idtr; + mdb_x86_desc_t sr_ldtr; + mdb_x86_desc_t sr_tr; + mdb_x86_desc_t sr_cs; + mdb_x86_desc_t sr_ss; + mdb_x86_desc_t sr_ds; + mdb_x86_desc_t sr_es; + mdb_x86_desc_t sr_fs; + mdb_x86_desc_t sr_gs; +}; + +extern void mdb_x86_print_sysregs(struct sysregs *, boolean_t); + + +#ifdef __cplusplus +} +#endif + +#endif /* _MDB_X86UTIL_H */ diff --git a/usr/src/cmd/mdb/intel/mdb/proc_amd64dep.c b/usr/src/cmd/mdb/intel/mdb/proc_amd64dep.c index cb613e2f0c..b19498b96e 100644 --- a/usr/src/cmd/mdb/intel/mdb/proc_amd64dep.c +++ b/usr/src/cmd/mdb/intel/mdb/proc_amd64dep.c @@ -38,6 +38,7 @@ #include <mdb/mdb_proc.h> #include <mdb/mdb_kreg.h> #include <mdb/mdb_err.h> +#include <mdb/mdb_isautil.h> #include <mdb/mdb_amd64util.h> #include <mdb/mdb.h> @@ -144,7 +145,8 @@ pt_read_instr(mdb_tgt_t *t) const lwpstatus_t *psp = &Pstatus(t->t_pshandle)->pr_lwp; uint8_t ret = 0; - (void) mdb_tgt_vread(t, &ret, sizeof (ret), psp->pr_reg[REG_RIP]); + (void) mdb_tgt_aread(t, MDB_TGT_AS_VIRT_I, &ret, sizeof (ret), + psp->pr_reg[REG_RIP]); return (ret); } diff --git a/usr/src/cmd/mdb/intel/mdb/proc_ia32dep.c b/usr/src/cmd/mdb/intel/mdb/proc_ia32dep.c index 7f505b950f..c03a73f31e 100644 --- a/usr/src/cmd/mdb/intel/mdb/proc_ia32dep.c +++ b/usr/src/cmd/mdb/intel/mdb/proc_ia32dep.c @@ -24,8 +24,8 @@ * Use is subject to license terms. */ /* - * Copyright (c) 2018, Joyent, Inc. * Copyright 2019 Doma Gergő Mihály <doma.gergo.mihaly@gmail.com> + * Copyright 2018 Joyent, Inc. */ /* @@ -38,6 +38,7 @@ #include <mdb/mdb_proc.h> #include <mdb/mdb_kreg.h> #include <mdb/mdb_err.h> +#include <mdb/mdb_isautil.h> #include <mdb/mdb_ia32util.h> #include <mdb/mdb.h> @@ -99,7 +100,8 @@ pt_read_instr(mdb_tgt_t *t) const lwpstatus_t *psp = &Pstatus(t->t_pshandle)->pr_lwp; uint8_t ret = 0; - (void) mdb_tgt_vread(t, &ret, sizeof (ret), psp->pr_reg[EIP]); + (void) mdb_tgt_aread(t, MDB_TGT_AS_VIRT_I, &ret, sizeof (ret), + psp->pr_reg[EIP]); return (ret); } |
