KVM: nVMX: Don't speculatively write virtual-APIC page address
authorSean Christopherson <sean.j.christopherson@intel.com>
Tue, 7 May 2019 16:06:33 +0000 (09:06 -0700)
committerPaolo Bonzini <pbonzini@redhat.com>
Tue, 18 Jun 2019 09:47:35 +0000 (11:47 +0200)
The VIRTUAL_APIC_PAGE_ADDR in vmcs02 is guaranteed to be updated before
it is consumed by hardware, either in nested_vmx_enter_non_root_mode()
or via the KVM_REQ_GET_VMCS12_PAGES callback.  Avoid an extra VMWRITE
and only stuff a bad value into vmcs02 when mapping vmcs12's address
fails.  This also eliminates the need for extra comments to connect the
dots between prepare_vmcs02_early() and nested_get_vmcs12_pages().

Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
arch/x86/kvm/vmx/nested.c

index 4ba0e7b..ded0247 100644 (file)
@@ -2039,20 +2039,13 @@ static void prepare_vmcs02_early(struct vcpu_vmx *vmx, struct vmcs12 *vmcs12)
        exec_control &= ~CPU_BASED_TPR_SHADOW;
        exec_control |= vmcs12->cpu_based_vm_exec_control;
 
-       /*
-        * Write an illegal value to VIRTUAL_APIC_PAGE_ADDR. Later, if
-        * nested_get_vmcs12_pages can't fix it up, the illegal value
-        * will result in a VM entry failure.
-        */
-       if (exec_control & CPU_BASED_TPR_SHADOW) {
-               vmcs_write64(VIRTUAL_APIC_PAGE_ADDR, -1ull);
+       if (exec_control & CPU_BASED_TPR_SHADOW)
                vmcs_write32(TPR_THRESHOLD, vmcs12->tpr_threshold);
-       } else {
 #ifdef CONFIG_X86_64
+       else
                exec_control |= CPU_BASED_CR8_LOAD_EXITING |
                                CPU_BASED_CR8_STORE_EXITING;
 #endif
-       }
 
        /*
         * A vmexit (to either L1 hypervisor or L0 userspace) is always needed
@@ -2861,10 +2854,6 @@ static void nested_get_vmcs12_pages(struct kvm_vcpu *vcpu)
        if (nested_cpu_has(vmcs12, CPU_BASED_TPR_SHADOW)) {
                map = &vmx->nested.virtual_apic_map;
 
-               /*
-                * If translation failed, VM entry will fail because
-                * prepare_vmcs02 set VIRTUAL_APIC_PAGE_ADDR to -1ull.
-                */
                if (!kvm_vcpu_map(vcpu, gpa_to_gfn(vmcs12->virtual_apic_page_addr), map)) {
                        vmcs_write64(VIRTUAL_APIC_PAGE_ADDR, pfn_to_hpa(map->pfn));
                } else if (nested_cpu_has(vmcs12, CPU_BASED_CR8_LOAD_EXITING) &&
@@ -2880,6 +2869,12 @@ static void nested_get_vmcs12_pages(struct kvm_vcpu *vcpu)
                         */
                        vmcs_clear_bits(CPU_BASED_VM_EXEC_CONTROL,
                                        CPU_BASED_TPR_SHADOW);
+               } else {
+                       /*
+                        * Write an illegal value to VIRTUAL_APIC_PAGE_ADDR to
+                        * force VM-Entry to fail.
+                        */
+                       vmcs_write64(VIRTUAL_APIC_PAGE_ADDR, -1ull);
                }
        }