aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGleb Natapov <gleb@redhat.com>2012-12-10 07:05:55 -0500
committerMarcelo Tosatti <mtosatti@redhat.com>2012-12-13 20:05:21 -0500
commitf3200d00ea42e485772ff92d6d649aa8eeb640c0 (patch)
tree78324a59e921b1d3f1ed48bbdc6f1bf7fb96f147
parent5e2c688351f4aee9981918661b6c1679f4155f06 (diff)
KVM: inject ExtINT interrupt before APIC interrupts
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>
-rw-r--r--arch/x86/kvm/i8259.c2
-rw-r--r--arch/x86/kvm/irq.c26
2 files changed, 10 insertions, 18 deletions
diff --git a/arch/x86/kvm/i8259.c b/arch/x86/kvm/i8259.c
index 848206df0967..cc31f7c06d3d 100644
--- a/arch/x86/kvm/i8259.c
+++ b/arch/x86/kvm/i8259.c
@@ -241,6 +241,8 @@ int kvm_pic_read_irq(struct kvm *kvm)
241 int irq, irq2, intno; 241 int irq, irq2, intno;
242 struct kvm_pic *s = pic_irqchip(kvm); 242 struct kvm_pic *s = pic_irqchip(kvm);
243 243
244 s->output = 0;
245
244 pic_lock(s); 246 pic_lock(s);
245 irq = pic_get_irq(&s->pics[0]); 247 irq = pic_get_irq(&s->pics[0]);
246 if (irq >= 0) { 248 if (irq >= 0) {
diff --git a/arch/x86/kvm/irq.c b/arch/x86/kvm/irq.c
index 7e06ba1618bd..ebd98d0c4f6e 100644
--- a/arch/x86/kvm/irq.c
+++ b/arch/x86/kvm/irq.c
@@ -48,14 +48,10 @@ int kvm_cpu_has_interrupt(struct kvm_vcpu *v)
48 if (!irqchip_in_kernel(v->kvm)) 48 if (!irqchip_in_kernel(v->kvm))
49 return v->arch.interrupt.pending; 49 return v->arch.interrupt.pending;
50 50
51 if (kvm_apic_has_interrupt(v) == -1) { /* LAPIC */ 51 if (kvm_apic_accept_pic_intr(v) && pic_irqchip(v->kvm)->output)
52 if (kvm_apic_accept_pic_intr(v)) { 52 return pic_irqchip(v->kvm)->output; /* PIC */
53 s = pic_irqchip(v->kvm); /* PIC */ 53
54 return s->output; 54 return kvm_apic_has_interrupt(v) != -1; /* LAPIC */
55 } else
56 return 0;
57 }
58 return 1;
59} 55}
60EXPORT_SYMBOL_GPL(kvm_cpu_has_interrupt); 56EXPORT_SYMBOL_GPL(kvm_cpu_has_interrupt);
61 57
@@ -65,20 +61,14 @@ EXPORT_SYMBOL_GPL(kvm_cpu_has_interrupt);
65int kvm_cpu_get_interrupt(struct kvm_vcpu *v) 61int kvm_cpu_get_interrupt(struct kvm_vcpu *v)
66{ 62{
67 struct kvm_pic *s; 63 struct kvm_pic *s;
68 int vector;
69 64
70 if (!irqchip_in_kernel(v->kvm)) 65 if (!irqchip_in_kernel(v->kvm))
71 return v->arch.interrupt.nr; 66 return v->arch.interrupt.nr;
72 67
73 vector = kvm_get_apic_interrupt(v); /* APIC */ 68 if (kvm_apic_accept_pic_intr(v) && pic_irqchip(v->kvm)->output)
74 if (vector == -1) { 69 return kvm_pic_read_irq(v->kvm); /* PIC */
75 if (kvm_apic_accept_pic_intr(v)) { 70
76 s = pic_irqchip(v->kvm); 71 return kvm_get_apic_interrupt(v); /* APIC */
77 s->output = 0; /* PIC */
78 vector = kvm_pic_read_irq(v->kvm);
79 }
80 }
81 return vector;
82} 72}
83EXPORT_SYMBOL_GPL(kvm_cpu_get_interrupt); 73EXPORT_SYMBOL_GPL(kvm_cpu_get_interrupt);
84 74