KVM: inject ExtINT interrupt before APIC interrupts
authorGleb Natapov <gleb@redhat.com>
Mon, 10 Dec 2012 12:05:55 +0000 (14:05 +0200)
committerMarcelo Tosatti <mtosatti@redhat.com>
Fri, 14 Dec 2012 01:05:21 +0000 (23:05 -0200)
According to Intel SDM Volume 3 Section 10.8.1 "Interrupt Handling with
the Pentium 4 and Intel Xeon Processors" and Section 10.8.2 "Interrupt
Handling with the P6 Family and Pentium Processors" ExtINT interrupts are
sent directly to the processor core for handling. Currently KVM checks
APIC before it considers ExtINT interrupts for injection which is
backwards from the spec. Make code behave according to the SDM.

Signed-off-by: Gleb Natapov <gleb@redhat.com>
Acked-by: "Zhang, Yang Z" <yang.z.zhang@intel.com>
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
arch/x86/kvm/i8259.c
arch/x86/kvm/irq.c

index 848206df0967d1d35e4fde100575147ef482a2f4..cc31f7c06d3ddc8ab4ef61c775510e2dcbfde518 100644 (file)
@@ -241,6 +241,8 @@ int kvm_pic_read_irq(struct kvm *kvm)
        int irq, irq2, intno;
        struct kvm_pic *s = pic_irqchip(kvm);
 
+       s->output = 0;
+
        pic_lock(s);
        irq = pic_get_irq(&s->pics[0]);
        if (irq >= 0) {
index 7e06ba1618bd73168226a4a299895778e4a00065..ebd98d0c4f6efbb2b749d1b2e8546a73b54eaf8b 100644 (file)
@@ -48,14 +48,10 @@ int kvm_cpu_has_interrupt(struct kvm_vcpu *v)
        if (!irqchip_in_kernel(v->kvm))
                return v->arch.interrupt.pending;
 
-       if (kvm_apic_has_interrupt(v) == -1) {  /* LAPIC */
-               if (kvm_apic_accept_pic_intr(v)) {
-                       s = pic_irqchip(v->kvm);        /* PIC */
-                       return s->output;
-               } else
-                       return 0;
-       }
-       return 1;
+       if (kvm_apic_accept_pic_intr(v) && pic_irqchip(v->kvm)->output)
+               return pic_irqchip(v->kvm)->output;     /* PIC */
+
+       return kvm_apic_has_interrupt(v) != -1; /* LAPIC */
 }
 EXPORT_SYMBOL_GPL(kvm_cpu_has_interrupt);
 
@@ -65,20 +61,14 @@ EXPORT_SYMBOL_GPL(kvm_cpu_has_interrupt);
 int kvm_cpu_get_interrupt(struct kvm_vcpu *v)
 {
        struct kvm_pic *s;
-       int vector;
 
        if (!irqchip_in_kernel(v->kvm))
                return v->arch.interrupt.nr;
 
-       vector = kvm_get_apic_interrupt(v);     /* APIC */
-       if (vector == -1) {
-               if (kvm_apic_accept_pic_intr(v)) {
-                       s = pic_irqchip(v->kvm);
-                       s->output = 0;          /* PIC */
-                       vector = kvm_pic_read_irq(v->kvm);
-               }
-       }
-       return vector;
+       if (kvm_apic_accept_pic_intr(v) && pic_irqchip(v->kvm)->output)
+               return kvm_pic_read_irq(v->kvm);        /* PIC */
+
+       return kvm_get_apic_interrupt(v);       /* APIC */
 }
 EXPORT_SYMBOL_GPL(kvm_cpu_get_interrupt);