KVM: PIC: call ack notifiers for irqs that are dropped form irr
authorGleb Natapov <gleb@redhat.com>
Thu, 26 Jul 2012 07:00:45 +0000 (10:00 +0300)
committerAvi Kivity <avi@redhat.com>
Thu, 26 Jul 2012 09:19:06 +0000 (12:19 +0300)
After commit 242ec97c358256 PIT interrupts are no longer delivered after
PIC reset. It happens because PIT injects interrupt only if previous one
was acked, but since on PIC reset it is dropped from irr it will never
be delivered and hence acknowledged. Fix that by calling ack notifier on
PIC reset.

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

index 1df8fb9e1d5dafc47000ef644823a748c1b31c91..e498b18f010c7b97480ccf1f1018c87a5f07daa1 100644 (file)
@@ -316,6 +316,11 @@ static void pic_ioport_write(void *opaque, u32 addr, u32 val)
        addr &= 1;
        if (addr == 0) {
                if (val & 0x10) {
+                       u8 edge_irr = s->irr & ~s->elcr;
+                       int i;
+                       bool found;
+                       struct kvm_vcpu *vcpu;
+
                        s->init4 = val & 1;
                        s->last_irr = 0;
                        s->irr &= s->elcr;
@@ -333,6 +338,18 @@ static void pic_ioport_write(void *opaque, u32 addr, u32 val)
                        if (val & 0x08)
                                pr_pic_unimpl(
                                        "level sensitive irq not supported");
+
+                       kvm_for_each_vcpu(i, vcpu, s->pics_state->kvm)
+                               if (kvm_apic_accept_pic_intr(vcpu)) {
+                                       found = true;
+                                       break;
+                               }
+
+
+                       if (found)
+                               for (irq = 0; irq < PIC_NUM_PINS/2; irq++)
+                                       if (edge_irr & (1 << irq))
+                                               pic_clear_isr(s, irq);
                } else if (val & 0x08) {
                        if (val & 0x04)
                                s->poll = 1;