Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 22 Oct 2013 00:58:51 +0000 (UTC)
From:      Neel Natu <neel@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org
Subject:   svn commit: r256869 - in stable/10: lib/libvmmapi sys/amd64/amd64 sys/amd64/include sys/amd64/vmm sys/amd64/vmm/intel usr.sbin/bhyve usr.sbin/bhyvectl
Message-ID:  <201310220058.r9M0wppf080682@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: neel
Date: Tue Oct 22 00:58:51 2013
New Revision: 256869
URL: http://svnweb.freebsd.org/changeset/base/256869

Log:
  MFC r256645.
  
  Add a new capability, VM_CAP_ENABLE_INVPCID, that can be enabled to expose
  'invpcid' instruction to the guest. Currently bhyve will try to enable this
  capability unconditionally if it is available.
  
  Consolidate code in bhyve to set the capabilities so it is no longer
  duplicated in BSP and AP bringup.
  
  Add a sysctl 'vm.pmap.invpcid_works' to display whether the 'invpcid'
  instruction is available.
  
  Approved by:	re (hrs)

Modified:
  stable/10/lib/libvmmapi/vmmapi.c
  stable/10/sys/amd64/amd64/pmap.c
  stable/10/sys/amd64/include/vmm.h   (contents, props changed)
  stable/10/sys/amd64/vmm/intel/vmx.c
  stable/10/sys/amd64/vmm/intel/vmx.h
  stable/10/sys/amd64/vmm/intel/vmx_controls.h
  stable/10/sys/amd64/vmm/x86.c
  stable/10/usr.sbin/bhyve/bhyverun.c
  stable/10/usr.sbin/bhyve/bhyverun.h
  stable/10/usr.sbin/bhyve/spinup_ap.c
  stable/10/usr.sbin/bhyvectl/bhyvectl.c
Directory Properties:
  stable/10/lib/libvmmapi/   (props changed)
  stable/10/sys/   (props changed)
  stable/10/sys/amd64/vmm/   (props changed)
  stable/10/usr.sbin/bhyve/   (props changed)
  stable/10/usr.sbin/bhyvectl/   (props changed)

Modified: stable/10/lib/libvmmapi/vmmapi.c
==============================================================================
--- stable/10/lib/libvmmapi/vmmapi.c	Tue Oct 22 00:50:53 2013	(r256868)
+++ stable/10/lib/libvmmapi/vmmapi.c	Tue Oct 22 00:58:51 2013	(r256869)
@@ -415,6 +415,7 @@ static struct {
 	{ "mtrap_exit",		VM_CAP_MTRAP_EXIT },
 	{ "pause_exit",		VM_CAP_PAUSE_EXIT },
 	{ "unrestricted_guest",	VM_CAP_UNRESTRICTED_GUEST },
+	{ "enable_invpcid",	VM_CAP_ENABLE_INVPCID },
 	{ 0 }
 };
 

Modified: stable/10/sys/amd64/amd64/pmap.c
==============================================================================
--- stable/10/sys/amd64/amd64/pmap.c	Tue Oct 22 00:50:53 2013	(r256868)
+++ stable/10/sys/amd64/amd64/pmap.c	Tue Oct 22 00:58:51 2013	(r256869)
@@ -371,6 +371,8 @@ int pmap_pcid_enabled = 1;
 SYSCTL_INT(_vm_pmap, OID_AUTO, pcid_enabled, CTLFLAG_RDTUN, &pmap_pcid_enabled,
     0, "Is TLB Context ID enabled ?");
 int invpcid_works = 0;
+SYSCTL_INT(_vm_pmap, OID_AUTO, invpcid_works, CTLFLAG_RD, &invpcid_works, 0,
+    "Is the invpcid instruction available ?");
 
 static int
 pmap_pcid_save_cnt_proc(SYSCTL_HANDLER_ARGS)

Modified: stable/10/sys/amd64/include/vmm.h
==============================================================================
--- stable/10/sys/amd64/include/vmm.h	Tue Oct 22 00:50:53 2013	(r256868)
+++ stable/10/sys/amd64/include/vmm.h	Tue Oct 22 00:58:51 2013	(r256869)
@@ -223,6 +223,7 @@ enum vm_cap_type {
 	VM_CAP_MTRAP_EXIT,
 	VM_CAP_PAUSE_EXIT,
 	VM_CAP_UNRESTRICTED_GUEST,
+	VM_CAP_ENABLE_INVPCID,
 	VM_CAP_MAX
 };
 

