svn commit: r272916 - in projects/bhyve_svm: sys/amd64/vmm/amd usr.sbin/bhyvectl

Neel Natu neel at FreeBSD.org
Fri Oct 10 21:49:00 UTC 2014


Author: neel
Date: Fri Oct 10 21:48:59 2014
New Revision: 272916
URL: https://svnweb.freebsd.org/changeset/base/272916

Log:
  Fix bhyvectl so it works correctly on AMD/SVM hosts. Also, add command line
  options to display some key VMCB fields.
  
  The set of valid options that can be passed to bhyvectl now depends on the
  processor type. AMD-specific options are identified by a "--vmcb" or "--avic"
  in the option name. Intel-specific options are identified by a "--vmcs" in
  the option name.
  
  Submitted by:	Anish Gupta (akgupt3 at gmail.com)

Modified:
  projects/bhyve_svm/sys/amd64/vmm/amd/vmcb.c
  projects/bhyve_svm/sys/amd64/vmm/amd/vmcb.h
  projects/bhyve_svm/usr.sbin/bhyvectl/bhyvectl.c

Modified: projects/bhyve_svm/sys/amd64/vmm/amd/vmcb.c
==============================================================================
--- projects/bhyve_svm/sys/amd64/vmm/amd/vmcb.c	Fri Oct 10 21:22:25 2014	(r272915)
+++ projects/bhyve_svm/sys/amd64/vmm/amd/vmcb.c	Fri Oct 10 21:48:59 2014	(r272916)
@@ -111,6 +111,48 @@ vmcb_segptr(struct vmcb *vmcb, int type)
 	return (seg);
 }
 
+static int
+vmcb_access(struct svm_softc *softc, int vcpu, int write, int ident,
+	uint64_t *val)
+{
+	struct vmcb *vmcb;
+	int off, bytes;
+	char *ptr;
+
+	vmcb	= svm_get_vmcb(softc, vcpu);
+	off	= VMCB_ACCESS_OFFSET(ident);
+	bytes	= VMCB_ACCESS_BYTES(ident);
+
+	if ((off + bytes) >= sizeof (struct vmcb))
+		return (EINVAL);
+
+	ptr = (char *)vmcb;
+
+	if (!write)
+		*val = 0;
+
+	switch (bytes) {
+	case 8:
+	case 4:
+	case 2:
+		if (write)
+			memcpy(ptr + off, val, bytes);
+		else
+			memcpy(val, ptr + off, bytes);
+		break;
+	default:
+		VCPU_CTR1(softc->vm, vcpu,
+		    "Invalid size %d for VMCB access: %d", bytes);
+		return (EINVAL);
+	}
+
+	/* Invalidate all VMCB state cached by h/w. */
+	if (write)
+		svm_set_dirty(softc, vcpu, 0xffffffff);
+
+	return (0);
+}
+
 /*
  * Read from segment selector, control and general purpose register of VMCB.
  */
