aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJim Mattson <jmattson@google.com>2017-03-16 16:53:59 -0400
committerPaolo Bonzini <pbonzini@redhat.com>2017-03-23 14:02:06 -0400
commitfb6c8198431311027c3434d4e94ab8bc040f7aea (patch)
tree24158162ec309947b0452170b391aff74ff0a12d
parentc761159cf81b8641290f7559a8d8e30f6ab92669 (diff)
kvm: vmx: Flush TLB when the APIC-access address changes
Quoting from the Intel SDM, volume 3, section 28.3.3.4: Guidelines for Use of the INVEPT Instruction: If EPT was in use on a logical processor at one time with EPTP X, it is recommended that software use the INVEPT instruction with the "single-context" INVEPT type and with EPTP X in the INVEPT descriptor before a VM entry on the same logical processor that enables EPT with EPTP X and either (a) the "virtualize APIC accesses" VM-execution control was changed from 0 to 1; or (b) the value of the APIC-access address was changed. In the nested case, the burden falls on L1, unless L0 enables EPT in vmcs02 when L1 doesn't enable EPT in vmcs12. Signed-off-by: Jim Mattson <jmattson@google.com> Signed-off-by: Radim Krčmář <rkrcmar@redhat.com>
-rw-r--r--arch/x86/kvm/vmx.c18
1 files changed, 17 insertions, 1 deletions
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index c66436530a93..e2f608283a5a 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -4024,6 +4024,12 @@ static void vmx_flush_tlb(struct kvm_vcpu *vcpu)
4024 __vmx_flush_tlb(vcpu, to_vmx(vcpu)->vpid); 4024 __vmx_flush_tlb(vcpu, to_vmx(vcpu)->vpid);
4025} 4025}
4026 4026
4027static void vmx_flush_tlb_ept_only(struct kvm_vcpu *vcpu)
4028{
4029 if (enable_ept)
4030 vmx_flush_tlb(vcpu);
4031}
4032
4027static void vmx_decache_cr0_guest_bits(struct kvm_vcpu *vcpu) 4033static void vmx_decache_cr0_guest_bits(struct kvm_vcpu *vcpu)
4028{ 4034{
4029 ulong cr0_guest_owned_bits = vcpu->arch.cr0_guest_owned_bits; 4035 ulong cr0_guest_owned_bits = vcpu->arch.cr0_guest_owned_bits;
@@ -8548,6 +8554,7 @@ static void vmx_set_virtual_x2apic_mode(struct kvm_vcpu *vcpu, bool set)
8548 } else { 8554 } else {
8549 sec_exec_control &= ~SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE; 8555 sec_exec_control &= ~SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE;
8550 sec_exec_control |= SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES; 8556 sec_exec_control |= SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES;
8557 vmx_flush_tlb_ept_only(vcpu);
8551 } 8558 }
8552 vmcs_write32(SECONDARY_VM_EXEC_CONTROL, sec_exec_control); 8559 vmcs_write32(SECONDARY_VM_EXEC_CONTROL, sec_exec_control);
8553 8560
@@ -8573,8 +8580,10 @@ static void vmx_set_apic_access_page_addr(struct kvm_vcpu *vcpu, hpa_t hpa)
8573 */ 8580 */
8574 if (!is_guest_mode(vcpu) || 8581 if (!is_guest_mode(vcpu) ||
8575 !nested_cpu_has2(get_vmcs12(&vmx->vcpu), 8582 !nested_cpu_has2(get_vmcs12(&vmx->vcpu),
8576 SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES)) 8583 SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES)) {
8577 vmcs_write64(APIC_ACCESS_ADDR, hpa); 8584 vmcs_write64(APIC_ACCESS_ADDR, hpa);
8585 vmx_flush_tlb_ept_only(vcpu);
8586 }
8578} 8587}
8579 8588
8580static void vmx_hwapic_isr_update(struct kvm_vcpu *vcpu, int max_isr) 8589static void vmx_hwapic_isr_update(struct kvm_vcpu *vcpu, int max_isr)
@@ -10256,6 +10265,9 @@ static int prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12,
10256 if (nested_cpu_has_ept(vmcs12)) { 10265 if (nested_cpu_has_ept(vmcs12)) {
10257 kvm_mmu_unload(vcpu); 10266 kvm_mmu_unload(vcpu);
10258 nested_ept_init_mmu_context(vcpu); 10267 nested_ept_init_mmu_context(vcpu);
10268 } else if (nested_cpu_has2(vmcs12,
10269 SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES)) {
10270 vmx_flush_tlb_ept_only(vcpu);
10259 } 10271 }
10260 10272
10261 /* 10273 /*
@@ -11055,6 +11067,10 @@ static void nested_vmx_vmexit(struct kvm_vcpu *vcpu, u32 exit_reason,
11055 vmx->nested.change_vmcs01_virtual_x2apic_mode = false; 11067 vmx->nested.change_vmcs01_virtual_x2apic_mode = false;
11056 vmx_set_virtual_x2apic_mode(vcpu, 11068 vmx_set_virtual_x2apic_mode(vcpu,
11057 vcpu->arch.apic_base & X2APIC_ENABLE); 11069 vcpu->arch.apic_base & X2APIC_ENABLE);
11070 } else if (!nested_cpu_has_ept(vmcs12) &&
11071 nested_cpu_has2(vmcs12,
11072 SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES)) {
11073 vmx_flush_tlb_ept_only(vcpu);
11058 } 11074 }
11059 11075
11060 /* This is needed for same reason as it was needed in prepare_vmcs02 */ 11076 /* This is needed for same reason as it was needed in prepare_vmcs02 */