svn commit: r266765 - in head/sys/amd64/vmm: . intel

John Baldwin jhb at FreeBSD.org
Tue May 27 19:04:39 UTC 2014


Author: jhb
Date: Tue May 27 19:04:38 2014
New Revision: 266765
URL: http://svnweb.freebsd.org/changeset/base/266765

Log:
  - Rework the XSAVE/XRSTOR emulation to only expose XCR0 features to the
    guest for which the rules regarding xsetbv emulation are known.  In
    particular future extensions like AVX-512 have interdependencies among
    feature bits that could allow a guest to trigger a GP# in the host with
    the current approach of allowing anything the host supports.
  - Add proper checking of Intel MPX and AVX-512 XSAVE features in the
    xsetbv emulation and allow these features to be exposed to the guest if
    they are enabled in the host.
  - Expose a subset of known-safe features from leaf 0 of the structured
    extended features to guests if they are supported on the host including
    RDFSBASE/RDGSBASE, BMI1/2, AVX2, AVX-512, HLE, ERMS, and RTM.  Aside
    from AVX-512, these features are all new instructions available for use
    in ring 3 with no additional hypervisor changes needed.
  
  Reviewed by:	neel

Modified:
  head/sys/amd64/vmm/intel/vmx.c
  head/sys/amd64/vmm/vmm_host.c
  head/sys/amd64/vmm/x86.c

Modified: head/sys/amd64/vmm/intel/vmx.c
==============================================================================
--- head/sys/amd64/vmm/intel/vmx.c	Tue May 27 19:02:25 2014	(r266764)
+++ head/sys/amd64/vmm/intel/vmx.c	Tue May 27 19:04:38 2014	(r266765)
@@ -1380,8 +1380,30 @@ vmx_emulate_xsetbv(struct vmx *vmx, int 
 		return (HANDLED);
 	}
 
-	if ((xcrval & (XFEATURE_ENABLED_AVX | XFEATURE_ENABLED_SSE)) ==
-	    XFEATURE_ENABLED_AVX) {
+	/* AVX (YMM_Hi128) requires SSE. */
+	if (xcrval & XFEATURE_ENABLED_AVX &&
+	    (xcrval & XFEATURE_AVX) != XFEATURE_AVX) {
+		vm_inject_gp(vmx->vm, vcpu);
+		return (HANDLED);
+	}
+
+	/*
+	 * AVX512 requires base AVX (YMM_Hi128) as well as OpMask,
+	 * ZMM_Hi256, and Hi16_ZMM.
+	 */
+	if (xcrval & XFEATURE_AVX512 &&
+	    (xcrval & (XFEATURE_AVX512 | XFEATURE_AVX)) !=
+	    (XFEATURE_AVX512 | XFEATURE_AVX)) {
+		vm_inject_gp(vmx->vm, vcpu);
+		return (HANDLED);
+	}
+
+	/*
+	 * Intel MPX requires both bound register state flags to be
+	 * set.
+	 */
+	if (((xcrval & XFEATURE_ENABLED_BNDREGS) != 0) !=
+	    ((xcrval & XFEATURE_ENABLED_BNDCSR) != 0)) {
 		vm_inject_gp(vmx->vm, vcpu);
 		return (HANDLED);
 	}

Modified: head/sys/amd64/vmm/vmm_host.c
==============================================================================
--- head/sys/amd64/vmm/vmm_host.c	Tue May 27 19:02:25 2014	(r266764)
+++ head/sys/amd64/vmm/vmm_host.c	Tue May 27 19:04:38 2014	(r266765)
@@ -66,11 +66,16 @@ vmm_host_state_init(void)
 	 * XSAVE.  Only permit a guest to use XSAVE features supported
 	 * by the host.  This ensures that the FPU state used by the
 	 * guest is always a subset of the saved guest FPU state.
+	 *
+	 * In addition, only permit known XSAVE features where the
+	 * rules for which features depend on other features is known
+	 * to properly emulate xsetbv.
 	 */
 	if (vmm_host_cr4 & CR4_XSAVE) {
 		vmm_xsave_limits.xsave_enabled = 1;
 		vmm_host_xcr0 = rxcr(0);
-		vmm_xsave_limits.xcr0_allowed = vmm_host_xcr0;
+		vmm_xsave_limits.xcr0_allowed = vmm_host_xcr0 &
+		    (XFEATURE_AVX | XFEATURE_MPX | XFEATURE_AVX512);
 
 		cpuid_count(0xd, 0x0, regs);
 		vmm_xsave_limits.xsave_max_size = regs[1];

Modified: head/sys/amd64/vmm/x86.c
==============================================================================
--- head/sys/amd64/vmm/x86.c	Tue May 27 19:02:25 2014	(r266764)
+++ head/sys/amd64/vmm/x86.c	Tue May 27 19:04:38 2014	(r266765)
@@ -241,6 +241,26 @@ x86_emulate_cpuid(struct vm *vm, int vcp
 
 			/* leaf 0 */
 			if (*ecx == 0) {
+				cpuid_count(*eax, *ecx, regs);
+
+				/* Only leaf 0 is supported */
+				regs[0] = 0;
+
+				/*
+				 * Expose known-safe features.
+				 */
+				regs[1] &= (CPUID_STDEXT_FSGSBASE |
+				    CPUID_STDEXT_BMI1 | CPUID_STDEXT_HLE |
+				    CPUID_STDEXT_AVX2 | CPUID_STDEXT_BMI2 |
+				    CPUID_STDEXT_ERMS | CPUID_STDEXT_RTM |
+				    CPUID_STDEXT_AVX512F |
+				    CPUID_STDEXT_AVX512PF |
+				    CPUID_STDEXT_AVX512ER |
+				    CPUID_STDEXT_AVX512CD);
+				regs[2] = 0;
+				regs[3] = 0;
+
+				/* Advertise INVPCID if it is enabled. */
 				error = vm_get_capability(vm, vcpu_id,
 				    VM_CAP_ENABLE_INVPCID, &enable_invpcid);
 				if (error == 0 && enable_invpcid)


More information about the svn-src-head mailing list