aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarcelo Tosatti <mtosatti@redhat.com>2008-07-26 16:01:00 -0400
committerAvi Kivity <avi@qumranet.com>2008-10-15 04:15:16 -0400
commitf52447261bc8c21dfd4635196e32d2da1352f589 (patch)
treea0de6cefa7fbfdd07285bd60c4f61e4e2f2d4ed6
parent564f15378f04921d5749f27ec53d5e68a6d1d446 (diff)
KVM: irq ack notification
Based on a patch from: Ben-Ami Yassour <benami@il.ibm.com> which was based on a patch from: Amit Shah <amit.shah@qumranet.com> Notify IRQ acking on PIC/APIC emulation. The previous patch missed two things: - Edge triggered interrupts on IOAPIC - PIC reset with IRR/ISR set should be equivalent to ack (LAPIC probably needs something similar). Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com> CC: Amit Shah <amit.shah@qumranet.com> CC: Ben-Ami Yassour <benami@il.ibm.com> Signed-off-by: Avi Kivity <avi@qumranet.com>
-rw-r--r--arch/x86/kvm/i8259.c12
-rw-r--r--arch/x86/kvm/irq.c2
-rw-r--r--arch/x86/kvm/irq.h3
-rw-r--r--arch/x86/kvm/lapic.c7
-rw-r--r--virt/kvm/ioapic.c20
-rw-r--r--virt/kvm/ioapic.h3
6 files changed, 34 insertions, 13 deletions
diff --git a/arch/x86/kvm/i8259.c b/arch/x86/kvm/i8259.c
index 55e179ad98ef..de704995b819 100644
--- a/arch/x86/kvm/i8259.c
+++ b/arch/x86/kvm/i8259.c
@@ -159,9 +159,10 @@ static inline void pic_intack(struct kvm_kpic_state *s, int irq)
159 s->irr &= ~(1 << irq); 159 s->irr &= ~(1 << irq);
160} 160}
161 161
162int kvm_pic_read_irq(struct kvm_pic *s) 162int kvm_pic_read_irq(struct kvm *kvm)
163{ 163{
164 int irq, irq2, intno; 164 int irq, irq2, intno;
165 struct kvm_pic *s = pic_irqchip(kvm);
165 166
166 irq = pic_get_irq(&s->pics[0]); 167 irq = pic_get_irq(&s->pics[0]);
167 if (irq >= 0) { 168 if (irq >= 0) {
@@ -187,12 +188,21 @@ int kvm_pic_read_irq(struct kvm_pic *s)
187 intno = s->pics[0].irq_base + irq; 188 intno = s->pics[0].irq_base + irq;
188 } 189 }
189 pic_update_irq(s); 190 pic_update_irq(s);
191 kvm_notify_acked_irq(kvm, irq);
190 192
191 return intno; 193 return intno;
192} 194}
193 195
194void kvm_pic_reset(struct kvm_kpic_state *s) 196void kvm_pic_reset(struct kvm_kpic_state *s)
195{ 197{
198 int irq;
199 struct kvm *kvm = s->pics_state->irq_request_opaque;
200
201 for (irq = 0; irq < PIC_NUM_PINS; irq++) {
202 if (!(s->imr & (1 << irq)) && (s->irr & (1 << irq) ||
203 s->isr & (1 << irq)))
204 kvm_notify_acked_irq(kvm, irq);
205 }
196 s->last_irr = 0; 206 s->last_irr = 0;
197 s->irr = 0; 207 s->irr = 0;
198 s->imr = 0; 208 s->imr = 0;
diff --git a/arch/x86/kvm/irq.c b/arch/x86/kvm/irq.c
index 90911958d853..3c508afaa285 100644
--- a/arch/x86/kvm/irq.c
+++ b/arch/x86/kvm/irq.c
@@ -72,7 +72,7 @@ int kvm_cpu_get_interrupt(struct kvm_vcpu *v)
72 if (kvm_apic_accept_pic_intr(v)) { 72 if (kvm_apic_accept_pic_intr(v)) {
73 s = pic_irqchip(v->kvm); 73 s = pic_irqchip(v->kvm);
74 s->output = 0; /* PIC */ 74 s->output = 0; /* PIC */
75 vector = kvm_pic_read_irq(s); 75 vector = kvm_pic_read_irq(v->kvm);
76 } 76 }
77 } 77 }
78 return vector; 78 return vector;
diff --git a/arch/x86/kvm/irq.h b/arch/x86/kvm/irq.h
index 95fe718e3abc..479a3d2d5614 100644
--- a/arch/x86/kvm/irq.h
+++ b/arch/x86/kvm/irq.h
@@ -63,11 +63,12 @@ struct kvm_pic {
63 void *irq_request_opaque; 63 void *irq_request_opaque;
64 int output; /* intr from master PIC */ 64 int output; /* intr from master PIC */
65 struct kvm_io_device dev; 65 struct kvm_io_device dev;
66 void (*ack_notifier)(void *opaque, int irq);
66}; 67};
67 68
68struct kvm_pic *kvm_create_pic(struct kvm *kvm); 69struct kvm_pic *kvm_create_pic(struct kvm *kvm);
69void kvm_pic_set_irq(void *opaque, int irq, int level); 70void kvm_pic_set_irq(void *opaque, int irq, int level);
70int kvm_pic_read_irq(struct kvm_pic *s); 71int kvm_pic_read_irq(struct kvm *kvm);
71void kvm_pic_update_irq(struct kvm_pic *s); 72void kvm_pic_update_irq(struct kvm_pic *s);
72 73
73static inline struct kvm_pic *pic_irqchip(struct kvm *kvm) 74static inline struct kvm_pic *pic_irqchip(struct kvm *kvm)
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index 9fde0ac24268..be94f93a73f6 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -439,7 +439,7 @@ struct kvm_vcpu *kvm_get_lowest_prio_vcpu(struct kvm *kvm, u8 vector,
439static void apic_set_eoi(struct kvm_lapic *apic) 439static void apic_set_eoi(struct kvm_lapic *apic)
440{ 440{
441 int vector = apic_find_highest_isr(apic); 441 int vector = apic_find_highest_isr(apic);
442 442 int trigger_mode;
443 /* 443 /*
444 * Not every write EOI will has corresponding ISR, 444 * Not every write EOI will has corresponding ISR,
445 * one example is when Kernel check timer on setup_IO_APIC 445 * one example is when Kernel check timer on setup_IO_APIC
@@ -451,7 +451,10 @@ static void apic_set_eoi(struct kvm_lapic *apic)
451 apic_update_ppr(apic); 451 apic_update_ppr(apic);
452 452
453 if (apic_test_and_clear_vector(vector, apic->regs + APIC_TMR)) 453 if (apic_test_and_clear_vector(vector, apic->regs + APIC_TMR))
454 kvm_ioapic_update_eoi(apic->vcpu->kvm, vector); 454 trigger_mode = IOAPIC_LEVEL_TRIG;
455 else
456 trigger_mode = IOAPIC_EDGE_TRIG;
457 kvm_ioapic_update_eoi(apic->vcpu->kvm, vector, trigger_mode);
455} 458}
456 459
457static void apic_send_ipi(struct kvm_lapic *apic) 460static void apic_send_ipi(struct kvm_lapic *apic)
diff --git a/virt/kvm/ioapic.c b/virt/kvm/ioapic.c
index c0d22870ee9c..515cd7ce761c 100644
--- a/virt/kvm/ioapic.c
+++ b/virt/kvm/ioapic.c
@@ -39,6 +39,7 @@
39 39
40#include "ioapic.h" 40#include "ioapic.h"
41#include "lapic.h" 41#include "lapic.h"
42#include "irq.h"
42 43
43#if 0 44#if 0
44#define ioapic_debug(fmt,arg...) printk(KERN_WARNING fmt,##arg) 45#define ioapic_debug(fmt,arg...) printk(KERN_WARNING fmt,##arg)
@@ -285,26 +286,31 @@ void kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level)
285 } 286 }
286} 287}
287 288
288static void __kvm_ioapic_update_eoi(struct kvm_ioapic *ioapic, int gsi) 289static void __kvm_ioapic_update_eoi(struct kvm_ioapic *ioapic, int gsi,
290 int trigger_mode)
289{ 291{
290 union ioapic_redir_entry *ent; 292 union ioapic_redir_entry *ent;
291 293
292 ent = &ioapic->redirtbl[gsi]; 294 ent = &ioapic->redirtbl[gsi];
293 ASSERT(ent->fields.trig_mode == IOAPIC_LEVEL_TRIG);
294 295
295 ent->fields.remote_irr = 0; 296 kvm_notify_acked_irq(ioapic->kvm, gsi);
296 if (!ent->fields.mask && (ioapic->irr & (1 << gsi))) 297
297 ioapic_service(ioapic, gsi); 298 if (trigger_mode == IOAPIC_LEVEL_TRIG) {
299 ASSERT(ent->fields.trig_mode == IOAPIC_LEVEL_TRIG);
300 ent->fields.remote_irr = 0;
301 if (!ent->fields.mask && (ioapic->irr & (1 << gsi)))
302 ioapic_service(ioapic, gsi);
303 }
298} 304}
299 305
300void kvm_ioapic_update_eoi(struct kvm *kvm, int vector) 306void kvm_ioapic_update_eoi(struct kvm *kvm, int vector, int trigger_mode)
301{ 307{
302 struct kvm_ioapic *ioapic = kvm->arch.vioapic; 308 struct kvm_ioapic *ioapic = kvm->arch.vioapic;
303 int i; 309 int i;
304 310
305 for (i = 0; i < IOAPIC_NUM_PINS; i++) 311 for (i = 0; i < IOAPIC_NUM_PINS; i++)
306 if (ioapic->redirtbl[i].fields.vector == vector) 312 if (ioapic->redirtbl[i].fields.vector == vector)
307 __kvm_ioapic_update_eoi(ioapic, i); 313 __kvm_ioapic_update_eoi(ioapic, i, trigger_mode);
308} 314}
309 315
310static int ioapic_in_range(struct kvm_io_device *this, gpa_t addr, 316static int ioapic_in_range(struct kvm_io_device *this, gpa_t addr,
diff --git a/virt/kvm/ioapic.h b/virt/kvm/ioapic.h
index 7f16675fe783..b52732f493c1 100644
--- a/virt/kvm/ioapic.h
+++ b/virt/kvm/ioapic.h
@@ -58,6 +58,7 @@ struct kvm_ioapic {
58 } redirtbl[IOAPIC_NUM_PINS]; 58 } redirtbl[IOAPIC_NUM_PINS];
59 struct kvm_io_device dev; 59 struct kvm_io_device dev;
60 struct kvm *kvm; 60 struct kvm *kvm;
61 void (*ack_notifier)(void *opaque, int irq);
61}; 62};
62 63
63#ifdef DEBUG 64#ifdef DEBUG
@@ -87,7 +88,7 @@ static inline int irqchip_in_kernel(struct kvm *kvm)
87 88
88struct kvm_vcpu *kvm_get_lowest_prio_vcpu(struct kvm *kvm, u8 vector, 89struct kvm_vcpu *kvm_get_lowest_prio_vcpu(struct kvm *kvm, u8 vector,
89 unsigned long bitmap); 90 unsigned long bitmap);
90void kvm_ioapic_update_eoi(struct kvm *kvm, int vector); 91void kvm_ioapic_update_eoi(struct kvm *kvm, int vector, int trigger_mode);
91int kvm_ioapic_init(struct kvm *kvm); 92int kvm_ioapic_init(struct kvm *kvm);
92void kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level); 93void kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level);
93void kvm_ioapic_reset(struct kvm_ioapic *ioapic); 94void kvm_ioapic_reset(struct kvm_ioapic *ioapic);