Modified: stable/10/sys/amd64/vmm/intel/vmx.c
==============================================================================
--- stable/10/sys/amd64/vmm/intel/vmx.c	Tue Oct 22 00:50:53 2013	(r256868)
+++ stable/10/sys/amd64/vmm/intel/vmx.c	Tue Oct 22 00:58:51 2013	(r256869)
@@ -164,6 +164,7 @@ static int cap_halt_exit;
 static int cap_pause_exit;
 static int cap_unrestricted_guest;
 static int cap_monitor_trap;
+static int cap_invpcid;
  
 static struct unrhdr *vpid_unr;
 static u_int vpid_alloc_failed;
@@ -660,6 +661,11 @@ vmx_init(void)
 					PROCBASED2_UNRESTRICTED_GUEST, 0,
 				        &tmp) == 0);
 
+	cap_invpcid = (vmx_set_ctlreg(MSR_VMX_PROCBASED_CTLS2,
+	    MSR_VMX_PROCBASED_CTLS2, PROCBASED2_ENABLE_INVPCID, 0,
+	    &tmp) == 0);
+
+
 	/* Initialize EPT */
 	error = ept_init();
 	if (error) {
@@ -828,6 +834,7 @@ vmx_vminit(struct vm *vm, pmap_t pmap)
 
 		vmx->cap[i].set = 0;
 		vmx->cap[i].proc_ctls = procbased_ctls;
+		vmx->cap[i].proc_ctls2 = procbased_ctls2;
 
 		vmx->state[i].lastcpu = -1;
 		vmx->state[i].vpid = vpid[i];
@@ -1932,6 +1939,10 @@ vmx_getcap(void *arg, int vcpu, int type
 		if (cap_unrestricted_guest)
 			ret = 0;
 		break;
+	case VM_CAP_ENABLE_INVPCID:
+		if (cap_invpcid)
+			ret = 0;
+		break;
 	default:
 		break;
 	}
@@ -1988,11 +1999,21 @@ vmx_setcap(void *arg, int vcpu, int type
 	case VM_CAP_UNRESTRICTED_GUEST:
 		if (cap_unrestricted_guest) {
 			retval = 0;
-			baseval = procbased_ctls2;
+			pptr = &vmx->cap[vcpu].proc_ctls2;
+			baseval = *pptr;
 			flag = PROCBASED2_UNRESTRICTED_GUEST;
 			reg = VMCS_SEC_PROC_BASED_CTLS;
 		}
 		break;
+	case VM_CAP_ENABLE_INVPCID:
+		if (cap_invpcid) {
+			retval = 0;
+			pptr = &vmx->cap[vcpu].proc_ctls2;
+			baseval = *pptr;
+			flag = PROCBASED2_ENABLE_INVPCID;
+			reg = VMCS_SEC_PROC_BASED_CTLS;
+		}
+		break;
 	default:
 		break;
 	}

Modified: stable/10/sys/amd64/vmm/intel/vmx.h
==============================================================================
--- stable/10/sys/amd64/vmm/intel/vmx.h	Tue Oct 22 00:50:53 2013	(r256868)
+++ stable/10/sys/amd64/vmm/intel/vmx.h	Tue Oct 22 00:58:51 2013	(r256869)
@@ -84,6 +84,7 @@ struct vmxctx {
 struct vmxcap {
 	int	set;
 	uint32_t proc_ctls;
+	uint32_t proc_ctls2;
 };
 
 struct vmxstate {

Modified: stable/10/sys/amd64/vmm/intel/vmx_controls.h
==============================================================================
--- stable/10/sys/amd64/vmm/intel/vmx_controls.h	Tue Oct 22 00:50:53 2013	(r256868)
+++ stable/10/sys/amd64/vmm/intel/vmx_controls.h	Tue Oct 22 00:58:51 2013	(r256869)
@@ -68,6 +68,7 @@
 #define	PROCBASED2_WBINVD_EXITING	(1 << 6)
 #define	PROCBASED2_UNRESTRICTED_GUEST	(1 << 7)
 #define	PROCBASED2_PAUSE_LOOP_EXITING	(1 << 10)
+#define	PROCBASED2_ENABLE_INVPCID	(1 << 12)
 
 /* VM Exit Controls */
 #define	VM_EXIT_SAVE_DEBUG_CONTROLS	(1 << 2)

Modified: stable/10/sys/amd64/vmm/x86.c
==============================================================================
--- stable/10/sys/amd64/vmm/x86.c	Tue Oct 22 00:50:53 2013	(r256868)
+++ stable/10/sys/amd64/vmm/x86.c	Tue Oct 22 00:58:51 2013	(r256869)
@@ -53,7 +53,7 @@ int
 x86_emulate_cpuid(struct vm *vm, int vcpu_id,
 		  uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
 {
-	int error;
+	int error, enable_invpcid;
 	unsigned int 	func, regs[4];
 	enum x2apic_state x2apic_state;
 
@@ -202,8 +202,22 @@ x86_emulate_cpuid(struct vm *vm, int vcp
 			regs[0] |= 0x04008000;
 			break;
 
-		case CPUID_0000_0006:
 		case CPUID_0000_0007:
+			regs[0] = 0;
+			regs[1] = 0;
+			regs[2] = 0;
+			regs[3] = 0;
+
+			/* leaf 0 */
+			if (*ecx == 0) {
+				error = vm_get_capability(vm, vcpu_id,
+				    VM_CAP_ENABLE_INVPCID, &enable_invpcid);
+				if (error == 0 && enable_invpcid)
+					regs[1] |= CPUID_STDEXT_INVPCID;
+			}
+			break;
+
+		case CPUID_0000_0006:
 		case CPUID_0000_000A:
 		case CPUID_0000_000D:
 			/*

Modified: stable/10/usr.sbin/bhyve/bhyverun.c
==============================================================================
--- stable/10/usr.sbin/bhyve/bhyverun.c	Tue Oct 22 00:50:53 2013	(r256868)
+++ stable/10/usr.sbin/bhyve/bhyverun.c	Tue Oct 22 00:58:51 2013	(r256869)
@@ -493,10 +493,54 @@ num_vcpus_allowed(struct vmctx *ctx)
 		return (1);
 }
 
+void
+fbsdrun_set_capabilities(struct vmctx *ctx, int cpu)
+{
+	int err, tmp;
+
+	if (fbsdrun_vmexit_on_hlt()) {
+		err = vm_get_capability(ctx, cpu, VM_CAP_HALT_EXIT, &tmp);
+		if (err < 0) {
+			fprintf(stderr, "VM exit on HLT not supported\n");
+			exit(1);
+		}
+		vm_set_capability(ctx, cpu, VM_CAP_HALT_EXIT, 1);
+		if (cpu == BSP)
+			handler[VM_EXITCODE_HLT] = vmexit_hlt;
+	}
+
+        if (fbsdrun_vmexit_on_pause()) {
+		/*
+		 * pause exit support required for this mode
+		 */
+		err = vm_get_capability(ctx, cpu, VM_CAP_PAUSE_EXIT, &tmp);
+		if (err < 0) {
+			fprintf(stderr,
+			    "SMP mux requested, no pause support\n");
+			exit(1);
+		}
+		vm_set_capability(ctx, cpu, VM_CAP_PAUSE_EXIT, 1);
+		if (cpu == BSP)
+			handler[VM_EXITCODE_PAUSE] = vmexit_pause;
+        }
+
+	if (fbsdrun_disable_x2apic())
+		err = vm_set_x2apic_state(ctx, cpu, X2APIC_DISABLED);
+	else
+		err = vm_set_x2apic_state(ctx, cpu, X2APIC_ENABLED);
+
+	if (err) {
+		fprintf(stderr, "Unable to set x2apic state (%d)\n", err);
+		exit(1);
+	}
+
+	vm_set_capability(ctx, cpu, VM_CAP_ENABLE_INVPCID, 1);
+}
+
 int
 main(int argc, char *argv[])
 {
-	int c, error, gdb_port, tmp, err, ioapic, bvmcons;
+	int c, error, gdb_port, err, ioapic, bvmcons;
 	int max_vcpus;
 	struct vmctx *ctx;
 	uint64_t rip;
@@ -586,39 +630,7 @@ main(int argc, char *argv[])
 		exit(1);
 	}
 
-	if (fbsdrun_vmexit_on_hlt()) {
-		err = vm_get_capability(ctx, BSP, VM_CAP_HALT_EXIT, &tmp);
-		if (err < 0) {
-			fprintf(stderr, "VM exit on HLT not supported\n");
-			exit(1);
-		}
-		vm_set_capability(ctx, BSP, VM_CAP_HALT_EXIT, 1);
-		handler[VM_EXITCODE_HLT] = vmexit_hlt;
-	}
-
-        if (fbsdrun_vmexit_on_pause()) {
-		/*
-		 * pause exit support required for this mode
-		 */
-		err = vm_get_capability(ctx, BSP, VM_CAP_PAUSE_EXIT, &tmp);
-		if (err < 0) {
-			fprintf(stderr,
-			    "SMP mux requested, no pause support\n");
-			exit(1);
-		}
-		vm_set_capability(ctx, BSP, VM_CAP_PAUSE_EXIT, 1);
-		handler[VM_EXITCODE_PAUSE] = vmexit_pause;
-        }
-
-	if (fbsdrun_disable_x2apic())
-		err = vm_set_x2apic_state(ctx, BSP, X2APIC_DISABLED);
-	else
-		err = vm_set_x2apic_state(ctx, BSP, X2APIC_ENABLED);
-
-	if (err) {
-		fprintf(stderr, "Unable to set x2apic state (%d)\n", err);
-		exit(1);
-	}
+	fbsdrun_set_capabilities(ctx, BSP);
 
 	err = vm_setup_memory(ctx, memsize, VM_MMAP_ALL);
 	if (err) {

Modified: stable/10/usr.sbin/bhyve/bhyverun.h
==============================================================================
--- stable/10/usr.sbin/bhyve/bhyverun.h	Tue Oct 22 00:50:53 2013	(r256868)
+++ stable/10/usr.sbin/bhyve/bhyverun.h	Tue Oct 22 00:58:51 2013	(r256869)
@@ -41,6 +41,7 @@ extern char *vmname;
 
 void *paddr_guest2host(struct vmctx *ctx, uintptr_t addr, size_t len);
 
+void fbsdrun_set_capabilities(struct vmctx *ctx, int cpu);
 void fbsdrun_addcpu(struct vmctx *ctx, int cpu, uint64_t rip);
 int  fbsdrun_muxed(void);
 int  fbsdrun_vmexit_on_hlt(void);

Modified: stable/10/usr.sbin/bhyve/spinup_ap.c
==============================================================================
--- stable/10/usr.sbin/bhyve/spinup_ap.c	Tue Oct 22 00:50:53 2013	(r256868)
+++ stable/10/usr.sbin/bhyve/spinup_ap.c	Tue Oct 22 00:58:51 2013	(r256869)
@@ -85,22 +85,7 @@ spinup_ap(struct vmctx *ctx, int vcpu, i
 	error = vcpu_reset(ctx, newcpu);
 	assert(error == 0);
 
-	/* Set up capabilities */
-	if (fbsdrun_vmexit_on_hlt()) {
-		error = vm_set_capability(ctx, newcpu, VM_CAP_HALT_EXIT, 1);
-		assert(error == 0);
-	}
-
-	if (fbsdrun_vmexit_on_pause()) {
-		error = vm_set_capability(ctx, newcpu, VM_CAP_PAUSE_EXIT, 1);
-		assert(error == 0);
-	}
-
-	if (fbsdrun_disable_x2apic())
-		error = vm_set_x2apic_state(ctx, newcpu, X2APIC_DISABLED);
-	else
-		error = vm_set_x2apic_state(ctx, newcpu, X2APIC_ENABLED);
-	assert(error == 0);
+	fbsdrun_set_capabilities(ctx, newcpu);
 
 	/*
 	 * Enable the 'unrestricted guest' mode for 'newcpu'.

Modified: stable/10/usr.sbin/bhyvectl/bhyvectl.c
==============================================================================
--- stable/10/usr.sbin/bhyvectl/bhyvectl.c	Tue Oct 22 00:50:53 2013	(r256868)
+++ stable/10/usr.sbin/bhyvectl/bhyvectl.c	Tue Oct 22 00:58:51 2013	(r256869)
@@ -1495,6 +1495,7 @@ main(int argc, char *argv[])
 					vm_capability_type2name(captype),
 					val ? "set" : "not set", vcpu);
 			} else if (errno == ENOENT) {
+				error = 0;
 				printf("Capability \"%s\" is not available\n",
 					vm_capability_type2name(captype));
 			} else {



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201310220058.r9M0wppf080682>