diff options
author | neel <neel@FreeBSD.org> | 2014-12-30 08:24:14 +0000 |
---|---|---|
committer | neel <neel@FreeBSD.org> | 2014-12-30 08:24:14 +0000 |
commit | 9a7db864f78c4821164e142b15574dd789e438fc (patch) | |
tree | 5ca9ce0dfb46b18acadddbaeeda0e8409ebb1eac /usr.sbin | |
parent | 6d931c08fa2abce728837379fb2549a6513f49b0 (diff) | |
download | FreeBSD-src-9a7db864f78c4821164e142b15574dd789e438fc.zip FreeBSD-src-9a7db864f78c4821164e142b15574dd789e438fc.tar.gz |
MFC r273375
Add support AMD processors with the SVM/AMD-V hardware extensions.
MFC r273749
Remove bhyve SVM feature printf's now that they are available in the general
CPU feature detection code.
MFC r273766
Add missing 'break' pointed out by Coverity CID 1249760.
MFC r276098
Allow ktr(4) tracing of all guest exceptions via the tunable "hw.vmm.trace_guest_exceptions"
MFC r276392
Inject #UD into the guest when it executes either 'MONITOR' or 'MWAIT' on an
AMD/SVM host.
MFC r276402
Remove "svn:mergeinfo" property that was dragged along when these files were
svn copied in r273375.
Diffstat (limited to 'usr.sbin')
-rw-r--r-- | usr.sbin/bhyve/bhyverun.c | 15 | ||||
-rw-r--r-- | usr.sbin/bhyve/xmsr.c | 104 | ||||
-rw-r--r-- | usr.sbin/bhyvectl/bhyvectl.c | 1854 |
3 files changed, 1257 insertions, 716 deletions
diff --git a/usr.sbin/bhyve/bhyverun.c b/usr.sbin/bhyve/bhyverun.c index b2b36bb..5971993 100644 --- a/usr.sbin/bhyve/bhyverun.c +++ b/usr.sbin/bhyve/bhyverun.c @@ -445,6 +445,20 @@ vmexit_vmx(struct vmctx *ctx, struct vm_exit *vmexit, int *pvcpu) } static int +vmexit_svm(struct vmctx *ctx, struct vm_exit *vmexit, int *pvcpu) +{ + + fprintf(stderr, "vm exit[%d]\n", *pvcpu); + fprintf(stderr, "\treason\t\tSVM\n"); + fprintf(stderr, "\trip\t\t0x%016lx\n", vmexit->rip); + fprintf(stderr, "\tinst_length\t%d\n", vmexit->inst_length); + fprintf(stderr, "\texitcode\t%#lx\n", vmexit->u.svm.exitcode); + fprintf(stderr, "\texitinfo1\t%#lx\n", vmexit->u.svm.exitinfo1); + fprintf(stderr, "\texitinfo2\t%#lx\n", vmexit->u.svm.exitinfo2); + return (VMEXIT_ABORT); +} + +static int vmexit_bogus(struct vmctx *ctx, struct vm_exit *vmexit, int *pvcpu) { @@ -555,6 +569,7 @@ static vmexit_handler_t handler[VM_EXITCODE_MAX] = { [VM_EXITCODE_INOUT] = vmexit_inout, [VM_EXITCODE_INOUT_STR] = vmexit_inout, [VM_EXITCODE_VMX] = vmexit_vmx, + [VM_EXITCODE_SVM] = vmexit_svm, [VM_EXITCODE_BOGUS] = vmexit_bogus, [VM_EXITCODE_RDMSR] = vmexit_rdmsr, [VM_EXITCODE_WRMSR] = vmexit_wrmsr, diff --git a/usr.sbin/bhyve/xmsr.c b/usr.sbin/bhyve/xmsr.c index 1ed1ea1..d50a939 100644 --- a/usr.sbin/bhyve/xmsr.c +++ b/usr.sbin/bhyve/xmsr.c @@ -46,11 +46,11 @@ __FBSDID("$FreeBSD$"); static int cpu_vendor_intel, cpu_vendor_amd; int -emulate_wrmsr(struct vmctx *ctx, int vcpu, uint32_t code, uint64_t val) +emulate_wrmsr(struct vmctx *ctx, int vcpu, uint32_t num, uint64_t val) { if (cpu_vendor_intel) { - switch (code) { + switch (num) { case 0xd04: /* Sandy Bridge uncore PMCs */ case 0xc24: return (0); @@ -61,6 +61,39 @@ emulate_wrmsr(struct vmctx *ctx, int vcpu, uint32_t code, uint64_t val) default: break; } + } else if (cpu_vendor_amd) { + switch (num) { + case MSR_HWCR: + /* + * Ignore writes to hardware configuration MSR. + */ + return (0); + + case MSR_NB_CFG1: + case MSR_IC_CFG: + return (0); /* Ignore writes */ + + case MSR_PERFEVSEL0: + case MSR_PERFEVSEL1: + case MSR_PERFEVSEL2: + case MSR_PERFEVSEL3: + /* Ignore writes to the PerfEvtSel MSRs */ + return (0); + + case MSR_K7_PERFCTR0: + case MSR_K7_PERFCTR1: + case MSR_K7_PERFCTR2: + case MSR_K7_PERFCTR3: + /* Ignore writes to the PerfCtr MSRs */ + return (0); + + case MSR_P_STATE_CONTROL: + /* Ignore write to change the P-state */ + return (0); + + default: + break; + } } return (-1); } @@ -91,6 +124,73 @@ emulate_rdmsr(struct vmctx *ctx, int vcpu, uint32_t num, uint64_t *val) error = -1; break; } + } else if (cpu_vendor_amd) { + switch (num) { + case MSR_BIOS_SIGN: + *val = 0; + break; + case MSR_HWCR: + /* + * Bios and Kernel Developer's Guides for AMD Families + * 12H, 14H, 15H and 16H. + */ + *val = 0x01000010; /* Reset value */ + *val |= 1 << 9; /* MONITOR/MWAIT disable */ + break; + + case MSR_NB_CFG1: + case MSR_IC_CFG: + /* + * The reset value is processor family dependent so + * just return 0. + */ + *val = 0; + break; + + case MSR_PERFEVSEL0: + case MSR_PERFEVSEL1: + case MSR_PERFEVSEL2: + case MSR_PERFEVSEL3: + /* + * PerfEvtSel MSRs are not properly virtualized so just + * return zero. + */ + *val = 0; + break; + + case MSR_K7_PERFCTR0: + case MSR_K7_PERFCTR1: + case MSR_K7_PERFCTR2: + case MSR_K7_PERFCTR3: + /* + * PerfCtr MSRs are not properly virtualized so just + * return zero. + */ + *val = 0; + break; + + case MSR_SMM_ADDR: + case MSR_SMM_MASK: + /* + * Return the reset value defined in the AMD Bios and + * Kernel Developer's Guide. + */ + *val = 0; + break; + + case MSR_P_STATE_LIMIT: + case MSR_P_STATE_CONTROL: + case MSR_P_STATE_STATUS: + case MSR_P_STATE_CONFIG(0): /* P0 configuration */ + *val = 0; + break; + + default: + error = -1; + break; + } + } else { + error = -1; } return (error); } diff --git a/usr.sbin/bhyvectl/bhyvectl.c b/usr.sbin/bhyvectl/bhyvectl.c index f5e50d3..0c4457e 100644 --- a/usr.sbin/bhyvectl/bhyvectl.c +++ b/usr.sbin/bhyvectl/bhyvectl.c @@ -37,6 +37,8 @@ __FBSDID("$FreeBSD$"); #include <stdio.h> #include <stdlib.h> +#include <stdbool.h> +#include <string.h> #include <unistd.h> #include <libgen.h> #include <libutil.h> @@ -45,9 +47,12 @@ __FBSDID("$FreeBSD$"); #include <getopt.h> #include <assert.h> +#include <machine/cpufunc.h> #include <machine/vmm.h> +#include <machine/specialreg.h> #include <vmmapi.h> +#include "amd/vmcb.h" #include "intel/vmcs.h" #define MB (1UL << 20) @@ -60,7 +65,7 @@ __FBSDID("$FreeBSD$"); static const char *progname; static void -usage(void) +usage(bool cpu_intel) { (void)fprintf(stderr, @@ -141,48 +146,6 @@ usage(void) " [--get-ss]\n" " [--get-tr]\n" " [--get-ldtr]\n" - " [--get-vmcs-pinbased-ctls]\n" - " [--get-vmcs-procbased-ctls]\n" - " [--get-vmcs-procbased-ctls2]\n" - " [--get-vmcs-entry-interruption-info]\n" - " [--set-vmcs-entry-interruption-info=<info>]\n" - " [--get-vmcs-eptp]\n" - " [--get-vmcs-guest-physical-address\n" - " [--get-vmcs-guest-linear-address\n" - " [--set-vmcs-exception-bitmap]\n" - " [--get-vmcs-exception-bitmap]\n" - " [--get-vmcs-io-bitmap-address]\n" - " [--get-vmcs-tsc-offset]\n" - " [--get-vmcs-guest-pat]\n" - " [--get-vmcs-host-pat]\n" - " [--get-vmcs-host-cr0]\n" - " [--get-vmcs-host-cr3]\n" - " [--get-vmcs-host-cr4]\n" - " [--get-vmcs-host-rip]\n" - " [--get-vmcs-host-rsp]\n" - " [--get-vmcs-cr0-mask]\n" - " [--get-vmcs-cr0-shadow]\n" - " [--get-vmcs-cr4-mask]\n" - " [--get-vmcs-cr4-shadow]\n" - " [--get-vmcs-cr3-targets]\n" - " [--get-vmcs-apic-access-address]\n" - " [--get-vmcs-virtual-apic-address]\n" - " [--get-vmcs-tpr-threshold]\n" - " [--get-vmcs-msr-bitmap]\n" - " [--get-vmcs-msr-bitmap-address]\n" - " [--get-vmcs-vpid]\n" - " [--get-vmcs-ple-gap]\n" - " [--get-vmcs-ple-window]\n" - " [--get-vmcs-instruction-error]\n" - " [--get-vmcs-exit-ctls]\n" - " [--get-vmcs-entry-ctls]\n" - " [--get-vmcs-guest-sysenter]\n" - " [--get-vmcs-link]\n" - " [--get-vmcs-exit-reason]\n" - " [--get-vmcs-exit-qualification]\n" - " [--get-vmcs-exit-interruption-info]\n" - " [--get-vmcs-exit-interruption-error]\n" - " [--get-vmcs-interruptibility]\n" " [--set-x2apic-state=<state>]\n" " [--get-x2apic-state]\n" " [--unassign-pptdev=<bus/slot/func>]\n" @@ -196,8 +159,64 @@ usage(void) " [--force-poweroff]\n" " [--get-active-cpus]\n" " [--get-suspended-cpus]\n" - " [--get-intinfo]\n", + " [--get-intinfo]\n" + " [--get-eptp]\n" + " [--set-exception-bitmap]\n" + " [--get-exception-bitmap]\n" + " [--get-tsc-offset]\n" + " [--get-guest-pat]\n" + " [--get-io-bitmap-address]\n" + " [--get-msr-bitmap]\n" + " [--get-msr-bitmap-address]\n" + " [--get-guest-sysenter]\n" + " [--get-exit-reason]\n", progname); + + if (cpu_intel) { + (void)fprintf(stderr, + " [--get-vmcs-pinbased-ctls]\n" + " [--get-vmcs-procbased-ctls]\n" + " [--get-vmcs-procbased-ctls2]\n" + " [--get-vmcs-entry-interruption-info]\n" + " [--set-vmcs-entry-interruption-info=<info>]\n" + " [--get-vmcs-guest-physical-address\n" + " [--get-vmcs-guest-linear-address\n" + " [--get-vmcs-host-pat]\n" + " [--get-vmcs-host-cr0]\n" + " [--get-vmcs-host-cr3]\n" + " [--get-vmcs-host-cr4]\n" + " [--get-vmcs-host-rip]\n" + " [--get-vmcs-host-rsp]\n" + " [--get-vmcs-cr0-mask]\n" + " [--get-vmcs-cr0-shadow]\n" + " [--get-vmcs-cr4-mask]\n" + " [--get-vmcs-cr4-shadow]\n" + " [--get-vmcs-cr3-targets]\n" + " [--get-vmcs-apic-access-address]\n" + " [--get-vmcs-virtual-apic-address]\n" + " [--get-vmcs-tpr-threshold]\n" + " [--get-vmcs-vpid]\n" + " [--get-vmcs-instruction-error]\n" + " [--get-vmcs-exit-ctls]\n" + " [--get-vmcs-entry-ctls]\n" + " [--get-vmcs-link]\n" + " [--get-vmcs-exit-qualification]\n" + " [--get-vmcs-exit-interruption-info]\n" + " [--get-vmcs-exit-interruption-error]\n" + " [--get-vmcs-interruptibility]\n" + ); + } else { + (void)fprintf(stderr, + " [--get-vmcb-intercepts]\n" + " [--get-vmcb-asid]\n" + " [--get-vmcb-exit-details]\n" + " [--get-vmcb-tlb-ctrl]\n" + " [--get-vmcb-virq]\n" + " [--get-avic-apic-bar]\n" + " [--get-avic-backing-page]\n" + " [--get-avic-table]\n" + ); + } exit(1); } @@ -234,6 +253,12 @@ static int unassign_pptdev, bus, slot, func; static int run; /* + * VMCB specific. + */ +static int get_vmcb_intercept, get_vmcb_exit_details, get_vmcb_tlb_ctrl; +static int get_vmcb_virq, get_avic_table; + +/* * VMCS-specific fields */ static int get_pinbased_ctls, get_procbased_ctls, get_procbased_ctls2; @@ -248,13 +273,13 @@ static int get_cr4_mask, get_cr4_shadow; static int get_cr3_targets; static int get_apic_access_addr, get_virtual_apic_addr, get_tpr_threshold; static int get_msr_bitmap, get_msr_bitmap_address; -static int get_vpid, get_ple_gap, get_ple_window; +static int get_vpid_asid; static int get_inst_err, get_exit_ctls, get_entry_ctls; static int get_host_cr0, get_host_cr3, get_host_cr4; static int get_host_rip, get_host_rsp; static int get_guest_pat, get_host_pat; static int get_guest_sysenter, get_vmcs_link; -static int get_vmcs_exit_reason, get_vmcs_exit_qualification; +static int get_exit_reason, get_vmcs_exit_qualification; static int get_vmcs_exit_interruption_info, get_vmcs_exit_interruption_error; static uint64_t desc_base; @@ -289,29 +314,115 @@ dump_vm_run_exitcode(struct vm_exit *vmexit, int vcpu) printf("\tinst_type\t\t%d\n", vmexit->u.vmx.inst_type); printf("\tinst_error\t\t%d\n", vmexit->u.vmx.inst_error); break; + case VM_EXITCODE_SVM: + printf("\treason\t\tSVM\n"); + printf("\texit_reason\t\t%#lx\n", vmexit->u.svm.exitcode); + printf("\texitinfo1\t\t%#lx\n", vmexit->u.svm.exitinfo1); + printf("\texitinfo2\t\t%#lx\n", vmexit->u.svm.exitinfo2); + break; default: printf("*** unknown vm run exitcode %d\n", vmexit->exitcode); break; } } -static int -dump_vmcs_msr_bitmap(int vcpu, u_long addr) +/* AMD 6th generation and Intel compatible MSRs */ +#define MSR_AMD6TH_START 0xC0000000 +#define MSR_AMD6TH_END 0xC0001FFF +/* AMD 7th and 8th generation compatible MSRs */ +#define MSR_AMD7TH_START 0xC0010000 +#define MSR_AMD7TH_END 0xC0011FFF + +static const char * +msr_name(uint32_t msr) { - int error, fd, byte, bit, readable, writeable; - u_int msr; - const char *bitmap; + static char buf[32]; + + switch(msr) { + case MSR_TSC: + return ("MSR_TSC"); + case MSR_EFER: + return ("MSR_EFER"); + case MSR_STAR: + return ("MSR_STAR"); + case MSR_LSTAR: + return ("MSR_LSTAR"); + case MSR_CSTAR: + return ("MSR_CSTAR"); + case MSR_SF_MASK: + return ("MSR_SF_MASK"); + case MSR_FSBASE: + return ("MSR_FSBASE"); + case MSR_GSBASE: + return ("MSR_GSBASE"); + case MSR_KGSBASE: + return ("MSR_KGSBASE"); + case MSR_SYSENTER_CS_MSR: + return ("MSR_SYSENTER_CS_MSR"); + case MSR_SYSENTER_ESP_MSR: + return ("MSR_SYSENTER_ESP_MSR"); + case MSR_SYSENTER_EIP_MSR: + return ("MSR_SYSENTER_EIP_MSR"); + case MSR_PAT: + return ("MSR_PAT"); + } + snprintf(buf, sizeof(buf), "MSR %#08x", msr); + + return (buf); +} - error = -1; - bitmap = MAP_FAILED; +static inline void +print_msr_pm(uint64_t msr, int vcpu, int readable, int writeable) +{ - fd = open("/dev/mem", O_RDONLY, 0); - if (fd < 0) - goto done; + if (readable || writeable) { + printf("%-20s[%d]\t\t%c%c\n", msr_name(msr), vcpu, + readable ? 'R' : '-', writeable ? 'W' : '-'); + } +} - bitmap = mmap(NULL, PAGE_SIZE, PROT_READ, MAP_SHARED, fd, addr); - if (bitmap == MAP_FAILED) - goto done; +/* + * Reference APM vol2, section 15.11 MSR Intercepts. + */ +static void +dump_amd_msr_pm(const char *bitmap, int vcpu) +{ + int byte, bit, readable, writeable; + uint32_t msr; + + for (msr = 0; msr < 0x2000; msr++) { + byte = msr / 4; + bit = (msr % 4) * 2; + + /* Look at MSRs in the range 0x00000000 to 0x00001FFF */ + readable = (bitmap[byte] & (1 << bit)) ? 0 : 1; + writeable = (bitmap[byte] & (2 << bit)) ? 0 : 1; + print_msr_pm(msr, vcpu, readable, writeable); + + /* Look at MSRs in the range 0xC0000000 to 0xC0001FFF */ + byte += 2048; + readable = (bitmap[byte] & (1 << bit)) ? 0 : 1; + writeable = (bitmap[byte] & (2 << bit)) ? 0 : 1; + print_msr_pm(msr + MSR_AMD6TH_START, vcpu, readable, + writeable); + + /* MSR 0xC0010000 to 0xC0011FF is only for AMD */ + byte += 4096; + readable = (bitmap[byte] & (1 << bit)) ? 0 : 1; + writeable = (bitmap[byte] & (2 << bit)) ? 0 : 1; + print_msr_pm(msr + MSR_AMD7TH_START, vcpu, readable, + writeable); + } +} + +/* + * Reference Intel SDM Vol3 Section 24.6.9 MSR-Bitmap Address + */ +static void +dump_intel_msr_pm(const char *bitmap, int vcpu) +{ + int byte, bit, readable, writeable; + uint32_t msr; for (msr = 0; msr < 0x2000; msr++) { byte = msr / 8; @@ -319,31 +430,56 @@ dump_vmcs_msr_bitmap(int vcpu, u_long addr) /* Look at MSRs in the range 0x00000000 to 0x00001FFF */ readable = (bitmap[byte] & (1 << bit)) ? 0 : 1; - writeable = (bitmap[2048 + byte] & (1 << bit)) ? 0 : 1; - if (readable || writeable) { - printf("msr 0x%08x[%d]\t\t%c%c\n", msr, vcpu, - readable ? 'R' : '-', - writeable ? 'W' : '-'); - } + writeable = (bitmap[2048 + byte] & (1 << bit)) ? 0 : 1; + print_msr_pm(msr, vcpu, readable, writeable); /* Look at MSRs in the range 0xC0000000 to 0xC0001FFF */ byte += 1024; readable = (bitmap[byte] & (1 << bit)) ? 0 : 1; - writeable = (bitmap[2048 + byte] & (1 << bit)) ? 0 : 1; - if (readable || writeable) { - printf("msr 0x%08x[%d]\t\t%c%c\n", - 0xc0000000 + msr, vcpu, - readable ? 'R' : '-', - writeable ? 'W' : '-'); - } + writeable = (bitmap[2048 + byte] & (1 << bit)) ? 0 : 1; + print_msr_pm(msr + MSR_AMD6TH_START, vcpu, readable, + writeable); } +} + +static int +dump_msr_bitmap(int vcpu, uint64_t addr, bool cpu_intel) +{ + int error, fd, map_size; + const char *bitmap; + + error = -1; + bitmap = MAP_FAILED; + + fd = open("/dev/mem", O_RDONLY, 0); + if (fd < 0) { + perror("Couldn't open /dev/mem"); + goto done; + } + + if (cpu_intel) + map_size = PAGE_SIZE; + else + map_size = 2 * PAGE_SIZE; + + bitmap = mmap(NULL, map_size, PROT_READ, MAP_SHARED, fd, addr); + if (bitmap == MAP_FAILED) { + perror("mmap failed"); + goto done; + } + + if (cpu_intel) + dump_intel_msr_pm(bitmap, vcpu); + else + dump_amd_msr_pm(bitmap, vcpu); error = 0; done: if (bitmap != MAP_FAILED) - munmap((void *)bitmap, PAGE_SIZE); + munmap((void *)bitmap, map_size); if (fd >= 0) close(fd); + return (error); } @@ -361,6 +497,22 @@ vm_set_vmcs_field(struct vmctx *ctx, int vcpu, int field, uint64_t val) return (vm_set_register(ctx, vcpu, VMCS_IDENT(field), val)); } +static int +vm_get_vmcb_field(struct vmctx *ctx, int vcpu, int off, int bytes, + uint64_t *ret_val) +{ + + return (vm_get_register(ctx, vcpu, VMCB_ACCESS(off, bytes), ret_val)); +} + +static int +vm_set_vmcb_field(struct vmctx *ctx, int vcpu, int off, int bytes, + uint64_t val) +{ + + return (vm_set_register(ctx, vcpu, VMCB_ACCESS(off, bytes), val)); +} + enum { VMNAME = 1000, /* avoid collision with return values from getopt */ VCPU, @@ -386,7 +538,7 @@ enum { SET_TR, SET_LDTR, SET_X2APIC_STATE, - SET_VMCS_EXCEPTION_BITMAP, + SET_EXCEPTION_BITMAP, SET_VMCS_ENTRY_INTERRUPTION_INFO, SET_CAP, CAPNAME, @@ -445,25 +597,647 @@ print_intinfo(const char *banner, uint64_t info) printf("\n"); } -int -main(int argc, char *argv[]) +static bool +cpu_vendor_intel(void) { - char *vmname; - int error, ch, vcpu, ptenum; - vm_paddr_t gpa, gpa_pmap; - size_t len; - struct vm_exit vmexit; - uint64_t ctl, eptp, bm, addr, u64, pteval[4], *pte, info[2]; - struct vmctx *ctx; - int wired; - cpuset_t cpus; + u_int regs[4]; + char cpu_vendor[13]; + + do_cpuid(0, regs); + ((u_int *)&cpu_vendor)[0] = regs[1]; + ((u_int *)&cpu_vendor)[1] = regs[3]; + ((u_int *)&cpu_vendor)[2] = regs[2]; + cpu_vendor[12] = '\0'; + + if (strcmp(cpu_vendor, "AuthenticAMD") == 0) { + return (false); + } else if (strcmp(cpu_vendor, "GenuineIntel") == 0) { + return (true); + } else { + fprintf(stderr, "Unknown cpu vendor \"%s\"\n", cpu_vendor); + exit(1); + } +} - uint64_t cr0, cr3, cr4, dr7, rsp, rip, rflags, efer, pat; +static int +get_all_registers(struct vmctx *ctx, int vcpu) +{ + uint64_t cr0, cr3, cr4, dr7, rsp, rip, rflags, efer; uint64_t rax, rbx, rcx, rdx, rsi, rdi, rbp; uint64_t r8, r9, r10, r11, r12, r13, r14, r15; + int error; + + if (get_efer || get_all) { + error = vm_get_register(ctx, vcpu, VM_REG_GUEST_EFER, &efer); + if (error == 0) + printf("efer[%d]\t\t0x%016lx\n", vcpu, efer); + } + + if (!error && (get_cr0 || get_all)) { + error = vm_get_register(ctx, vcpu, VM_REG_GUEST_CR0, &cr0); + if (error == 0) + printf("cr0[%d]\t\t0x%016lx\n", vcpu, cr0); + } + + if (!error && (get_cr3 || get_all)) { + error = vm_get_register(ctx, vcpu, VM_REG_GUEST_CR3, &cr3); + if (error == 0) + printf("cr3[%d]\t\t0x%016lx\n", vcpu, cr3); + } + + if (!error && (get_cr4 || get_all)) { + error = vm_get_register(ctx, vcpu, VM_REG_GUEST_CR4, &cr4); + if (error == 0) + printf("cr4[%d]\t\t0x%016lx\n", vcpu, cr4); + } + + if (!error && (get_dr7 || get_all)) { + error = vm_get_register(ctx, vcpu, VM_REG_GUEST_DR7, &dr7); + if (error == 0) + printf("dr7[%d]\t\t0x%016lx\n", vcpu, dr7); + } + + if (!error && (get_rsp || get_all)) { + error = vm_get_register(ctx, vcpu, VM_REG_GUEST_RSP, &rsp); + if (error == 0) + printf("rsp[%d]\t\t0x%016lx\n", vcpu, rsp); + } + + if (!error && (get_rip || get_all)) { + error = vm_get_register(ctx, vcpu, VM_REG_GUEST_RIP, &rip); + if (error == 0) + printf("rip[%d]\t\t0x%016lx\n", vcpu, rip); + } + + if (!error && (get_rax || get_all)) { + error = vm_get_register(ctx, vcpu, VM_REG_GUEST_RAX, &rax); + if (error == 0) + printf("rax[%d]\t\t0x%016lx\n", vcpu, rax); + } + + if (!error && (get_rbx || get_all)) { + error = vm_get_register(ctx, vcpu, VM_REG_GUEST_RBX, &rbx); + if (error == 0) + printf("rbx[%d]\t\t0x%016lx\n", vcpu, rbx); + } + + if (!error && (get_rcx || get_all)) { + error = vm_get_register(ctx, vcpu, VM_REG_GUEST_RCX, &rcx); + if (error == 0) + printf("rcx[%d]\t\t0x%016lx\n", vcpu, rcx); + } + + if (!error && (get_rdx || get_all)) { + error = vm_get_register(ctx, vcpu, VM_REG_GUEST_RDX, &rdx); + if (error == 0) + printf("rdx[%d]\t\t0x%016lx\n", vcpu, rdx); + } + + if (!error && (get_rsi || get_all)) { + error = vm_get_register(ctx, vcpu, VM_REG_GUEST_RSI, &rsi); + if (error == 0) + printf("rsi[%d]\t\t0x%016lx\n", vcpu, rsi); + } + + if (!error && (get_rdi || get_all)) { + error = vm_get_register(ctx, vcpu, VM_REG_GUEST_RDI, &rdi); + if (error == 0) + printf("rdi[%d]\t\t0x%016lx\n", vcpu, rdi); + } + + if (!error && (get_rbp || get_all)) { + error = vm_get_register(ctx, vcpu, VM_REG_GUEST_RBP, &rbp); + if (error == 0) + printf("rbp[%d]\t\t0x%016lx\n", vcpu, rbp); + } + + if (!error && (get_r8 || get_all)) { + error = vm_get_register(ctx, vcpu, VM_REG_GUEST_R8, &r8); + if (error == 0) + printf("r8[%d]\t\t0x%016lx\n", vcpu, r8); + } + + if (!error && (get_r9 || get_all)) { + error = vm_get_register(ctx, vcpu, VM_REG_GUEST_R9, &r9); + if (error == 0) + printf("r9[%d]\t\t0x%016lx\n", vcpu, r9); + } + + if (!error && (get_r10 || get_all)) { + error = vm_get_register(ctx, vcpu, VM_REG_GUEST_R10, &r10); + if (error == 0) + printf("r10[%d]\t\t0x%016lx\n", vcpu, r10); + } + + if (!error && (get_r11 || get_all)) { + error = vm_get_register(ctx, vcpu, VM_REG_GUEST_R11, &r11); + if (error == 0) + printf("r11[%d]\t\t0x%016lx\n", vcpu, r11); + } + + if (!error && (get_r12 || get_all)) { + error = vm_get_register(ctx, vcpu, VM_REG_GUEST_R12, &r12); + if (error == 0) + printf("r12[%d]\t\t0x%016lx\n", vcpu, r12); + } + + if (!error && (get_r13 || get_all)) { + error = vm_get_register(ctx, vcpu, VM_REG_GUEST_R13, &r13); + if (error == 0) + printf("r13[%d]\t\t0x%016lx\n", vcpu, r13); + } + + if (!error && (get_r14 || get_all)) { + error = vm_get_register(ctx, vcpu, VM_REG_GUEST_R14, &r14); + if (error == 0) + printf("r14[%d]\t\t0x%016lx\n", vcpu, r14); + } + + if (!error && (get_r15 || get_all)) { + error = vm_get_register(ctx, vcpu, VM_REG_GUEST_R15, &r15); + if (error == 0) + printf("r15[%d]\t\t0x%016lx\n", vcpu, r15); + } + + if (!error && (get_rflags || get_all)) { + error = vm_get_register(ctx, vcpu, VM_REG_GUEST_RFLAGS, + &rflags); + if (error == 0) + printf("rflags[%d]\t0x%016lx\n", vcpu, rflags); + } + + return (error); +} + +static int +get_all_segments(struct vmctx *ctx, int vcpu) +{ + int error; uint64_t cs, ds, es, fs, gs, ss, tr, ldtr; - struct option opts[] = { + if (get_desc_ds || get_all) { + error = vm_get_desc(ctx, vcpu, VM_REG_GUEST_DS, + &desc_base, &desc_limit, &desc_access); + if (error == 0) { + printf("ds desc[%d]\t0x%016lx/0x%08x/0x%08x\n", + vcpu, desc_base, desc_limit, desc_access); + } + } + + if (!error && (get_desc_es || get_all)) { + error = vm_get_desc(ctx, vcpu, VM_REG_GUEST_ES, + &desc_base, &desc_limit, &desc_access); + if (error == 0) { + printf("es desc[%d]\t0x%016lx/0x%08x/0x%08x\n", + vcpu, desc_base, desc_limit, desc_access); + } + } + + if (!error && (get_desc_fs || get_all)) { + error = vm_get_desc(ctx, vcpu, VM_REG_GUEST_FS, + &desc_base, &desc_limit, &desc_access); + if (error == 0) { + printf("fs desc[%d]\t0x%016lx/0x%08x/0x%08x\n", + vcpu, desc_base, desc_limit, desc_access); + } + } + + if (!error && (get_desc_gs || get_all)) { + error = vm_get_desc(ctx, vcpu, VM_REG_GUEST_GS, + &desc_base, &desc_limit, &desc_access); + if (error == 0) { + printf("gs desc[%d]\t0x%016lx/0x%08x/0x%08x\n", + vcpu, desc_base, desc_limit, desc_access); + } + } + + if (!error && (get_desc_ss || get_all)) { + error = vm_get_desc(ctx, vcpu, VM_REG_GUEST_SS, + &desc_base, &desc_limit, &desc_access); + if (error == 0) { + printf("ss desc[%d]\t0x%016lx/0x%08x/0x%08x\n", + vcpu, desc_base, desc_limit, desc_access); + } + } + + if (!error && (get_desc_cs || get_all)) { + error = vm_get_desc(ctx, vcpu, VM_REG_GUEST_CS, + &desc_base, &desc_limit, &desc_access); + if (error == 0) { + printf("cs desc[%d]\t0x%016lx/0x%08x/0x%08x\n", + vcpu, desc_base, desc_limit, desc_access); + } + } + + if (!error && (get_desc_tr || get_all)) { + error = vm_get_desc(ctx, vcpu, VM_REG_GUEST_TR, + &desc_base, &desc_limit, &desc_access); + if (error == 0) { + printf("tr desc[%d]\t0x%016lx/0x%08x/0x%08x\n", + vcpu, desc_base, desc_limit, desc_access); + } + } + + if (!error && (get_desc_ldtr || get_all)) { + error = vm_get_desc(ctx, vcpu, VM_REG_GUEST_LDTR, + &desc_base, &desc_limit, &desc_access); + if (error == 0) { + printf("ldtr desc[%d]\t0x%016lx/0x%08x/0x%08x\n", + vcpu, desc_base, desc_limit, desc_access); + } + } + + if (!error && (get_desc_gdtr || get_all)) { + error = vm_get_desc(ctx, vcpu, VM_REG_GUEST_GDTR, + &desc_base, &desc_limit, &desc_access); + if (error == 0) { + printf("gdtr[%d]\t\t0x%016lx/0x%08x\n", + vcpu, desc_base, desc_limit); + } + } + + if (!error && (get_desc_idtr || get_all)) { + error = vm_get_desc(ctx, vcpu, VM_REG_GUEST_IDTR, + &desc_base, &desc_limit, &desc_access); + if (error == 0) { + printf("idtr[%d]\t\t0x%016lx/0x%08x\n", + vcpu, desc_base, desc_limit); + } + } + + if (!error && (get_cs || get_all)) { + error = vm_get_register(ctx, vcpu, VM_REG_GUEST_CS, &cs); + if (error == 0) + printf("cs[%d]\t\t0x%04lx\n", vcpu, cs); + } + + if (!error && (get_ds || get_all)) { + error = vm_get_register(ctx, vcpu, VM_REG_GUEST_DS, &ds); + if (error == 0) + printf("ds[%d]\t\t0x%04lx\n", vcpu, ds); + } + + if (!error && (get_es || get_all)) { + error = vm_get_register(ctx, vcpu, VM_REG_GUEST_ES, &es); + if (error == 0) + printf("es[%d]\t\t0x%04lx\n", vcpu, es); + } + + if (!error && (get_fs || get_all)) { + error = vm_get_register(ctx, vcpu, VM_REG_GUEST_FS, &fs); + if (error == 0) + printf("fs[%d]\t\t0x%04lx\n", vcpu, fs); + } + + if (!error && (get_gs || get_all)) { + error = vm_get_register(ctx, vcpu, VM_REG_GUEST_GS, &gs); + if (error == 0) + printf("gs[%d]\t\t0x%04lx\n", vcpu, gs); + } + + if (!error && (get_ss || get_all)) { + error = vm_get_register(ctx, vcpu, VM_REG_GUEST_SS, &ss); + if (error == 0) + printf("ss[%d]\t\t0x%04lx\n", vcpu, ss); + } + + if (!error && (get_tr || get_all)) { + error = vm_get_register(ctx, vcpu, VM_REG_GUEST_TR, &tr); + if (error == 0) + printf("tr[%d]\t\t0x%04lx\n", vcpu, tr); + } + + if (!error && (get_ldtr || get_all)) { + error = vm_get_register(ctx, vcpu, VM_REG_GUEST_LDTR, &ldtr); + if (error == 0) + printf("ldtr[%d]\t\t0x%04lx\n", vcpu, ldtr); + } + + return (error); +} + +static int +get_misc_vmcs(struct vmctx *ctx, int vcpu) +{ + uint64_t ctl, cr0, cr3, cr4, rsp, rip, pat, addr, u64; + int error; + + if (get_cr0_mask || get_all) { + uint64_t cr0mask; + error = vm_get_vmcs_field(ctx, vcpu, VMCS_CR0_MASK, &cr0mask); + if (error == 0) + printf("cr0_mask[%d]\t\t0x%016lx\n", vcpu, cr0mask); + } + + if (!error && (get_cr0_shadow || get_all)) { + uint64_t cr0shadow; + error = vm_get_vmcs_field(ctx, vcpu, VMCS_CR0_SHADOW, + &cr0shadow); + if (error == 0) + printf("cr0_shadow[%d]\t\t0x%016lx\n", vcpu, cr0shadow); + } + + if (!error && (get_cr4_mask || get_all)) { + uint64_t cr4mask; + error = vm_get_vmcs_field(ctx, vcpu, VMCS_CR4_MASK, &cr4mask); + if (error == 0) + printf("cr4_mask[%d]\t\t0x%016lx\n", vcpu, cr4mask); + } + + if (!error && (get_cr4_shadow || get_all)) { + uint64_t cr4shadow; + error = vm_get_vmcs_field(ctx, vcpu, VMCS_CR4_SHADOW, + &cr4shadow); + if (error == 0) + printf("cr4_shadow[%d]\t\t0x%016lx\n", vcpu, cr4shadow); + } + + if (!error && (get_cr3_targets || get_all)) { + uint64_t target_count, target_addr; + error = vm_get_vmcs_field(ctx, vcpu, VMCS_CR3_TARGET_COUNT, + &target_count); + if (error == 0) { + printf("cr3_target_count[%d]\t0x%016lx\n", + vcpu, target_count); + } + + error = vm_get_vmcs_field(ctx, vcpu, VMCS_CR3_TARGET0, + &target_addr); + if (error == 0) { + printf("cr3_target0[%d]\t\t0x%016lx\n", + vcpu, target_addr); + } + + error = vm_get_vmcs_field(ctx, vcpu, VMCS_CR3_TARGET1, + &target_addr); + if (error == 0) { + printf("cr3_target1[%d]\t\t0x%016lx\n", + vcpu, target_addr); + } + + error = vm_get_vmcs_field(ctx, vcpu, VMCS_CR3_TARGET2, + &target_addr); + if (error == 0) { + printf("cr3_target2[%d]\t\t0x%016lx\n", + vcpu, target_addr); + } + + error = vm_get_vmcs_field(ctx, vcpu, VMCS_CR3_TARGET3, + &target_addr); + if (error == 0) { + printf("cr3_target3[%d]\t\t0x%016lx\n", + vcpu, target_addr); + } + } + + if (!error && (get_pinbased_ctls || get_all)) { + error = vm_get_vmcs_field(ctx, vcpu, VMCS_PIN_BASED_CTLS, &ctl); + if (error == 0) + printf("pinbased_ctls[%d]\t0x%016lx\n", vcpu, ctl); + } + + if (!error && (get_procbased_ctls || get_all)) { + error = vm_get_vmcs_field(ctx, vcpu, + VMCS_PRI_PROC_BASED_CTLS, &ctl); + if (error == 0) + printf("procbased_ctls[%d]\t0x%016lx\n", vcpu, ctl); + } + + if (!error && (get_procbased_ctls2 || get_all)) { + error = vm_get_vmcs_field(ctx, vcpu, + VMCS_SEC_PROC_BASED_CTLS, &ctl); + if (error == 0) + printf("procbased_ctls2[%d]\t0x%016lx\n", vcpu, ctl); + } + + if (!error && (get_vmcs_gla || get_all)) { + error = vm_get_vmcs_field(ctx, vcpu, + VMCS_GUEST_LINEAR_ADDRESS, &u64); + if (error == 0) + printf("gla[%d]\t\t0x%016lx\n", vcpu, u64); + } + + if (!error && (get_vmcs_gpa || get_all)) { + error = vm_get_vmcs_field(ctx, vcpu, + VMCS_GUEST_PHYSICAL_ADDRESS, &u64); + if (error == 0) + printf("gpa[%d]\t\t0x%016lx\n", vcpu, u64); + } + + if (!error && (get_vmcs_entry_interruption_info || + get_all)) { + error = vm_get_vmcs_field(ctx, vcpu, VMCS_ENTRY_INTR_INFO,&u64); + if (error == 0) { + printf("entry_interruption_info[%d]\t0x%016lx\n", + vcpu, u64); + } + } + + if (!error && (get_tpr_threshold || get_all)) { + uint64_t threshold; + error = vm_get_vmcs_field(ctx, vcpu, VMCS_TPR_THRESHOLD, + &threshold); + if (error == 0) + printf("tpr_threshold[%d]\t0x%016lx\n", vcpu, threshold); + } + + if (!error && (get_inst_err || get_all)) { + uint64_t insterr; + error = vm_get_vmcs_field(ctx, vcpu, VMCS_INSTRUCTION_ERROR, + &insterr); + if (error == 0) { + printf("instruction_error[%d]\t0x%016lx\n", + vcpu, insterr); + } + } + + if (!error && (get_exit_ctls || get_all)) { + error = vm_get_vmcs_field(ctx, vcpu, VMCS_EXIT_CTLS, &ctl); + if (error == 0) + printf("exit_ctls[%d]\t\t0x%016lx\n", vcpu, ctl); + } + + if (!error && (get_entry_ctls || get_all)) { + error = vm_get_vmcs_field(ctx, vcpu, VMCS_ENTRY_CTLS, &ctl); + if (error == 0) + printf("entry_ctls[%d]\t\t0x%016lx\n", vcpu, ctl); + } + + if (!error && (get_host_pat || get_all)) { + error = vm_get_vmcs_field(ctx, vcpu, VMCS_HOST_IA32_PAT, &pat); + if (error == 0) + printf("host_pat[%d]\t\t0x%016lx\n", vcpu, pat); + } + + if (!error && (get_host_cr0 || get_all)) { + error = vm_get_vmcs_field(ctx, vcpu, VMCS_HOST_CR0, &cr0); + if (error == 0) + printf("host_cr0[%d]\t\t0x%016lx\n", vcpu, cr0); + } + + if (!error && (get_host_cr3 || get_all)) { + error = vm_get_vmcs_field(ctx, vcpu, VMCS_HOST_CR3, &cr3); + if (error == 0) + printf("host_cr3[%d]\t\t0x%016lx\n", vcpu, cr3); + } + + if (!error && (get_host_cr4 || get_all)) { + error = vm_get_vmcs_field(ctx, vcpu, VMCS_HOST_CR4, &cr4); + if (error == 0) + printf("host_cr4[%d]\t\t0x%016lx\n", vcpu, cr4); + } + + if (!error && (get_host_rip || get_all)) { + error = vm_get_vmcs_field(ctx, vcpu, VMCS_HOST_RIP, &rip); + if (error == 0) + printf("host_rip[%d]\t\t0x%016lx\n", vcpu, rip); + } + + if (!error && (get_host_rsp || get_all)) { + error = vm_get_vmcs_field(ctx, vcpu, VMCS_HOST_RSP, &rsp); + if (error == 0) + printf("host_rsp[%d]\t\t0x%016lx\n", vcpu, rsp); + } + + if (!error && (get_vmcs_link || get_all)) { + error = vm_get_vmcs_field(ctx, vcpu, VMCS_LINK_POINTER, &addr); + if (error == 0) + printf("vmcs_pointer[%d]\t0x%016lx\n", vcpu, addr); + } + + if (!error && (get_vmcs_exit_interruption_info || get_all)) { + error = vm_get_vmcs_field(ctx, vcpu, VMCS_EXIT_INTR_INFO, &u64); + if (error == 0) { + printf("vmcs_exit_interruption_info[%d]\t0x%016lx\n", + vcpu, u64); + } + } + + if (!error && (get_vmcs_exit_interruption_error || get_all)) { + error = vm_get_vmcs_field(ctx, vcpu, VMCS_EXIT_INTR_ERRCODE, + &u64); + if (error == 0) { + printf("vmcs_exit_interruption_error[%d]\t0x%016lx\n", + vcpu, u64); + } + } + + if (!error && (get_vmcs_interruptibility || get_all)) { + error = vm_get_vmcs_field(ctx, vcpu, + VMCS_GUEST_INTERRUPTIBILITY, &u64); + if (error == 0) { + printf("vmcs_guest_interruptibility[%d]\t0x%016lx\n", + vcpu, u64); + } + } + + if (!error && (get_vmcs_exit_qualification || get_all)) { + error = vm_get_vmcs_field(ctx, vcpu, VMCS_EXIT_QUALIFICATION, + &u64); + if (error == 0) + printf("vmcs_exit_qualification[%d]\t0x%016lx\n", + vcpu, u64); + } + + return (error); +} + +static int +get_misc_vmcb(struct vmctx *ctx, int vcpu) +{ + uint64_t ctl, addr; + int error; + + if (get_vmcb_intercept || get_all) { + error = vm_get_vmcb_field(ctx, vcpu, VMCB_OFF_CR_INTERCEPT, 4, + &ctl); + if (error == 0) + printf("cr_intercept[%d]\t0x%08x\n", vcpu, (int)ctl); + + error = vm_get_vmcb_field(ctx, vcpu, VMCB_OFF_DR_INTERCEPT, 4, + &ctl); + if (error == 0) + printf("dr_intercept[%d]\t0x%08x\n", vcpu, (int)ctl); + + error = vm_get_vmcb_field(ctx, vcpu, VMCB_OFF_EXC_INTERCEPT, 4, + &ctl); + if (error == 0) + printf("exc_intercept[%d]\t0x%08x\n", vcpu, (int)ctl); + + error = vm_get_vmcb_field(ctx, vcpu, VMCB_OFF_INST1_INTERCEPT, + 4, &ctl); + if (error == 0) + printf("inst1_intercept[%d]\t0x%08x\n", vcpu, (int)ctl); + + error = vm_get_vmcb_field(ctx, vcpu, VMCB_OFF_INST2_INTERCEPT, + 4, &ctl); + if (error == 0) + printf("inst2_intercept[%d]\t0x%08x\n", vcpu, (int)ctl); + } + + if (!error && (get_vmcb_tlb_ctrl || get_all)) { + error = vm_get_vmcb_field(ctx, vcpu, VMCB_OFF_TLB_CTRL, + 4, &ctl); + if (error == 0) + printf("TLB ctrl[%d]\t0x%016lx\n", vcpu, ctl); + } + + if (!error && (get_vmcb_exit_details || get_all)) { + error = vm_get_vmcb_field(ctx, vcpu, VMCB_OFF_EXITINFO1, + 8, &ctl); + if (error == 0) + printf("exitinfo1[%d]\t0x%016lx\n", vcpu, ctl); + error = vm_get_vmcb_field(ctx, vcpu, VMCB_OFF_EXITINFO2, + 8, &ctl); + if (error == 0) + printf("exitinfo2[%d]\t0x%016lx\n", vcpu, ctl); + error = vm_get_vmcb_field(ctx, vcpu, VMCB_OFF_EXITINTINFO, + 8, &ctl); + if (error == 0) + printf("exitintinfo[%d]\t0x%016lx\n", vcpu, ctl); + } + + if (!error && (get_vmcb_virq || get_all)) { + error = vm_get_vmcb_field(ctx, vcpu, VMCB_OFF_VIRQ, + 8, &ctl); + if (error == 0) + printf("v_irq/tpr[%d]\t0x%016lx\n", vcpu, ctl); + } + + if (!error && (get_apic_access_addr || get_all)) { + error = vm_get_vmcb_field(ctx, vcpu, VMCB_OFF_AVIC_BAR, 8, + &addr); + if (error == 0) + printf("AVIC apic_bar[%d]\t0x%016lx\n", vcpu, addr); + } + + if (!error && (get_virtual_apic_addr || get_all)) { + error = vm_get_vmcb_field(ctx, vcpu, VMCB_OFF_AVIC_PAGE, 8, + &addr); + if (error == 0) + printf("AVIC backing page[%d]\t0x%016lx\n", vcpu, addr); + } + + if (!error && (get_avic_table || get_all)) { + error = vm_get_vmcb_field(ctx, vcpu, VMCB_OFF_AVIC_LT, 8, + &addr); + if (error == 0) + printf("AVIC logical table[%d]\t0x%016lx\n", + vcpu, addr); + error = vm_get_vmcb_field(ctx, vcpu, VMCB_OFF_AVIC_PT, 8, + &addr); + if (error == 0) + printf("AVIC physical table[%d]\t0x%016lx\n", + vcpu, addr); + } + + return (error); +} + +static struct option * +setup_options(bool cpu_intel) +{ + const struct option common_opts[] = { { "vm", REQ_ARG, 0, VMNAME }, { "cpu", REQ_ARG, 0, VCPU }, { "set-mem", REQ_ARG, 0, SET_MEM }, @@ -488,10 +1262,8 @@ main(int argc, char *argv[]) { "set-tr", REQ_ARG, 0, SET_TR }, { "set-ldtr", REQ_ARG, 0, SET_LDTR }, { "set-x2apic-state",REQ_ARG, 0, SET_X2APIC_STATE }, - { "set-vmcs-exception-bitmap", - REQ_ARG, 0, SET_VMCS_EXCEPTION_BITMAP }, - { "set-vmcs-entry-interruption-info", - REQ_ARG, 0, SET_VMCS_ENTRY_INTERRUPTION_INFO }, + { "set-exception-bitmap", + REQ_ARG, 0, SET_EXCEPTION_BITMAP }, { "capname", REQ_ARG, 0, CAPNAME }, { "unassign-pptdev", REQ_ARG, 0, UNASSIGN_PPTDEV }, { "setcap", REQ_ARG, 0, SET_CAP }, @@ -552,6 +1324,35 @@ main(int argc, char *argv[]) { "get-ss", NO_ARG, &get_ss, 1 }, { "get-tr", NO_ARG, &get_tr, 1 }, { "get-ldtr", NO_ARG, &get_ldtr, 1 }, + { "get-eptp", NO_ARG, &get_eptp, 1 }, + { "get-exception-bitmap", + NO_ARG, &get_exception_bitmap, 1 }, + { "get-io-bitmap-address", + NO_ARG, &get_io_bitmap, 1 }, + { "get-tsc-offset", NO_ARG, &get_tsc_offset, 1 }, + { "get-msr-bitmap", + NO_ARG, &get_msr_bitmap, 1 }, + { "get-msr-bitmap-address", + NO_ARG, &get_msr_bitmap_address, 1 }, + { "get-guest-pat", NO_ARG, &get_guest_pat, 1 }, + { "get-guest-sysenter", + NO_ARG, &get_guest_sysenter, 1 }, + { "get-exit-reason", + NO_ARG, &get_exit_reason, 1 }, + { "get-x2apic-state", NO_ARG, &get_x2apic_state, 1 }, + { "get-all", NO_ARG, &get_all, 1 }, + { "run", NO_ARG, &run, 1 }, + { "create", NO_ARG, &create, 1 }, + { "destroy", NO_ARG, &destroy, 1 }, + { "inject-nmi", NO_ARG, &inject_nmi, 1 }, + { "force-reset", NO_ARG, &force_reset, 1 }, + { "force-poweroff", NO_ARG, &force_poweroff, 1 }, + { "get-active-cpus", NO_ARG, &get_active_cpus, 1 }, + { "get-suspended-cpus", NO_ARG, &get_suspended_cpus, 1 }, + { "get-intinfo", NO_ARG, &get_intinfo, 1 }, + }; + + const struct option intel_opts[] = { { "get-vmcs-pinbased-ctls", NO_ARG, &get_pinbased_ctls, 1 }, { "get-vmcs-procbased-ctls", @@ -564,74 +1365,123 @@ main(int argc, char *argv[]) NO_ARG, &get_vmcs_gpa, 1 }, { "get-vmcs-entry-interruption-info", NO_ARG, &get_vmcs_entry_interruption_info, 1}, - { "get-vmcs-eptp", NO_ARG, &get_eptp, 1 }, - { "get-vmcs-exception-bitmap", - NO_ARG, &get_exception_bitmap, 1 }, - { "get-vmcs-io-bitmap-address", - NO_ARG, &get_io_bitmap, 1 }, - { "get-vmcs-tsc-offset", NO_ARG,&get_tsc_offset, 1 }, { "get-vmcs-cr0-mask", NO_ARG, &get_cr0_mask, 1 }, { "get-vmcs-cr0-shadow", NO_ARG,&get_cr0_shadow, 1 }, - { "get-vmcs-cr4-mask", NO_ARG, &get_cr4_mask, 1 }, - { "get-vmcs-cr4-shadow", NO_ARG,&get_cr4_shadow, 1 }, - { "get-vmcs-cr3-targets", NO_ARG, &get_cr3_targets, 1}, - { "get-vmcs-apic-access-address", - NO_ARG, &get_apic_access_addr, 1}, - { "get-vmcs-virtual-apic-address", - NO_ARG, &get_virtual_apic_addr, 1}, + { "get-vmcs-cr4-mask", NO_ARG, &get_cr4_mask, 1 }, + { "get-vmcs-cr4-shadow", NO_ARG, &get_cr4_shadow, 1 }, + { "get-vmcs-cr3-targets", NO_ARG, &get_cr3_targets, 1 }, { "get-vmcs-tpr-threshold", - NO_ARG, &get_tpr_threshold, 1 }, - { "get-vmcs-msr-bitmap", - NO_ARG, &get_msr_bitmap, 1 }, - { "get-vmcs-msr-bitmap-address", - NO_ARG, &get_msr_bitmap_address, 1 }, - { "get-vmcs-vpid", NO_ARG, &get_vpid, 1 }, - { "get-vmcs-ple-gap", NO_ARG, &get_ple_gap, 1 }, - { "get-vmcs-ple-window", NO_ARG,&get_ple_window,1 }, - { "get-vmcs-instruction-error", - NO_ARG, &get_inst_err, 1 }, - { "get-vmcs-exit-ctls", NO_ARG, &get_exit_ctls, 1 }, + NO_ARG, &get_tpr_threshold, 1 }, + { "get-vmcs-vpid", NO_ARG, &get_vpid_asid, 1 }, + { "get-vmcs-exit-ctls", NO_ARG, &get_exit_ctls, 1 }, { "get-vmcs-entry-ctls", NO_ARG, &get_entry_ctls, 1 }, - { "get-vmcs-guest-pat", NO_ARG, &get_guest_pat, 1 }, + { "get-vmcs-instruction-error", + NO_ARG, &get_inst_err, 1 }, { "get-vmcs-host-pat", NO_ARG, &get_host_pat, 1 }, { "get-vmcs-host-cr0", - NO_ARG, &get_host_cr0, 1 }, + NO_ARG, &get_host_cr0, 1 }, + { "set-vmcs-entry-interruption-info", + REQ_ARG, 0, SET_VMCS_ENTRY_INTERRUPTION_INFO }, + { "get-vmcs-exit-qualification", + NO_ARG, &get_vmcs_exit_qualification, 1 }, + { "get-vmcs-interruptibility", + NO_ARG, &get_vmcs_interruptibility, 1 }, + { "get-vmcs-exit-interruption-error", + NO_ARG, &get_vmcs_exit_interruption_error, 1 }, + { "get-vmcs-exit-interruption-info", + NO_ARG, &get_vmcs_exit_interruption_info, 1 }, + { "get-vmcs-link", NO_ARG, &get_vmcs_link, 1 }, { "get-vmcs-host-cr3", - NO_ARG, &get_host_cr3, 1 }, + NO_ARG, &get_host_cr3, 1 }, { "get-vmcs-host-cr4", NO_ARG, &get_host_cr4, 1 }, { "get-vmcs-host-rip", NO_ARG, &get_host_rip, 1 }, { "get-vmcs-host-rsp", NO_ARG, &get_host_rsp, 1 }, - { "get-vmcs-guest-sysenter", - NO_ARG, &get_guest_sysenter, 1 }, - { "get-vmcs-link", NO_ARG, &get_vmcs_link, 1 }, - { "get-vmcs-exit-reason", - NO_ARG, &get_vmcs_exit_reason, 1 }, - { "get-vmcs-exit-qualification", - NO_ARG, &get_vmcs_exit_qualification, 1 }, - { "get-vmcs-exit-interruption-info", - NO_ARG, &get_vmcs_exit_interruption_info, 1}, - { "get-vmcs-exit-interruption-error", - NO_ARG, &get_vmcs_exit_interruption_error, 1}, - { "get-vmcs-interruptibility", - NO_ARG, &get_vmcs_interruptibility, 1 }, - { "get-x2apic-state",NO_ARG, &get_x2apic_state, 1 }, - { "get-all", NO_ARG, &get_all, 1 }, - { "run", NO_ARG, &run, 1 }, - { "create", NO_ARG, &create, 1 }, - { "destroy", NO_ARG, &destroy, 1 }, - { "inject-nmi", NO_ARG, &inject_nmi, 1 }, - { "force-reset", NO_ARG, &force_reset, 1 }, - { "force-poweroff", NO_ARG, &force_poweroff, 1 }, - { "get-active-cpus", NO_ARG, &get_active_cpus, 1 }, - { "get-suspended-cpus", NO_ARG, &get_suspended_cpus, 1 }, - { "get-intinfo", NO_ARG, &get_intinfo, 1 }, - { NULL, 0, NULL, 0 } + { "get-apic-access-address", + NO_ARG, &get_apic_access_addr, 1}, + { "get-virtual-apic-address", + NO_ARG, &get_virtual_apic_addr, 1} + }; + + const struct option amd_opts[] = { + { "get-vmcb-intercepts", + NO_ARG, &get_vmcb_intercept, 1 }, + { "get-vmcb-asid", + NO_ARG, &get_vpid_asid, 1 }, + { "get-vmcb-exit-details", + NO_ARG, &get_vmcb_exit_details, 1 }, + { "get-vmcb-tlb-ctrl", + NO_ARG, &get_vmcb_tlb_ctrl, 1 }, + { "get-vmcb-virq", + NO_ARG, &get_vmcb_virq, 1 }, + { "get-avic-apic-bar", + NO_ARG, &get_apic_access_addr, 1 }, + { "get-avic-backing-page", + NO_ARG, &get_virtual_apic_addr, 1 }, + { "get-avic-table", + NO_ARG, &get_avic_table, 1 } }; + const struct option null_opt = { + NULL, 0, NULL, 0 + }; + + struct option *all_opts; + char *cp; + int optlen; + + optlen = sizeof(common_opts); + + if (cpu_intel) + optlen += sizeof(intel_opts); + else + optlen += sizeof(amd_opts); + + optlen += sizeof(null_opt); + + all_opts = malloc(optlen); + + cp = (char *)all_opts; + memcpy(cp, common_opts, sizeof(common_opts)); + cp += sizeof(common_opts); + + if (cpu_intel) { + memcpy(cp, intel_opts, sizeof(intel_opts)); + cp += sizeof(intel_opts); + } else { + memcpy(cp, amd_opts, sizeof(amd_opts)); + cp += sizeof(amd_opts); + } + + memcpy(cp, &null_opt, sizeof(null_opt)); + cp += sizeof(null_opt); + + return (all_opts); +} + +int +main(int argc, char *argv[]) +{ + char *vmname; + int error, ch, vcpu, ptenum; + vm_paddr_t gpa, gpa_pmap; + size_t len; + struct vm_exit vmexit; + uint64_t rax, cr0, cr3, cr4, dr7, rsp, rip, rflags, efer, pat; + uint64_t eptp, bm, addr, u64, pteval[4], *pte, info[2]; + struct vmctx *ctx; + int wired; + cpuset_t cpus; + bool cpu_intel; + uint64_t cs, ds, es, fs, gs, ss, tr, ldtr; + struct option *opts; + + cpu_intel = cpu_vendor_intel(); + opts = setup_options(cpu_intel); + vcpu = 0; vmname = NULL; assert_lapic_lvt = -1; @@ -732,7 +1582,7 @@ main(int argc, char *argv[]) x2apic_state = strtol(optarg, NULL, 0); set_x2apic_state = 1; break; - case SET_VMCS_EXCEPTION_BITMAP: + case SET_EXCEPTION_BITMAP: exception_bitmap = strtoul(optarg, NULL, 0); set_exception_bitmap = 1; break; @@ -754,20 +1604,20 @@ main(int argc, char *argv[]) case UNASSIGN_PPTDEV: unassign_pptdev = 1; if (sscanf(optarg, "%d/%d/%d", &bus, &slot, &func) != 3) - usage(); + usage(cpu_intel); break; case ASSERT_LAPIC_LVT: assert_lapic_lvt = atoi(optarg); break; default: - usage(); + usage(cpu_intel); } } argc -= optind; argv += optind; if (vmname == NULL) - usage(); + usage(cpu_intel); error = 0; @@ -776,8 +1626,10 @@ main(int argc, char *argv[]) if (!error) { ctx = vm_open(vmname); - if (ctx == NULL) - error = -1; + if (ctx == NULL) { + printf("VM:%s is not created.\n", vmname); + exit (1); + } } if (!error && memsize) @@ -893,11 +1745,17 @@ main(int argc, char *argv[]) error = vm_unassign_pptdev(ctx, bus, slot, func); if (!error && set_exception_bitmap) { - error = vm_set_vmcs_field(ctx, vcpu, VMCS_EXCEPTION_BITMAP, - exception_bitmap); + if (cpu_intel) + error = vm_set_vmcs_field(ctx, vcpu, + VMCS_EXCEPTION_BITMAP, + exception_bitmap); + else + error = vm_set_vmcb_field(ctx, vcpu, + VMCB_OFF_EXC_INTERCEPT, + 4, exception_bitmap); } - if (!error && set_vmcs_entry_interruption_info) { + if (!error && cpu_intel && set_vmcs_entry_interruption_info) { error = vm_set_vmcs_field(ctx, vcpu, VMCS_ENTRY_INTR_INFO, vmcs_entry_interruption_info); } @@ -926,621 +1784,172 @@ main(int argc, char *argv[]) wired ? " wired" : ""); } - if (!error && (get_efer || get_all)) { - error = vm_get_register(ctx, vcpu, VM_REG_GUEST_EFER, &efer); - if (error == 0) - printf("efer[%d]\t\t0x%016lx\n", vcpu, efer); - } - - if (!error && (get_cr0 || get_all)) { - error = vm_get_register(ctx, vcpu, VM_REG_GUEST_CR0, &cr0); - if (error == 0) - printf("cr0[%d]\t\t0x%016lx\n", vcpu, cr0); - } - - if (!error && (get_cr3 || get_all)) { - error = vm_get_register(ctx, vcpu, VM_REG_GUEST_CR3, &cr3); - if (error == 0) - printf("cr3[%d]\t\t0x%016lx\n", vcpu, cr3); - } - - if (!error && (get_cr4 || get_all)) { - error = vm_get_register(ctx, vcpu, VM_REG_GUEST_CR4, &cr4); - if (error == 0) - printf("cr4[%d]\t\t0x%016lx\n", vcpu, cr4); - } - - if (!error && (get_dr7 || get_all)) { - error = vm_get_register(ctx, vcpu, VM_REG_GUEST_DR7, &dr7); - if (error == 0) - printf("dr7[%d]\t\t0x%016lx\n", vcpu, dr7); - } - - if (!error && (get_rsp || get_all)) { - error = vm_get_register(ctx, vcpu, VM_REG_GUEST_RSP, &rsp); - if (error == 0) - printf("rsp[%d]\t\t0x%016lx\n", vcpu, rsp); - } - - if (!error && (get_rip || get_all)) { - error = vm_get_register(ctx, vcpu, VM_REG_GUEST_RIP, &rip); - if (error == 0) - printf("rip[%d]\t\t0x%016lx\n", vcpu, rip); - } - - if (!error && (get_rax || get_all)) { - error = vm_get_register(ctx, vcpu, VM_REG_GUEST_RAX, &rax); - if (error == 0) - printf("rax[%d]\t\t0x%016lx\n", vcpu, rax); - } - - if (!error && (get_rbx || get_all)) { - error = vm_get_register(ctx, vcpu, VM_REG_GUEST_RBX, &rbx); - if (error == 0) - printf("rbx[%d]\t\t0x%016lx\n", vcpu, rbx); - } - - if (!error && (get_rcx || get_all)) { - error = vm_get_register(ctx, vcpu, VM_REG_GUEST_RCX, &rcx); - if (error == 0) - printf("rcx[%d]\t\t0x%016lx\n", vcpu, rcx); - } - - if (!error && (get_rdx || get_all)) { - error = vm_get_register(ctx, vcpu, VM_REG_GUEST_RDX, &rdx); - if (error == 0) - printf("rdx[%d]\t\t0x%016lx\n", vcpu, rdx); - } - - if (!error && (get_rsi || get_all)) { - error = vm_get_register(ctx, vcpu, VM_REG_GUEST_RSI, &rsi); - if (error == 0) - printf("rsi[%d]\t\t0x%016lx\n", vcpu, rsi); - } - - if (!error && (get_rdi || get_all)) { - error = vm_get_register(ctx, vcpu, VM_REG_GUEST_RDI, &rdi); - if (error == 0) - printf("rdi[%d]\t\t0x%016lx\n", vcpu, rdi); - } - - if (!error && (get_rbp || get_all)) { - error = vm_get_register(ctx, vcpu, VM_REG_GUEST_RBP, &rbp); - if (error == 0) - printf("rbp[%d]\t\t0x%016lx\n", vcpu, rbp); - } - - if (!error && (get_r8 || get_all)) { - error = vm_get_register(ctx, vcpu, VM_REG_GUEST_R8, &r8); - if (error == 0) - printf("r8[%d]\t\t0x%016lx\n", vcpu, r8); - } - - if (!error && (get_r9 || get_all)) { - error = vm_get_register(ctx, vcpu, VM_REG_GUEST_R9, &r9); - if (error == 0) - printf("r9[%d]\t\t0x%016lx\n", vcpu, r9); - } - - if (!error && (get_r10 || get_all)) { - error = vm_get_register(ctx, vcpu, VM_REG_GUEST_R10, &r10); - if (error == 0) - printf("r10[%d]\t\t0x%016lx\n", vcpu, r10); - } - - if (!error && (get_r11 || get_all)) { - error = vm_get_register(ctx, vcpu, VM_REG_GUEST_R11, &r11); - if (error == 0) - printf("r11[%d]\t\t0x%016lx\n", vcpu, r11); - } - - if (!error && (get_r12 || get_all)) { - error = vm_get_register(ctx, vcpu, VM_REG_GUEST_R12, &r12); - if (error == 0) - printf("r12[%d]\t\t0x%016lx\n", vcpu, r12); - } - - if (!error && (get_r13 || get_all)) { - error = vm_get_register(ctx, vcpu, VM_REG_GUEST_R13, &r13); - if (error == 0) - printf("r13[%d]\t\t0x%016lx\n", vcpu, r13); - } - - if (!error && (get_r14 || get_all)) { - error = vm_get_register(ctx, vcpu, VM_REG_GUEST_R14, &r14); - if (error == 0) - printf("r14[%d]\t\t0x%016lx\n", vcpu, r14); - } - - if (!error && (get_r15 || get_all)) { - error = vm_get_register(ctx, vcpu, VM_REG_GUEST_R15, &r15); - if (error == 0) - printf("r15[%d]\t\t0x%016lx\n", vcpu, r15); - } - - if (!error && (get_rflags || get_all)) { - error = vm_get_register(ctx, vcpu, VM_REG_GUEST_RFLAGS, - &rflags); - if (error == 0) - printf("rflags[%d]\t0x%016lx\n", vcpu, rflags); - } - - if (!error && (get_stats || get_all)) { - int i, num_stats; - uint64_t *stats; - struct timeval tv; - const char *desc; - - stats = vm_get_stats(ctx, vcpu, &tv, &num_stats); - if (stats != NULL) { - printf("vcpu%d\n", vcpu); - for (i = 0; i < num_stats; i++) { - desc = vm_get_stat_desc(ctx, i); - printf("%-40s\t%ld\n", desc, stats[i]); - } - } - } - - if (!error && (get_desc_ds || get_all)) { - error = vm_get_desc(ctx, vcpu, VM_REG_GUEST_DS, - &desc_base, &desc_limit, &desc_access); - if (error == 0) { - printf("ds desc[%d]\t0x%016lx/0x%08x/0x%08x\n", - vcpu, desc_base, desc_limit, desc_access); - } - } - - if (!error && (get_desc_es || get_all)) { - error = vm_get_desc(ctx, vcpu, VM_REG_GUEST_ES, - &desc_base, &desc_limit, &desc_access); - if (error == 0) { - printf("es desc[%d]\t0x%016lx/0x%08x/0x%08x\n", - vcpu, desc_base, desc_limit, desc_access); - } - } - - if (!error && (get_desc_fs || get_all)) { - error = vm_get_desc(ctx, vcpu, VM_REG_GUEST_FS, - &desc_base, &desc_limit, &desc_access); - if (error == 0) { - printf("fs desc[%d]\t0x%016lx/0x%08x/0x%08x\n", - vcpu, desc_base, desc_limit, desc_access); - } - } - - if (!error && (get_desc_gs || get_all)) { - error = vm_get_desc(ctx, vcpu, VM_REG_GUEST_GS, - &desc_base, &desc_limit, &desc_access); - if (error == 0) { - printf("gs desc[%d]\t0x%016lx/0x%08x/0x%08x\n", - vcpu, desc_base, desc_limit, desc_access); - } - } - - if (!error && (get_desc_ss || get_all)) { - error = vm_get_desc(ctx, vcpu, VM_REG_GUEST_SS, - &desc_base, &desc_limit, &desc_access); - if (error == 0) { - printf("ss desc[%d]\t0x%016lx/0x%08x/0x%08x\n", - vcpu, desc_base, desc_limit, desc_access); - } - } - - if (!error && (get_desc_cs || get_all)) { - error = vm_get_desc(ctx, vcpu, VM_REG_GUEST_CS, - &desc_base, &desc_limit, &desc_access); - if (error == 0) { - printf("cs desc[%d]\t0x%016lx/0x%08x/0x%08x\n", - vcpu, desc_base, desc_limit, desc_access); - } - } + if (!error) + error = get_all_registers(ctx, vcpu); - if (!error && (get_desc_tr || get_all)) { - error = vm_get_desc(ctx, vcpu, VM_REG_GUEST_TR, - &desc_base, &desc_limit, &desc_access); - if (error == 0) { - printf("tr desc[%d]\t0x%016lx/0x%08x/0x%08x\n", - vcpu, desc_base, desc_limit, desc_access); - } - } + if (!error) + error = get_all_segments(ctx, vcpu); - if (!error && (get_desc_ldtr || get_all)) { - error = vm_get_desc(ctx, vcpu, VM_REG_GUEST_LDTR, - &desc_base, &desc_limit, &desc_access); - if (error == 0) { - printf("ldtr desc[%d]\t0x%016lx/0x%08x/0x%08x\n", - vcpu, desc_base, desc_limit, desc_access); - } - } - - if (!error && (get_desc_gdtr || get_all)) { - error = vm_get_desc(ctx, vcpu, VM_REG_GUEST_GDTR, - &desc_base, &desc_limit, &desc_access); - if (error == 0) { - printf("gdtr[%d]\t\t0x%016lx/0x%08x\n", - vcpu, desc_base, desc_limit); - } - } - - if (!error && (get_desc_idtr || get_all)) { - error = vm_get_desc(ctx, vcpu, VM_REG_GUEST_IDTR, - &desc_base, &desc_limit, &desc_access); - if (error == 0) { - printf("idtr[%d]\t\t0x%016lx/0x%08x\n", - vcpu, desc_base, desc_limit); - } - } - - if (!error && (get_cs || get_all)) { - error = vm_get_register(ctx, vcpu, VM_REG_GUEST_CS, &cs); - if (error == 0) - printf("cs[%d]\t\t0x%04lx\n", vcpu, cs); - } - - if (!error && (get_ds || get_all)) { - error = vm_get_register(ctx, vcpu, VM_REG_GUEST_DS, &ds); - if (error == 0) - printf("ds[%d]\t\t0x%04lx\n", vcpu, ds); - } - - if (!error && (get_es || get_all)) { - error = vm_get_register(ctx, vcpu, VM_REG_GUEST_ES, &es); - if (error == 0) - printf("es[%d]\t\t0x%04lx\n", vcpu, es); - } - - if (!error && (get_fs || get_all)) { - error = vm_get_register(ctx, vcpu, VM_REG_GUEST_FS, &fs); - if (error == 0) - printf("fs[%d]\t\t0x%04lx\n", vcpu, fs); - } - - if (!error && (get_gs || get_all)) { - error = vm_get_register(ctx, vcpu, VM_REG_GUEST_GS, &gs); - if (error == 0) - printf("gs[%d]\t\t0x%04lx\n", vcpu, gs); - } - - if (!error && (get_ss || get_all)) { - error = vm_get_register(ctx, vcpu, VM_REG_GUEST_SS, &ss); - if (error == 0) - printf("ss[%d]\t\t0x%04lx\n", vcpu, ss); - } - - if (!error && (get_tr || get_all)) { - error = vm_get_register(ctx, vcpu, VM_REG_GUEST_TR, &tr); - if (error == 0) - printf("tr[%d]\t\t0x%04lx\n", vcpu, tr); - } - - if (!error && (get_ldtr || get_all)) { - error = vm_get_register(ctx, vcpu, VM_REG_GUEST_LDTR, &ldtr); - if (error == 0) - printf("ldtr[%d]\t\t0x%04lx\n", vcpu, ldtr); + if (!error) { + if (cpu_intel) + error = get_misc_vmcs(ctx, vcpu); + else + error = get_misc_vmcb(ctx, vcpu); } - + if (!error && (get_x2apic_state || get_all)) { error = vm_get_x2apic_state(ctx, vcpu, &x2apic_state); if (error == 0) printf("x2apic_state[%d]\t%d\n", vcpu, x2apic_state); } - if (!error && (get_pinbased_ctls || get_all)) { - error = vm_get_vmcs_field(ctx, vcpu, VMCS_PIN_BASED_CTLS, &ctl); - if (error == 0) - printf("pinbased_ctls[%d]\t0x%08lx\n", vcpu, ctl); - } - - if (!error && (get_procbased_ctls || get_all)) { - error = vm_get_vmcs_field(ctx, vcpu, - VMCS_PRI_PROC_BASED_CTLS, &ctl); - if (error == 0) - printf("procbased_ctls[%d]\t0x%08lx\n", vcpu, ctl); - } - - if (!error && (get_procbased_ctls2 || get_all)) { - error = vm_get_vmcs_field(ctx, vcpu, - VMCS_SEC_PROC_BASED_CTLS, &ctl); - if (error == 0) - printf("procbased_ctls2[%d]\t0x%08lx\n", vcpu, ctl); - } - - if (!error && (get_vmcs_gla || get_all)) { - error = vm_get_vmcs_field(ctx, vcpu, - VMCS_GUEST_LINEAR_ADDRESS, &u64); - if (error == 0) - printf("gla[%d]\t\t0x%016lx\n", vcpu, u64); - } - - if (!error && (get_vmcs_gpa || get_all)) { - error = vm_get_vmcs_field(ctx, vcpu, - VMCS_GUEST_PHYSICAL_ADDRESS, &u64); - if (error == 0) - printf("gpa[%d]\t\t0x%016lx\n", vcpu, u64); - } - - if (!error && (get_vmcs_entry_interruption_info || get_all)) { - error = vm_get_vmcs_field(ctx, vcpu, VMCS_ENTRY_INTR_INFO,&u64); - if (error == 0) { - printf("entry_interruption_info[%d]\t0x%08lx\n", - vcpu, u64); - } - } - if (!error && (get_eptp || get_all)) { - error = vm_get_vmcs_field(ctx, vcpu, VMCS_EPTP, &eptp); + if (cpu_intel) + error = vm_get_vmcs_field(ctx, vcpu, VMCS_EPTP, &eptp); + else + error = vm_get_vmcb_field(ctx, vcpu, VMCB_OFF_NPT_BASE, + 8, &eptp); if (error == 0) - printf("eptp[%d]\t\t0x%016lx\n", vcpu, eptp); + printf("%s[%d]\t\t0x%016lx\n", + cpu_intel ? "eptp" : "rvi/npt", vcpu, eptp); } if (!error && (get_exception_bitmap || get_all)) { - error = vm_get_vmcs_field(ctx, vcpu, VMCS_EXCEPTION_BITMAP, - &bm); + if(cpu_intel) + error = vm_get_vmcs_field(ctx, vcpu, + VMCS_EXCEPTION_BITMAP, &bm); + else + error = vm_get_vmcb_field(ctx, vcpu, + VMCB_OFF_EXC_INTERCEPT, + 4, &bm); if (error == 0) - printf("exception_bitmap[%d]\t0x%08lx\n", vcpu, bm); + printf("exception_bitmap[%d]\t%#lx\n", vcpu, bm); } if (!error && (get_io_bitmap || get_all)) { - error = vm_get_vmcs_field(ctx, vcpu, VMCS_IO_BITMAP_A, &bm); - if (error == 0) - printf("io_bitmap_a[%d]\t0x%08lx\n", vcpu, bm); - error = vm_get_vmcs_field(ctx, vcpu, VMCS_IO_BITMAP_B, &bm); - if (error == 0) - printf("io_bitmap_b[%d]\t0x%08lx\n", vcpu, bm); + if (cpu_intel) { + error = vm_get_vmcs_field(ctx, vcpu, VMCS_IO_BITMAP_A, + &bm); + if (error == 0) + printf("io_bitmap_a[%d]\t%#lx\n", vcpu, bm); + error = vm_get_vmcs_field(ctx, vcpu, VMCS_IO_BITMAP_B, + &bm); + if (error == 0) + printf("io_bitmap_b[%d]\t%#lx\n", vcpu, bm); + } else { + error = vm_get_vmcb_field(ctx, vcpu, + VMCB_OFF_IO_PERM, 8, &bm); + if (error == 0) + printf("io_bitmap[%d]\t%#lx\n", vcpu, bm); + } } if (!error && (get_tsc_offset || get_all)) { uint64_t tscoff; - error = vm_get_vmcs_field(ctx, vcpu, VMCS_TSC_OFFSET, &tscoff); + if (cpu_intel) + error = vm_get_vmcs_field(ctx, vcpu, VMCS_TSC_OFFSET, + &tscoff); + else + error = vm_get_vmcb_field(ctx, vcpu, + VMCB_OFF_TSC_OFFSET, + 8, &tscoff); if (error == 0) printf("tsc_offset[%d]\t0x%016lx\n", vcpu, tscoff); } - if (!error && (get_cr0_mask || get_all)) { - uint64_t cr0mask; - error = vm_get_vmcs_field(ctx, vcpu, VMCS_CR0_MASK, &cr0mask); - if (error == 0) - printf("cr0_mask[%d]\t\t0x%016lx\n", vcpu, cr0mask); - } - - if (!error && (get_cr0_shadow || get_all)) { - uint64_t cr0shadow; - error = vm_get_vmcs_field(ctx, vcpu, VMCS_CR0_SHADOW, - &cr0shadow); - if (error == 0) - printf("cr0_shadow[%d]\t\t0x%016lx\n", vcpu, cr0shadow); - } - - if (!error && (get_cr4_mask || get_all)) { - uint64_t cr4mask; - error = vm_get_vmcs_field(ctx, vcpu, VMCS_CR4_MASK, &cr4mask); - if (error == 0) - printf("cr4_mask[%d]\t\t0x%016lx\n", vcpu, cr4mask); - } - - if (!error && (get_cr4_shadow || get_all)) { - uint64_t cr4shadow; - error = vm_get_vmcs_field(ctx, vcpu, VMCS_CR4_SHADOW, - &cr4shadow); - if (error == 0) - printf("cr4_shadow[%d]\t\t0x%016lx\n", vcpu, cr4shadow); - } - - if (!error && (get_cr3_targets || get_all)) { - uint64_t target_count, target_addr; - error = vm_get_vmcs_field(ctx, vcpu, VMCS_CR3_TARGET_COUNT, - &target_count); - if (error == 0) { - printf("cr3_target_count[%d]\t0x%08lx\n", - vcpu, target_count); - } - - error = vm_get_vmcs_field(ctx, vcpu, VMCS_CR3_TARGET0, - &target_addr); - if (error == 0) { - printf("cr3_target0[%d]\t\t0x%016lx\n", - vcpu, target_addr); - } - - error = vm_get_vmcs_field(ctx, vcpu, VMCS_CR3_TARGET1, - &target_addr); - if (error == 0) { - printf("cr3_target1[%d]\t\t0x%016lx\n", - vcpu, target_addr); - } - - error = vm_get_vmcs_field(ctx, vcpu, VMCS_CR3_TARGET2, - &target_addr); - if (error == 0) { - printf("cr3_target2[%d]\t\t0x%016lx\n", - vcpu, target_addr); - } - - error = vm_get_vmcs_field(ctx, vcpu, VMCS_CR3_TARGET3, - &target_addr); - if (error == 0) { - printf("cr3_target3[%d]\t\t0x%016lx\n", - vcpu, target_addr); - } - } - - if (!error && (get_apic_access_addr || get_all)) { - error = vm_get_vmcs_field(ctx, vcpu, VMCS_APIC_ACCESS, &addr); - if (error == 0) - printf("apic_access_addr[%d]\t0x%016lx\n", vcpu, addr); - } - - if (!error && (get_virtual_apic_addr || get_all)) { - error = vm_get_vmcs_field(ctx, vcpu, VMCS_VIRTUAL_APIC, &addr); - if (error == 0) - printf("virtual_apic_addr[%d]\t0x%016lx\n", vcpu, addr); - } - - if (!error && (get_tpr_threshold || get_all)) { - uint64_t threshold; - error = vm_get_vmcs_field(ctx, vcpu, VMCS_TPR_THRESHOLD, - &threshold); - if (error == 0) - printf("tpr_threshold[%d]\t0x%08lx\n", vcpu, threshold); - } - if (!error && (get_msr_bitmap_address || get_all)) { - error = vm_get_vmcs_field(ctx, vcpu, VMCS_MSR_BITMAP, &addr); + if (cpu_intel) + error = vm_get_vmcs_field(ctx, vcpu, VMCS_MSR_BITMAP, + &addr); + else + error = vm_get_vmcb_field(ctx, vcpu, + VMCB_OFF_MSR_PERM, 8, &addr); if (error == 0) - printf("msr_bitmap[%d]\t\t0x%016lx\n", vcpu, addr); + printf("msr_bitmap[%d]\t\t%#lx\n", vcpu, addr); } if (!error && (get_msr_bitmap || get_all)) { - error = vm_get_vmcs_field(ctx, vcpu, VMCS_MSR_BITMAP, &addr); - if (error == 0) - error = dump_vmcs_msr_bitmap(vcpu, addr); - } - - if (!error && (get_vpid || get_all)) { - uint64_t vpid; - error = vm_get_vmcs_field(ctx, vcpu, VMCS_VPID, &vpid); - if (error == 0) - printf("vpid[%d]\t\t0x%04lx\n", vcpu, vpid); - } - - if (!error && (get_ple_window || get_all)) { - uint64_t window; - error = vm_get_vmcs_field(ctx, vcpu, VMCS_PLE_WINDOW, &window); - if (error == 0) - printf("ple_window[%d]\t\t0x%08lx\n", vcpu, window); - } - - if (!error && (get_ple_gap || get_all)) { - uint64_t gap; - error = vm_get_vmcs_field(ctx, vcpu, VMCS_PLE_GAP, &gap); - if (error == 0) - printf("ple_gap[%d]\t\t0x%08lx\n", vcpu, gap); - } - - if (!error && (get_inst_err || get_all)) { - uint64_t insterr; - error = vm_get_vmcs_field(ctx, vcpu, VMCS_INSTRUCTION_ERROR, - &insterr); - if (error == 0) { - printf("instruction_error[%d]\t0x%08lx\n", - vcpu, insterr); + if (cpu_intel) { + error = vm_get_vmcs_field(ctx, vcpu, + VMCS_MSR_BITMAP, &addr); + } else { + error = vm_get_vmcb_field(ctx, vcpu, + VMCB_OFF_MSR_PERM, 8, + &addr); } - } - if (!error && (get_exit_ctls || get_all)) { - error = vm_get_vmcs_field(ctx, vcpu, VMCS_EXIT_CTLS, &ctl); if (error == 0) - printf("exit_ctls[%d]\t\t0x%08lx\n", vcpu, ctl); + error = dump_msr_bitmap(vcpu, addr, cpu_intel); } - if (!error && (get_entry_ctls || get_all)) { - error = vm_get_vmcs_field(ctx, vcpu, VMCS_ENTRY_CTLS, &ctl); - if (error == 0) - printf("entry_ctls[%d]\t\t0x%08lx\n", vcpu, ctl); - } - - if (!error && (get_host_pat || get_all)) { - error = vm_get_vmcs_field(ctx, vcpu, VMCS_HOST_IA32_PAT, &pat); + if (!error && (get_vpid_asid || get_all)) { + uint64_t vpid; + if (cpu_intel) + error = vm_get_vmcs_field(ctx, vcpu, VMCS_VPID, &vpid); + else + error = vm_get_vmcb_field(ctx, vcpu, VMCB_OFF_ASID, + 4, &vpid); if (error == 0) - printf("host_pat[%d]\t\t0x%016lx\n", vcpu, pat); + printf("%s[%d]\t\t0x%04lx\n", + cpu_intel ? "vpid" : "asid", vcpu, vpid); } if (!error && (get_guest_pat || get_all)) { - error = vm_get_vmcs_field(ctx, vcpu, VMCS_GUEST_IA32_PAT, &pat); + if (cpu_intel) + error = vm_get_vmcs_field(ctx, vcpu, + VMCS_GUEST_IA32_PAT, &pat); + else + error = vm_get_vmcb_field(ctx, vcpu, + VMCB_OFF_GUEST_PAT, 8, &pat); if (error == 0) printf("guest_pat[%d]\t\t0x%016lx\n", vcpu, pat); } - if (!error && (get_host_cr0 || get_all)) { - error = vm_get_vmcs_field(ctx, vcpu, VMCS_HOST_CR0, &cr0); - if (error == 0) - printf("host_cr0[%d]\t\t0x%016lx\n", vcpu, cr0); - } - - if (!error && (get_host_cr3 || get_all)) { - error = vm_get_vmcs_field(ctx, vcpu, VMCS_HOST_CR3, &cr3); - if (error == 0) - printf("host_cr3[%d]\t\t0x%016lx\n", vcpu, cr3); - } - - if (!error && (get_host_cr4 || get_all)) { - error = vm_get_vmcs_field(ctx, vcpu, VMCS_HOST_CR4, &cr4); - if (error == 0) - printf("host_cr4[%d]\t\t0x%016lx\n", vcpu, cr4); - } - - if (!error && (get_host_rip || get_all)) { - error = vm_get_vmcs_field(ctx, vcpu, VMCS_HOST_RIP, &rip); - if (error == 0) - printf("host_rip[%d]\t\t0x%016lx\n", vcpu, rip); - } - - if (!error && (get_host_rsp || get_all)) { - error = vm_get_vmcs_field(ctx, vcpu, VMCS_HOST_RSP, &rsp); - if (error == 0) - printf("host_rsp[%d]\t\t0x%016lx\n", vcpu, rsp); - } - if (!error && (get_guest_sysenter || get_all)) { - error = vm_get_vmcs_field(ctx, vcpu, - VMCS_GUEST_IA32_SYSENTER_CS, &cs); - if (error == 0) - printf("guest_sysenter_cs[%d]\t0x%08lx\n", vcpu, cs); + if (cpu_intel) + error = vm_get_vmcs_field(ctx, vcpu, + VMCS_GUEST_IA32_SYSENTER_CS, + &cs); + else + error = vm_get_vmcb_field(ctx, vcpu, + VMCB_OFF_SYSENTER_CS, 8, + &cs); - error = vm_get_vmcs_field(ctx, vcpu, - VMCS_GUEST_IA32_SYSENTER_ESP, &rsp); if (error == 0) - printf("guest_sysenter_sp[%d]\t0x%016lx\n", vcpu, rsp); - error = vm_get_vmcs_field(ctx, vcpu, - VMCS_GUEST_IA32_SYSENTER_EIP, &rip); - if (error == 0) - printf("guest_sysenter_ip[%d]\t0x%016lx\n", vcpu, rip); - } + printf("guest_sysenter_cs[%d]\t%#lx\n", vcpu, cs); + if (cpu_intel) + error = vm_get_vmcs_field(ctx, vcpu, + VMCS_GUEST_IA32_SYSENTER_ESP, + &rsp); + else + error = vm_get_vmcb_field(ctx, vcpu, + VMCB_OFF_SYSENTER_ESP, 8, + &rsp); - if (!error && (get_vmcs_link || get_all)) { - error = vm_get_vmcs_field(ctx, vcpu, VMCS_LINK_POINTER, &addr); if (error == 0) - printf("vmcs_pointer[%d]\t0x%016lx\n", vcpu, addr); - } - - if (!error && (get_vmcs_exit_reason || get_all)) { - error = vm_get_vmcs_field(ctx, vcpu, VMCS_EXIT_REASON, &u64); + printf("guest_sysenter_sp[%d]\t%#lx\n", vcpu, rsp); + if (cpu_intel) + error = vm_get_vmcs_field(ctx, vcpu, + VMCS_GUEST_IA32_SYSENTER_EIP, + &rip); + else + error = vm_get_vmcb_field(ctx, vcpu, + VMCB_OFF_SYSENTER_EIP, 8, + &rip); if (error == 0) - printf("vmcs_exit_reason[%d]\t0x%016lx\n", vcpu, u64); + printf("guest_sysenter_ip[%d]\t%#lx\n", vcpu, rip); } - if (!error && (get_vmcs_exit_qualification || get_all)) { - error = vm_get_vmcs_field(ctx, vcpu, VMCS_EXIT_QUALIFICATION, - &u64); + if (!error && (get_exit_reason || get_all)) { + if (cpu_intel) + error = vm_get_vmcs_field(ctx, vcpu, VMCS_EXIT_REASON, + &u64); + else + error = vm_get_vmcb_field(ctx, vcpu, + VMCB_OFF_EXIT_REASON, 8, + &u64); if (error == 0) - printf("vmcs_exit_qualification[%d]\t0x%016lx\n", - vcpu, u64); - } - - if (!error && (get_vmcs_exit_interruption_info || get_all)) { - error = vm_get_vmcs_field(ctx, vcpu, VMCS_EXIT_INTR_INFO, &u64); - if (error == 0) { - printf("vmcs_exit_interruption_info[%d]\t0x%08lx\n", - vcpu, u64); - } - } - - if (!error && (get_vmcs_exit_interruption_error || get_all)) { - error = vm_get_vmcs_field(ctx, vcpu, VMCS_EXIT_INTR_ERRCODE, - &u64); - if (error == 0) { - printf("vmcs_exit_interruption_error[%d]\t0x%08lx\n", - vcpu, u64); - } - } - - if (!error && (get_vmcs_interruptibility || get_all)) { - error = vm_get_vmcs_field(ctx, vcpu, - VMCS_GUEST_INTERRUPTIBILITY, &u64); - if (error == 0) { - printf("vmcs_guest_interruptibility[%d]\t0x%08lx\n", - vcpu, u64); - } + printf("exit_reason[%d]\t%#lx\n", vcpu, u64); } if (!error && setcap) { @@ -1608,6 +2017,22 @@ main(int argc, char *argv[]) } } + if (!error && (get_stats || get_all)) { + int i, num_stats; + uint64_t *stats; + struct timeval tv; + const char *desc; + + stats = vm_get_stats(ctx, vcpu, &tv, &num_stats); + if (stats != NULL) { + printf("vcpu%d stats:\n", vcpu); + for (i = 0; i < num_stats; i++) { + desc = vm_get_stat_desc(ctx, i); + printf("%-40s\t%ld\n", desc, stats[i]); + } + } + } + if (!error && run) { error = vm_get_register(ctx, vcpu, VM_REG_GUEST_RIP, &rip); assert(error == 0); @@ -1631,5 +2056,6 @@ main(int argc, char *argv[]) if (!error && destroy) vm_destroy(ctx); + free (opts); exit(error); } |