@@ -126,6 +168,9 @@ vmcb_read(struct svm_softc *sc, int vcpu
 	state = &vmcb->state;
 	err = 0;
 
+	if (VMCB_ACCESS_OK(ident))
+		return (vmcb_access(sc, vcpu, 0, ident, retval));
+
 	switch (ident) {
 	case VM_REG_GUEST_CR0:
 		*retval = state->cr0;
@@ -210,6 +255,9 @@ vmcb_write(struct svm_softc *sc, int vcp
 	dirtyseg = 0;
 	err = 0;
 
+	if (VMCB_ACCESS_OK(ident))
+		return (vmcb_access(sc, vcpu, 1, ident, &val));
+
 	switch (ident) {
 	case VM_REG_GUEST_CR0:
 		state->cr0 = val;

Modified: projects/bhyve_svm/sys/amd64/vmm/amd/vmcb.h
==============================================================================
--- projects/bhyve_svm/sys/amd64/vmm/amd/vmcb.h	Fri Oct 10 21:22:25 2014	(r272915)
+++ projects/bhyve_svm/sys/amd64/vmm/amd/vmcb.h	Fri Oct 10 21:48:59 2014	(r272916)
@@ -164,6 +164,45 @@ struct svm_softc;
 #define VMCB_EXITINTINFO_VALID(x)	(((x) & BIT(31)) ? 1 : 0)
 #define VMCB_EXITINTINFO_EC(x)		(((x) >> 32) & 0xFFFFFFFF)
 
+/* Offset of various VMCB fields. */
+#define	VMCB_OFF_CTRL(x)		(x)
+#define	VMCB_OFF_STATE(x)		((x) + 0x400)
+
+#define	VMCB_OFF_CR_INTERCEPT		VMCB_OFF_CTRL(0x0)
+#define	VMCB_OFF_DR_INTERCEPT		VMCB_OFF_CTRL(0x4)
+#define	VMCB_OFF_EXC_INTERCEPT		VMCB_OFF_CTRL(0x8)
+#define	VMCB_OFF_INST1_INTERCEPT	VMCB_OFF_CTRL(0xC)
+#define	VMCB_OFF_INST2_INTERCEPT	VMCB_OFF_CTRL(0x10)
+#define	VMCB_OFF_IO_PERM		VMCB_OFF_CTRL(0x40)
+#define	VMCB_OFF_MSR_PERM		VMCB_OFF_CTRL(0x48)
+#define	VMCB_OFF_TSC_OFFSET		VMCB_OFF_CTRL(0x50)
+#define	VMCB_OFF_ASID			VMCB_OFF_CTRL(0x58)
+#define	VMCB_OFF_TLB_CTRL		VMCB_OFF_CTRL(0x5C)
+#define	VMCB_OFF_VIRQ			VMCB_OFF_CTRL(0x60)
+#define	VMCB_OFF_EXIT_REASON		VMCB_OFF_CTRL(0x70)
+#define	VMCB_OFF_EXITINFO1		VMCB_OFF_CTRL(0x78)
+#define	VMCB_OFF_EXITINFO2		VMCB_OFF_CTRL(0x80)
+#define	VMCB_OFF_EXITINTINFO		VMCB_OFF_CTRL(0x88)
+#define	VMCB_OFF_AVIC_BAR		VMCB_OFF_CTRL(0x98)
+#define	VMCB_OFF_NPT_BASE		VMCB_OFF_CTRL(0xB0)
+#define	VMCB_OFF_AVIC_PAGE		VMCB_OFF_CTRL(0xE0)
+#define	VMCB_OFF_AVIC_LT		VMCB_OFF_CTRL(0xF0)
+#define	VMCB_OFF_AVIC_PT		VMCB_OFF_CTRL(0xF8)
+#define	VMCB_OFF_SYSENTER_CS		VMCB_OFF_STATE(0x228)
+#define	VMCB_OFF_SYSENTER_ESP		VMCB_OFF_STATE(0x230)
+#define	VMCB_OFF_SYSENTER_EIP		VMCB_OFF_STATE(0x238)
+#define	VMCB_OFF_GUEST_PAT		VMCB_OFF_STATE(0x268)
+
+/*
+ * Encode the VMCB offset and bytes that we want to read from VMCB.
+ */
+#define	VMCB_ACCESS(o, w)		(0x80000000 | (((w) & 0xF) << 16) | \
+					((o) & 0xFFF))
+#define	VMCB_ACCESS_OK(v)               ((v) & 0x80000000 )
+#define	VMCB_ACCESS_BYTES(v)            (((v) >> 16) & 0xF)
+#define	VMCB_ACCESS_OFFSET(v)           ((v) & 0xFFF)
+
+#ifdef _KERNEL
 /* VMCB save state area segment format */
 struct vmcb_segment {
 	uint16_t	selector;
@@ -287,4 +326,5 @@ int	vmcb_setdesc(void *arg, int vcpu, in
 int	vmcb_getdesc(void *arg, int vcpu, int ident, struct seg_desc *desc);
 int	vmcb_seg(struct vmcb *vmcb, int ident, struct vmcb_segment *seg);
 
+#endif /* _KERNEL */
 #endif /* _VMCB_H_ */

Modified: projects/bhyve_svm/usr.sbin/bhyvectl/bhyvectl.c
==============================================================================
--- projects/bhyve_svm/usr.sbin/bhyvectl/bhyvectl.c	Fri Oct 10 21:22:25 2014	(r272915)
+++ projects/bhyve_svm/usr.sbin/bhyvectl/bhyvectl.c	Fri Oct 10 21:48:59 2014	(r272916)
@@ -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, f
 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 *vme
 		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];
 
-	error = -1;
-	bitmap = MAP_FAILED;
+	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);
 
-	fd = open("/dev/mem", O_RDONLY, 0);
-	if (fd < 0)
-		goto done;
+	return (buf);
+}
 
-	bitmap = mmap(NULL, PAGE_SIZE, PROT_READ, MAP_SHARED, fd, addr);
-	if (bitmap == MAP_FAILED)
-		goto done;
+static inline void
+print_msr_pm(uint64_t msr, int vcpu, int readable, int writeable)
+{
+
+	if (readable || writeable) {
+		printf("%-20s[%d]\t\t%c%c\n", msr_name(msr), vcpu,
+			readable ? 'R' : '-', writeable ? 'W' : '-');
+	}
+}
+
+/*
+ * 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 ad
 
 		/* 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
 	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,648 +597,190 @@ print_intinfo(const char *banner, uint64
 	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;
-	uint64_t cs, ds, es, fs, gs, ss, tr, ldtr;
+	int error;
 
-	struct option opts[] = {
-		{ "vm",		REQ_ARG,	0,	VMNAME },
-		{ "cpu",	REQ_ARG,	0,	VCPU },
-		{ "set-mem",	REQ_ARG,	0,	SET_MEM },
-		{ "set-efer",	REQ_ARG,	0,	SET_EFER },
-		{ "set-cr0",	REQ_ARG,	0,	SET_CR0 },
-		{ "set-cr3",	REQ_ARG,	0,	SET_CR3 },
-		{ "set-cr4",	REQ_ARG,	0,	SET_CR4 },
-		{ "set-dr7",	REQ_ARG,	0,	SET_DR7 },
-		{ "set-rsp",	REQ_ARG,	0,	SET_RSP },
-		{ "set-rip",	REQ_ARG,	0,	SET_RIP },
-		{ "set-rax",	REQ_ARG,	0,	SET_RAX },
-		{ "set-rflags",	REQ_ARG,	0,	SET_RFLAGS },
-		{ "desc-base",	REQ_ARG,	0,	DESC_BASE },
-		{ "desc-limit",	REQ_ARG,	0,	DESC_LIMIT },
-		{ "desc-access",REQ_ARG,	0,	DESC_ACCESS },
-		{ "set-cs",	REQ_ARG,	0,	SET_CS },
-		{ "set-ds",	REQ_ARG,	0,	SET_DS },
-		{ "set-es",	REQ_ARG,	0,	SET_ES },
-		{ "set-fs",	REQ_ARG,	0,	SET_FS },
-		{ "set-gs",	REQ_ARG,	0,	SET_GS },
-		{ "set-ss",	REQ_ARG,	0,	SET_SS },
-		{ "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 },
-		{ "capname",	REQ_ARG,	0,	CAPNAME },
-		{ "unassign-pptdev", REQ_ARG,	0,	UNASSIGN_PPTDEV },
-		{ "setcap",	REQ_ARG,	0,	SET_CAP },
-		{ "get-gpa-pmap", REQ_ARG,	0,	GET_GPA_PMAP },
-		{ "assert-lapic-lvt", REQ_ARG,	0,	ASSERT_LAPIC_LVT },
-		{ "getcap",	NO_ARG,		&getcap,	1 },
-		{ "get-stats",	NO_ARG,		&get_stats,	1 },
-		{ "get-desc-ds",NO_ARG,		&get_desc_ds,	1 },
-		{ "set-desc-ds",NO_ARG,		&set_desc_ds,	1 },
-		{ "get-desc-es",NO_ARG,		&get_desc_es,	1 },
-		{ "set-desc-es",NO_ARG,		&set_desc_es,	1 },
-		{ "get-desc-ss",NO_ARG,		&get_desc_ss,	1 },
-		{ "set-desc-ss",NO_ARG,		&set_desc_ss,	1 },
-		{ "get-desc-cs",NO_ARG,		&get_desc_cs,	1 },
-		{ "set-desc-cs",NO_ARG,		&set_desc_cs,	1 },
-		{ "get-desc-fs",NO_ARG,		&get_desc_fs,	1 },
-		{ "set-desc-fs",NO_ARG,		&set_desc_fs,	1 },
-		{ "get-desc-gs",NO_ARG,		&get_desc_gs,	1 },
-		{ "set-desc-gs",NO_ARG,		&set_desc_gs,	1 },
-		{ "get-desc-tr",NO_ARG,		&get_desc_tr,	1 },
-		{ "set-desc-tr",NO_ARG,		&set_desc_tr,	1 },
-		{ "set-desc-ldtr", NO_ARG,	&set_desc_ldtr,	1 },
-		{ "get-desc-ldtr", NO_ARG,	&get_desc_ldtr,	1 },
-		{ "set-desc-gdtr", NO_ARG,	&set_desc_gdtr, 1 },
-		{ "get-desc-gdtr", NO_ARG,	&get_desc_gdtr, 1 },
-		{ "set-desc-idtr", NO_ARG,	&set_desc_idtr, 1 },
-		{ "get-desc-idtr", NO_ARG,	&get_desc_idtr, 1 },
-		{ "get-lowmem", NO_ARG,		&get_lowmem,	1 },
-		{ "get-highmem",NO_ARG,		&get_highmem,	1 },
-		{ "get-efer",	NO_ARG,		&get_efer,	1 },
-		{ "get-cr0",	NO_ARG,		&get_cr0,	1 },
-		{ "get-cr3",	NO_ARG,		&get_cr3,	1 },
-		{ "get-cr4",	NO_ARG,		&get_cr4,	1 },
-		{ "get-dr7",	NO_ARG,		&get_dr7,	1 },
-		{ "get-rsp",	NO_ARG,		&get_rsp,	1 },
-		{ "get-rip",	NO_ARG,		&get_rip,	1 },
-		{ "get-rax",	NO_ARG,		&get_rax,	1 },
-		{ "get-rbx",	NO_ARG,		&get_rbx,	1 },
-		{ "get-rcx",	NO_ARG,		&get_rcx,	1 },
-		{ "get-rdx",	NO_ARG,		&get_rdx,	1 },
-		{ "get-rsi",	NO_ARG,		&get_rsi,	1 },
-		{ "get-rdi",	NO_ARG,		&get_rdi,	1 },
-		{ "get-rbp",	NO_ARG,		&get_rbp,	1 },
-		{ "get-r8",	NO_ARG,		&get_r8,	1 },
-		{ "get-r9",	NO_ARG,		&get_r9,	1 },
-		{ "get-r10",	NO_ARG,		&get_r10,	1 },
-		{ "get-r11",	NO_ARG,		&get_r11,	1 },
-		{ "get-r12",	NO_ARG,		&get_r12,	1 },
-		{ "get-r13",	NO_ARG,		&get_r13,	1 },
-		{ "get-r14",	NO_ARG,		&get_r14,	1 },
-		{ "get-r15",	NO_ARG,		&get_r15,	1 },
-		{ "get-rflags",	NO_ARG,		&get_rflags,	1 },
-		{ "get-cs",	NO_ARG,		&get_cs,	1 },
-		{ "get-ds",	NO_ARG,		&get_ds,	1 },
-		{ "get-es",	NO_ARG,		&get_es,	1 },
-		{ "get-fs",	NO_ARG,		&get_fs,	1 },
-		{ "get-gs",	NO_ARG,		&get_gs,	1 },
-		{ "get-ss",	NO_ARG,		&get_ss,	1 },
-		{ "get-tr",	NO_ARG,		&get_tr,	1 },
-		{ "get-ldtr",	NO_ARG,		&get_ldtr,	1 },
-		{ "get-vmcs-pinbased-ctls",
-				NO_ARG,		&get_pinbased_ctls, 1 },
-		{ "get-vmcs-procbased-ctls",
-				NO_ARG,		&get_procbased_ctls, 1 },
-		{ "get-vmcs-procbased-ctls2",
-				NO_ARG,		&get_procbased_ctls2, 1 },
-		{ "get-vmcs-guest-linear-address",
-				NO_ARG,		&get_vmcs_gla,	1 },
-		{ "get-vmcs-guest-physical-address",
-				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-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 },
-		{ "get-vmcs-entry-ctls",
-					NO_ARG,	&get_entry_ctls, 1 },
-		{ "get-vmcs-guest-pat",	NO_ARG,	&get_guest_pat,	1 },
-		{ "get-vmcs-host-pat",	NO_ARG,	&get_host_pat,	1 },
-		{ "get-vmcs-host-cr0",
-				NO_ARG,		&get_host_cr0,	1 },
-		{ "get-vmcs-host-cr3",
-				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 }
-	};
+	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);
+	}
 
-	vcpu = 0;
-	vmname = NULL;
-	assert_lapic_lvt = -1;
-	progname = basename(argv[0]);
+	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);
+	}
 
-	while ((ch = getopt_long(argc, argv, "", opts, NULL)) != -1) {
-		switch (ch) {
-		case 0:
-			break;
-		case VMNAME:
-			vmname = optarg;
-			break;
-		case VCPU:
-			vcpu = atoi(optarg);
-			break;
-		case SET_MEM:
-			memsize = atoi(optarg) * MB;
-			memsize = roundup(memsize, 2 * MB);
-			break;
-		case SET_EFER:
-			efer = strtoul(optarg, NULL, 0);
-			set_efer = 1;
-			break;
-		case SET_CR0:
-			cr0 = strtoul(optarg, NULL, 0);
-			set_cr0 = 1;
-			break;
-		case SET_CR3:
-			cr3 = strtoul(optarg, NULL, 0);
-			set_cr3 = 1;
-			break;
-		case SET_CR4:
-			cr4 = strtoul(optarg, NULL, 0);
-			set_cr4 = 1;
-			break;
-		case SET_DR7:
-			dr7 = strtoul(optarg, NULL, 0);
-			set_dr7 = 1;
-			break;
-		case SET_RSP:
-			rsp = strtoul(optarg, NULL, 0);
-			set_rsp = 1;
-			break;
-		case SET_RIP:
-			rip = strtoul(optarg, NULL, 0);
-			set_rip = 1;
-			break;
-		case SET_RAX:
-			rax = strtoul(optarg, NULL, 0);
-			set_rax = 1;
-			break;
-		case SET_RFLAGS:
-			rflags = strtoul(optarg, NULL, 0);
-			set_rflags = 1;
-			break;
-		case DESC_BASE:
-			desc_base = strtoul(optarg, NULL, 0);
-			break;
-		case DESC_LIMIT:
-			desc_limit = strtoul(optarg, NULL, 0);
-			break;
-		case DESC_ACCESS:
-			desc_access = strtoul(optarg, NULL, 0);
-			break;
-		case SET_CS:
-			cs = strtoul(optarg, NULL, 0);
-			set_cs = 1;
-			break;
-		case SET_DS:
-			ds = strtoul(optarg, NULL, 0);
-			set_ds = 1;
-			break;
-		case SET_ES:
-			es = strtoul(optarg, NULL, 0);
-			set_es = 1;
-			break;
-		case SET_FS:
-			fs = strtoul(optarg, NULL, 0);
-			set_fs = 1;
-			break;
-		case SET_GS:
-			gs = strtoul(optarg, NULL, 0);
-			set_gs = 1;
-			break;
-		case SET_SS:
-			ss = strtoul(optarg, NULL, 0);
-			set_ss = 1;
-			break;
-		case SET_TR:
-			tr = strtoul(optarg, NULL, 0);
-			set_tr = 1;
-			break;
-		case SET_LDTR:
-			ldtr = strtoul(optarg, NULL, 0);
-			set_ldtr = 1;
-			break;
-		case SET_X2APIC_STATE:
-			x2apic_state = strtol(optarg, NULL, 0);
-			set_x2apic_state = 1;
-			break;
-		case SET_VMCS_EXCEPTION_BITMAP:
-			exception_bitmap = strtoul(optarg, NULL, 0);
-			set_exception_bitmap = 1;
-			break;
-		case SET_VMCS_ENTRY_INTERRUPTION_INFO:
-			vmcs_entry_interruption_info = strtoul(optarg, NULL, 0);
-			set_vmcs_entry_interruption_info = 1;
-			break;
-		case SET_CAP:
-			capval = strtoul(optarg, NULL, 0);
-			setcap = 1;
-			break;
-		case GET_GPA_PMAP:
-			gpa_pmap = strtoul(optarg, NULL, 0);
-			get_gpa_pmap = 1;
-			break;
-		case CAPNAME:
-			capname = optarg;
-			break;
-		case UNASSIGN_PPTDEV:
-			unassign_pptdev = 1;
-			if (sscanf(optarg, "%d/%d/%d", &bus, &slot, &func) != 3)
-				usage();
-			break;
-		case ASSERT_LAPIC_LVT:
-			assert_lapic_lvt = atoi(optarg);
-			break;
-		default:
-			usage();
-		}
+	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);
 	}
-	argc -= optind;
-	argv += optind;
-
-	if (vmname == NULL)
-		usage();
 
-	error = 0;
-
-	if (!error && create)
-		error = vm_create(vmname);
-
-	if (!error) {
-		ctx = vm_open(vmname);
-		if (ctx == NULL)
-			error = -1;
+	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 && memsize)
-		error = vm_setup_memory(ctx, memsize, VM_MMAP_NONE);
-
-	if (!error && set_efer)
-		error = vm_set_register(ctx, vcpu, VM_REG_GUEST_EFER, efer);
-
-	if (!error && set_cr0)
-		error = vm_set_register(ctx, vcpu, VM_REG_GUEST_CR0, cr0);
+	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 && set_cr3)
-		error = vm_set_register(ctx, vcpu, VM_REG_GUEST_CR3, cr3);
+	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 && set_cr4)
-		error = vm_set_register(ctx, vcpu, VM_REG_GUEST_CR4, cr4);
+	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 && set_dr7)
-		error = vm_set_register(ctx, vcpu, VM_REG_GUEST_DR7, dr7);
+	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 && set_rsp)
-		error = vm_set_register(ctx, vcpu, VM_REG_GUEST_RSP, rsp);
+	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 && set_rip)
-		error = vm_set_register(ctx, vcpu, VM_REG_GUEST_RIP, rip);
+	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 && set_rax)
-		error = vm_set_register(ctx, vcpu, VM_REG_GUEST_RAX, rax);
+	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 && set_rflags) {
-		error = vm_set_register(ctx, vcpu, VM_REG_GUEST_RFLAGS,
-					rflags);
+	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 && set_desc_ds) {
-		error = vm_set_desc(ctx, vcpu, VM_REG_GUEST_DS,
-				    desc_base, desc_limit, desc_access);
+	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 && set_desc_es) {
-		error = vm_set_desc(ctx, vcpu, VM_REG_GUEST_ES,
-				    desc_base, desc_limit, desc_access);
+	if (!error && (get_rbp || get_all)) {

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-src-projects mailing list