Merge branch 'kvm-lapic-fix-and-cleanup' into HEAD
[linux-block.git] / arch / x86 / kvm / x86.c
index c3ac88036b522c2833c2768541153af6992c9527..508074e47bc0ebd4535de4bc548f57abdffe863d 100644 (file)
@@ -10148,7 +10148,7 @@ void kvm_make_scan_ioapic_request(struct kvm *kvm)
        kvm_make_all_cpus_request(kvm, KVM_REQ_SCAN_IOAPIC);
 }
 
-void kvm_vcpu_update_apicv(struct kvm_vcpu *vcpu)
+void __kvm_vcpu_update_apicv(struct kvm_vcpu *vcpu)
 {
        struct kvm_lapic *apic = vcpu->arch.apic;
        bool activate;
@@ -10183,7 +10183,30 @@ out:
        preempt_enable();
        up_read(&vcpu->kvm->arch.apicv_update_lock);
 }
-EXPORT_SYMBOL_GPL(kvm_vcpu_update_apicv);
+EXPORT_SYMBOL_GPL(__kvm_vcpu_update_apicv);
+
+static void kvm_vcpu_update_apicv(struct kvm_vcpu *vcpu)
+{
+       if (!lapic_in_kernel(vcpu))
+               return;
+
+       /*
+        * Due to sharing page tables across vCPUs, the xAPIC memslot must be
+        * deleted if any vCPU has xAPIC virtualization and x2APIC enabled, but
+        * and hardware doesn't support x2APIC virtualization.  E.g. some AMD
+        * CPUs support AVIC but not x2APIC.  KVM still allows enabling AVIC in
+        * this case so that KVM can the AVIC doorbell to inject interrupts to
+        * running vCPUs, but KVM must not create SPTEs for the APIC base as
+        * the vCPU would incorrectly be able to access the vAPIC page via MMIO
+        * despite being in x2APIC mode.  For simplicity, inhibiting the APIC
+        * access page is sticky.
+        */
+       if (apic_x2apic_mode(vcpu->arch.apic) &&
+           kvm_x86_ops.allow_apicv_in_x2apic_without_x2apic_virtualization)
+               kvm_inhibit_apic_access_page(vcpu);
+
+       __kvm_vcpu_update_apicv(vcpu);
+}
 
 void __kvm_set_or_clear_apicv_inhibit(struct kvm *kvm,
                                      enum kvm_apicv_inhibit reason, bool set)
@@ -10192,7 +10215,7 @@ void __kvm_set_or_clear_apicv_inhibit(struct kvm *kvm,
 
        lockdep_assert_held_write(&kvm->arch.apicv_update_lock);
 
-       if (!static_call(kvm_x86_check_apicv_inhibit_reasons)(reason))
+       if (!(kvm_x86_ops.required_apicv_inhibits & BIT(reason)))
                return;
 
        old = new = kvm->arch.apicv_inhibit_reasons;