Skip to content

Commit 72aeb60

Browse files
Liran Alonbonzini
authored andcommitted
KVM: nVMX: Verify eVMCS revision id match supported eVMCS version on eVMCS VMPTRLD
According to TLFS section 16.11.2 Enlightened VMCS, the first u32 field of eVMCS should specify eVMCS VersionNumber. This version should be in the range of supported eVMCS versions exposed to guest via CPUID.0x4000000A.EAX[0:15]. The range which KVM expose to guest in this CPUID field should be the same as the value returned in vmcs_version by nested_enable_evmcs(). According to the above, eVMCS VMPTRLD should verify that version specified in given eVMCS is in the supported range. However, current code mistakenly verfies this field against VMCS12_REVISION. One can also see that when KVM use eVMCS, it makes sure that alloc_vmcs_cpu() sets allocated eVMCS revision_id to KVM_EVMCS_VERSION. Obvious fix should just change eVMCS VMPTRLD to verify first u32 field of eVMCS is equal to KVM_EVMCS_VERSION. However, it turns out that Microsoft Hyper-V fails to comply to their own invented interface: When Hyper-V use eVMCS, it just sets first u32 field of eVMCS to revision_id specified in MSR_IA32_VMX_BASIC (In our case: VMCS12_REVISION). Instead of used eVMCS version number which is one of the supported versions specified in CPUID.0x4000000A.EAX[0:15]. To overcome Hyper-V bug, we accept either a supported eVMCS version or VMCS12_REVISION as valid values for first u32 field of eVMCS. Cc: Vitaly Kuznetsov <[email protected]> Reviewed-by: Nikita Leshenko <[email protected]> Reviewed-by: Mark Kanda <[email protected]> Signed-off-by: Liran Alon <[email protected]> Reviewed-by: Vitaly Kuznetsov <[email protected]> Signed-off-by: Paolo Bonzini <[email protected]>
1 parent 326e742 commit 72aeb60

File tree

1 file changed

+24
-1
lines changed

1 file changed

+24
-1
lines changed

arch/x86/kvm/vmx.c

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9378,7 +9378,30 @@ static int nested_vmx_handle_enlightened_vmptrld(struct kvm_vcpu *vcpu,
93789378

93799379
vmx->nested.hv_evmcs = kmap(vmx->nested.hv_evmcs_page);
93809380

9381-
if (vmx->nested.hv_evmcs->revision_id != VMCS12_REVISION) {
9381+
/*
9382+
* Currently, KVM only supports eVMCS version 1
9383+
* (== KVM_EVMCS_VERSION) and thus we expect guest to set this
9384+
* value to first u32 field of eVMCS which should specify eVMCS
9385+
* VersionNumber.
9386+
*
9387+
* Guest should be aware of supported eVMCS versions by host by
9388+
* examining CPUID.0x4000000A.EAX[0:15]. Host userspace VMM is
9389+
* expected to set this CPUID leaf according to the value
9390+
* returned in vmcs_version from nested_enable_evmcs().
9391+
*
9392+
* However, it turns out that Microsoft Hyper-V fails to comply
9393+
* to their own invented interface: When Hyper-V use eVMCS, it
9394+
* just sets first u32 field of eVMCS to revision_id specified
9395+
* in MSR_IA32_VMX_BASIC. Instead of used eVMCS version number
9396+
* which is one of the supported versions specified in
9397+
* CPUID.0x4000000A.EAX[0:15].
9398+
*
9399+
* To overcome Hyper-V bug, we accept here either a supported
9400+
* eVMCS version or VMCS12 revision_id as valid values for first
9401+
* u32 field of eVMCS.
9402+
*/
9403+
if ((vmx->nested.hv_evmcs->revision_id != KVM_EVMCS_VERSION) &&
9404+
(vmx->nested.hv_evmcs->revision_id != VMCS12_REVISION)) {
93829405
nested_release_evmcs(vcpu);
93839406
return 0;
93849407
}

0 commit comments

Comments
 (0)