KVM: lapic: do not scan IRR when delivering an interrupt
authorPaolo Bonzini <pbonzini@redhat.com>
Sun, 18 Dec 2016 20:43:41 +0000 (21:43 +0100)
committerRadim Krčmář <rkrcmar@redhat.com>
Mon, 9 Jan 2017 13:48:03 +0000 (14:48 +0100)
On interrupt delivery the PPR can only grow (except for auto-EOI),
so it is impossible that non-auto-EOI interrupt delivery results
in KVM_REQ_EVENT.  We can therefore use __apic_update_ppr.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
arch/x86/kvm/lapic.c

index 457fb206647d5a371c572e3ed0cda6b609ff3bec..10a745faa659d11e8a2eba1e3c51c75a13146abf 100644 (file)
@@ -2115,6 +2115,7 @@ int kvm_get_apic_interrupt(struct kvm_vcpu *vcpu)
 {
        int vector = kvm_apic_has_interrupt(vcpu);
        struct kvm_lapic *apic = vcpu->arch.apic;
+       u32 ppr;
 
        if (vector == -1)
                return -1;
@@ -2126,13 +2127,23 @@ int kvm_get_apic_interrupt(struct kvm_vcpu *vcpu)
         * because the process would deliver it through the IDT.
         */
 
-       apic_set_isr(vector, apic);
-       apic_update_ppr(apic);
        apic_clear_irr(vector, apic);
-
        if (test_bit(vector, vcpu_to_synic(vcpu)->auto_eoi_bitmap)) {
-               apic_clear_isr(vector, apic);
+               /*
+                * For auto-EOI interrupts, there might be another pending
+                * interrupt above PPR, so check whether to raise another
+                * KVM_REQ_EVENT.
+                */
                apic_update_ppr(apic);
+       } else {
+               /*
+                * For normal interrupts, PPR has been raised and there cannot
+                * be a higher-priority pending interrupt---except if there was
+                * a concurrent interrupt injection, but that would have
+                * triggered KVM_REQ_EVENT already.
+                */
+               apic_set_isr(vector, apic);
+               __apic_update_ppr(apic, &ppr);
        }
 
        return vector;