KVM: Call ack notifiers from PIC when guest OS acks an IRQ.
authorGleb Natapov <gleb@redhat.com>
Tue, 4 Aug 2009 12:30:28 +0000 (15:30 +0300)
committerAvi Kivity <avi@redhat.com>
Thu, 10 Sep 2009 05:33:22 +0000 (08:33 +0300)
Currently they are called when irq vector is been delivered.  Calling ack
notifiers at this point is wrong.  Device assignment ack notifier enables
host interrupts, but guest not yet had a chance to clear interrupt
condition in a device.

Signed-off-by: Gleb Natapov <gleb@redhat.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
arch/x86/kvm/i8259.c

index d27320c..3aacd33 100644 (file)
@@ -41,25 +41,16 @@ static void pic_lock(struct kvm_pic *s)
 static void pic_unlock(struct kvm_pic *s)
        __releases(&s->lock)
 {
-       struct kvm *kvm = s->kvm;
-       unsigned acks = s->pending_acks;
-       struct kvm_vcpu *vcpu;
-
-       s->pending_acks = 0;
-
        spin_unlock(&s->lock);
-
-       while (acks) {
-               kvm_notify_acked_irq(kvm, SELECT_PIC(__ffs(acks)),
-                                    __ffs(acks));
-               acks &= acks - 1;
-       }
 }
 
 static void pic_clear_isr(struct kvm_kpic_state *s, int irq)
 {
        s->isr &= ~(1 << irq);
        s->isr_ack |= (1 << irq);
+       if (s != &s->pics_state->pics[0])
+               irq += 8;
+       kvm_notify_acked_irq(s->pics_state->kvm, SELECT_PIC(irq), irq);
 }
 
 void kvm_pic_clear_isr_ack(struct kvm *kvm)
@@ -240,7 +231,6 @@ int kvm_pic_read_irq(struct kvm *kvm)
        }
        pic_update_irq(s);
        pic_unlock(s);
-       kvm_notify_acked_irq(kvm, SELECT_PIC(irq), irq);
 
        return intno;
 }
@@ -260,7 +250,7 @@ void kvm_pic_reset(struct kvm_kpic_state *s)
                if (vcpu0 && kvm_apic_accept_pic_intr(vcpu0))
                        if (s->irr & (1 << irq) || s->isr & (1 << irq)) {
                                n = irq + irqbase;
-                               s->pics_state->pending_acks |= 1 << n;
+                               kvm_notify_acked_irq(kvm, SELECT_PIC(n), n);
                        }
        }
        s->last_irr = 0;