KVM: nVMX: Use correct VPID02 when emulating L1 INVVPID
authorLiran Alon <liran.alon@oracle.com>
Mon, 8 Oct 2018 20:42:18 +0000 (23:42 +0300)
committerPaolo Bonzini <pbonzini@redhat.com>
Sat, 13 Oct 2018 10:00:54 +0000 (12:00 +0200)
In case L0 didn't allocate vmx->nested.vpid02 for L2,
vmcs02->vpid is set to vmx->vpid.
Consider this case when emulating L1 INVVPID in L0.

Reviewed-by: Nikita Leshenko <nikita.leshchenko@oracle.com>
Reviewed-by: Mark Kanda <mark.kanda@oracle.com>
Signed-off-by: Liran Alon <liran.alon@oracle.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
arch/x86/kvm/vmx.c

index a4fa15b8b1aed537b2668053118ff2882f243c36..12d39e2561bef09a33b1cd7c48a76985d25d42fa 100644 (file)
@@ -9003,6 +9003,13 @@ static int handle_invept(struct kvm_vcpu *vcpu)
        return kvm_skip_emulated_instruction(vcpu);
 }
 
+static u16 nested_get_vpid02(struct kvm_vcpu *vcpu)
+{
+       struct vcpu_vmx *vmx = to_vmx(vcpu);
+
+       return vmx->nested.vpid02 ? vmx->nested.vpid02 : vmx->vpid;
+}
+
 static int handle_invvpid(struct kvm_vcpu *vcpu)
 {
        struct vcpu_vmx *vmx = to_vmx(vcpu);
@@ -9014,6 +9021,7 @@ static int handle_invvpid(struct kvm_vcpu *vcpu)
                u64 vpid;
                u64 gla;
        } operand;
+       u16 vpid02;
 
        if (!(vmx->nested.msrs.secondary_ctls_high &
              SECONDARY_EXEC_ENABLE_VPID) ||
@@ -9053,6 +9061,7 @@ static int handle_invvpid(struct kvm_vcpu *vcpu)
                return kvm_skip_emulated_instruction(vcpu);
        }
 
+       vpid02 = nested_get_vpid02(vcpu);
        switch (type) {
        case VMX_VPID_EXTENT_INDIVIDUAL_ADDR:
                if (!operand.vpid ||
@@ -9061,12 +9070,11 @@ static int handle_invvpid(struct kvm_vcpu *vcpu)
                                VMXERR_INVALID_OPERAND_TO_INVEPT_INVVPID);
                        return kvm_skip_emulated_instruction(vcpu);
                }
-               if (cpu_has_vmx_invvpid_individual_addr() &&
-                   vmx->nested.vpid02) {
+               if (cpu_has_vmx_invvpid_individual_addr()) {
                        __invvpid(VMX_VPID_EXTENT_INDIVIDUAL_ADDR,
-                               vmx->nested.vpid02, operand.gla);
+                               vpid02, operand.gla);
                } else
-                       __vmx_flush_tlb(vcpu, vmx->nested.vpid02, true);
+                       __vmx_flush_tlb(vcpu, vpid02, true);
                break;
        case VMX_VPID_EXTENT_SINGLE_CONTEXT:
        case VMX_VPID_EXTENT_SINGLE_NON_GLOBAL:
@@ -9075,10 +9083,10 @@ static int handle_invvpid(struct kvm_vcpu *vcpu)
                                VMXERR_INVALID_OPERAND_TO_INVEPT_INVVPID);
                        return kvm_skip_emulated_instruction(vcpu);
                }
-               __vmx_flush_tlb(vcpu, vmx->nested.vpid02, true);
+               __vmx_flush_tlb(vcpu, vpid02, true);
                break;
        case VMX_VPID_EXTENT_ALL_CONTEXT:
-               __vmx_flush_tlb(vcpu, vmx->nested.vpid02, true);
+               __vmx_flush_tlb(vcpu, vpid02, true);
                break;
        default:
                WARN_ON_ONCE(1);