Date: Tue, 27 May 2014 19:04:38 +0000 (UTC) From: John Baldwin <jhb@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r266765 - in head/sys/amd64/vmm: . intel Message-ID: <201405271904.s4RJ4cx4068774@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
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)
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201405271904.s4RJ4cx4068774>