]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/commitdiff
KVM: x86: Software disabled APIC should still deliver NMIs
authorNadav Amit <namit@cs.technion.ac.il>
Sun, 2 Nov 2014 09:54:54 +0000 (11:54 +0200)
committerPaolo Bonzini <pbonzini@redhat.com>
Mon, 17 Nov 2014 11:16:19 +0000 (12:16 +0100)
Currently, the APIC logical map does not consider VCPUs whose local-apic is
software-disabled.  However, NMIs, INIT, etc. should still be delivered to such
VCPUs. Therefore, the APIC mode should first be determined, and then the map,
considering all VCPUs should be constructed.

To address this issue, first find the APIC mode, and only then construct the
logical map.

Signed-off-by: Nadav Amit <namit@cs.technion.ac.il>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
arch/x86/kvm/lapic.c

index 344e7d36d0e8215ef58ba8d2b263b3e5e172bafe..c98b44d0ffe6aebe8e603806a415f96f30f58917 100644 (file)
@@ -156,8 +156,6 @@ static void recalculate_apic_map(struct kvm *kvm)
 
        kvm_for_each_vcpu(i, vcpu, kvm) {
                struct kvm_lapic *apic = vcpu->arch.apic;
-               u16 cid, lid;
-               u32 ldr;
 
                if (!kvm_apic_present(vcpu))
                        continue;
@@ -175,13 +173,22 @@ static void recalculate_apic_map(struct kvm *kvm)
                        new->cid_mask = (1 << KVM_X2APIC_CID_BITS) - 1;
                        new->lid_mask = 0xffff;
                        new->broadcast = X2APIC_BROADCAST;
-               } else if (kvm_apic_sw_enabled(apic) &&
-                               !new->cid_mask /* flat mode */ &&
-                               kvm_apic_get_reg(apic, APIC_DFR) == APIC_DFR_CLUSTER) {
-                       new->cid_shift = 4;
-                       new->cid_mask = 0xf;
-                       new->lid_mask = 0xf;
+                       break;
+               } else if (kvm_apic_sw_enabled(apic)) {
+                       if (kvm_apic_get_reg(apic, APIC_DFR) ==
+                                                       APIC_DFR_CLUSTER) {
+                               new->cid_shift = 4;
+                               new->cid_mask = 0xf;
+                               new->lid_mask = 0xf;
+                       }
+                       break;
                }
+       }
+
+       kvm_for_each_vcpu(i, vcpu, kvm) {
+               struct kvm_lapic *apic = vcpu->arch.apic;
+               u16 cid, lid;
+               u32 ldr;
 
                new->phys_map[kvm_apic_id(apic)] = apic;