Skip to content

Commit

Permalink
KVM: inject ExtINT interrupt before APIC interrupts
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Gleb Natapov authored and Marcelo Tosatti committed Dec 14, 2012
1 parent 5e2c688 commit f3200d0
Show file tree
Hide file tree
Showing 2 changed files with 10 additions and 18 deletions.
2 changes: 2 additions & 0 deletions arch/x86/kvm/i8259.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
26 changes: 8 additions & 18 deletions arch/x86/kvm/irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand All @@ -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);

Expand Down

0 comments on commit f3200d0

Please sign in to comment.