aboutsummaryrefslogtreecommitdiffstats
path: root/virt
diff options
context:
space:
mode:
authorGleb Natapov <gleb@redhat.com>2009-02-04 10:28:14 -0500
committerAvi Kivity <avi@redhat.com>2009-03-24 05:03:11 -0400
commit4925663a079c77d95d8685228ad6675fc5639c8e (patch)
tree52e93df78b23a44ed21d015f835688f673dd351a /virt
parent452425dbaa1974e9fc489e64a8de46a47b4c2754 (diff)
KVM: Report IRQ injection status to userspace.
IRQ injection status is either -1 (if there was no CPU found that should except the interrupt because IRQ was masked or ioapic was misconfigured or ...) or >= 0 in that case the number indicates to how many CPUs interrupt was injected. If the value is 0 it means that the interrupt was coalesced and probably should be reinjected. Signed-off-by: Gleb Natapov <gleb@redhat.com> Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'virt')
-rw-r--r--virt/kvm/ioapic.c23
-rw-r--r--virt/kvm/ioapic.h2
-rw-r--r--virt/kvm/irq_comm.c41
3 files changed, 45 insertions, 21 deletions
diff --git a/virt/kvm/ioapic.c b/virt/kvm/ioapic.c
index 1c986ac59ad6..c3b99def9cbc 100644
--- a/virt/kvm/ioapic.c
+++ b/virt/kvm/ioapic.c
@@ -83,19 +83,22 @@ static unsigned long ioapic_read_indirect(struct kvm_ioapic *ioapic,
83 return result; 83 return result;
84} 84}
85 85
86static void ioapic_service(struct kvm_ioapic *ioapic, unsigned int idx) 86static int ioapic_service(struct kvm_ioapic *ioapic, unsigned int idx)
87{ 87{
88 union ioapic_redir_entry *pent; 88 union ioapic_redir_entry *pent;
89 int injected = -1;
89 90
90 pent = &ioapic->redirtbl[idx]; 91 pent = &ioapic->redirtbl[idx];
91 92
92 if (!pent->fields.mask) { 93 if (!pent->fields.mask) {
93 int injected = ioapic_deliver(ioapic, idx); 94 injected = ioapic_deliver(ioapic, idx);
94 if (injected && pent->fields.trig_mode == IOAPIC_LEVEL_TRIG) 95 if (injected && pent->fields.trig_mode == IOAPIC_LEVEL_TRIG)
95 pent->fields.remote_irr = 1; 96 pent->fields.remote_irr = 1;
96 } 97 }
97 if (!pent->fields.trig_mode) 98 if (!pent->fields.trig_mode)
98 ioapic->irr &= ~(1 << idx); 99 ioapic->irr &= ~(1 << idx);
100
101 return injected;
99} 102}
100 103
101static void ioapic_write_indirect(struct kvm_ioapic *ioapic, u32 val) 104static void ioapic_write_indirect(struct kvm_ioapic *ioapic, u32 val)
@@ -207,7 +210,7 @@ static int ioapic_deliver(struct kvm_ioapic *ioapic, int irq)
207 u8 trig_mode = ioapic->redirtbl[irq].fields.trig_mode; 210 u8 trig_mode = ioapic->redirtbl[irq].fields.trig_mode;
208 u32 deliver_bitmask; 211 u32 deliver_bitmask;
209 struct kvm_vcpu *vcpu; 212 struct kvm_vcpu *vcpu;
210 int vcpu_id, r = 0; 213 int vcpu_id, r = -1;
211 214
212 ioapic_debug("dest=%x dest_mode=%x delivery_mode=%x " 215 ioapic_debug("dest=%x dest_mode=%x delivery_mode=%x "
213 "vector=%x trig_mode=%x\n", 216 "vector=%x trig_mode=%x\n",
@@ -247,7 +250,9 @@ static int ioapic_deliver(struct kvm_ioapic *ioapic, int irq)
247 deliver_bitmask &= ~(1 << vcpu_id); 250 deliver_bitmask &= ~(1 << vcpu_id);
248 vcpu = ioapic->kvm->vcpus[vcpu_id]; 251 vcpu = ioapic->kvm->vcpus[vcpu_id];
249 if (vcpu) { 252 if (vcpu) {
250 r = ioapic_inj_irq(ioapic, vcpu, vector, 253 if (r < 0)
254 r = 0;
255 r += ioapic_inj_irq(ioapic, vcpu, vector,
251 trig_mode, delivery_mode); 256 trig_mode, delivery_mode);
252 } 257 }
253 } 258 }
@@ -258,8 +263,10 @@ static int ioapic_deliver(struct kvm_ioapic *ioapic, int irq)
258 continue; 263 continue;
259 deliver_bitmask &= ~(1 << vcpu_id); 264 deliver_bitmask &= ~(1 << vcpu_id);
260 vcpu = ioapic->kvm->vcpus[vcpu_id]; 265 vcpu = ioapic->kvm->vcpus[vcpu_id];
261 if (vcpu) 266 if (vcpu) {
262 ioapic_inj_nmi(vcpu); 267 ioapic_inj_nmi(vcpu);
268 r = 1;
269 }
263 else 270 else
264 ioapic_debug("NMI to vcpu %d failed\n", 271 ioapic_debug("NMI to vcpu %d failed\n",
265 vcpu->vcpu_id); 272 vcpu->vcpu_id);
@@ -273,11 +280,12 @@ static int ioapic_deliver(struct kvm_ioapic *ioapic, int irq)
273 return r; 280 return r;
274} 281}
275 282
276void kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level) 283int kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level)
277{ 284{
278 u32 old_irr = ioapic->irr; 285 u32 old_irr = ioapic->irr;
279 u32 mask = 1 << irq; 286 u32 mask = 1 << irq;
280 union ioapic_redir_entry entry; 287 union ioapic_redir_entry entry;
288 int ret = 1;
281 289
282 if (irq >= 0 && irq < IOAPIC_NUM_PINS) { 290 if (irq >= 0 && irq < IOAPIC_NUM_PINS) {
283 entry = ioapic->redirtbl[irq]; 291 entry = ioapic->redirtbl[irq];
@@ -288,9 +296,10 @@ void kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level)
288 ioapic->irr |= mask; 296 ioapic->irr |= mask;
289 if ((!entry.fields.trig_mode && old_irr != ioapic->irr) 297 if ((!entry.fields.trig_mode && old_irr != ioapic->irr)
290 || !entry.fields.remote_irr) 298 || !entry.fields.remote_irr)
291 ioapic_service(ioapic, irq); 299 ret = ioapic_service(ioapic, irq);
292 } 300 }
293 } 301 }
302 return ret;
294} 303}
295 304
296static void __kvm_ioapic_update_eoi(struct kvm_ioapic *ioapic, int pin, 305static void __kvm_ioapic_update_eoi(struct kvm_ioapic *ioapic, int pin,
diff --git a/virt/kvm/ioapic.h b/virt/kvm/ioapic.h
index 49c9581d2586..a34bd5e6436b 100644
--- a/virt/kvm/ioapic.h
+++ b/virt/kvm/ioapic.h
@@ -83,7 +83,7 @@ struct kvm_vcpu *kvm_get_lowest_prio_vcpu(struct kvm *kvm, u8 vector,
83 unsigned long bitmap); 83 unsigned long bitmap);
84void kvm_ioapic_update_eoi(struct kvm *kvm, int vector, int trigger_mode); 84void kvm_ioapic_update_eoi(struct kvm *kvm, int vector, int trigger_mode);
85int kvm_ioapic_init(struct kvm *kvm); 85int kvm_ioapic_init(struct kvm *kvm);
86void kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level); 86int kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level);
87void kvm_ioapic_reset(struct kvm_ioapic *ioapic); 87void kvm_ioapic_reset(struct kvm_ioapic *ioapic);
88u32 kvm_ioapic_get_delivery_bitmask(struct kvm_ioapic *ioapic, u8 dest, 88u32 kvm_ioapic_get_delivery_bitmask(struct kvm_ioapic *ioapic, u8 dest,
89 u8 dest_mode); 89 u8 dest_mode);
diff --git a/virt/kvm/irq_comm.c b/virt/kvm/irq_comm.c
index 6bc7439eff6e..be8aba791554 100644
--- a/virt/kvm/irq_comm.c
+++ b/virt/kvm/irq_comm.c
@@ -29,22 +29,24 @@
29 29
30#include "ioapic.h" 30#include "ioapic.h"
31 31
32static void kvm_set_pic_irq(struct kvm_kernel_irq_routing_entry *e, 32static int kvm_set_pic_irq(struct kvm_kernel_irq_routing_entry *e,
33 struct kvm *kvm, int level) 33 struct kvm *kvm, int level)
34{ 34{
35#ifdef CONFIG_X86 35#ifdef CONFIG_X86
36 kvm_pic_set_irq(pic_irqchip(kvm), e->irqchip.pin, level); 36 return kvm_pic_set_irq(pic_irqchip(kvm), e->irqchip.pin, level);
37#else
38 return -1;
37#endif 39#endif
38} 40}
39 41
40static void kvm_set_ioapic_irq(struct kvm_kernel_irq_routing_entry *e, 42static int kvm_set_ioapic_irq(struct kvm_kernel_irq_routing_entry *e,
41 struct kvm *kvm, int level) 43 struct kvm *kvm, int level)
42{ 44{
43 kvm_ioapic_set_irq(kvm->arch.vioapic, e->irqchip.pin, level); 45 return kvm_ioapic_set_irq(kvm->arch.vioapic, e->irqchip.pin, level);
44} 46}
45 47
46static void kvm_set_msi(struct kvm_kernel_irq_routing_entry *e, 48static int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e,
47 struct kvm *kvm, int level) 49 struct kvm *kvm, int level)
48{ 50{
49 int vcpu_id; 51 int vcpu_id;
50 struct kvm_vcpu *vcpu; 52 struct kvm_vcpu *vcpu;
@@ -88,13 +90,20 @@ static void kvm_set_msi(struct kvm_kernel_irq_routing_entry *e,
88 default: 90 default:
89 break; 91 break;
90 } 92 }
93 return 1;
91} 94}
92 95
93/* This should be called with the kvm->lock mutex held */ 96/* This should be called with the kvm->lock mutex held
94void kvm_set_irq(struct kvm *kvm, int irq_source_id, int irq, int level) 97 * Return value:
98 * < 0 Interrupt was ignored (masked or not delivered for other reasons)
99 * = 0 Interrupt was coalesced (previous irq is still pending)
100 * > 0 Number of CPUs interrupt was delivered to
101 */
102int kvm_set_irq(struct kvm *kvm, int irq_source_id, int irq, int level)
95{ 103{
96 struct kvm_kernel_irq_routing_entry *e; 104 struct kvm_kernel_irq_routing_entry *e;
97 unsigned long *irq_state, sig_level; 105 unsigned long *irq_state, sig_level;
106 int ret = -1;
98 107
99 if (irq < KVM_IOAPIC_NUM_PINS) { 108 if (irq < KVM_IOAPIC_NUM_PINS) {
100 irq_state = (unsigned long *)&kvm->arch.irq_states[irq]; 109 irq_state = (unsigned long *)&kvm->arch.irq_states[irq];
@@ -113,8 +122,14 @@ void kvm_set_irq(struct kvm *kvm, int irq_source_id, int irq, int level)
113 * writes to the unused one. 122 * writes to the unused one.
114 */ 123 */
115 list_for_each_entry(e, &kvm->irq_routing, link) 124 list_for_each_entry(e, &kvm->irq_routing, link)
116 if (e->gsi == irq) 125 if (e->gsi == irq) {
117 e->set(e, kvm, sig_level); 126 int r = e->set(e, kvm, sig_level);
127 if (r < 0)
128 continue;
129
130 ret = r + ((ret < 0) ? 0 : ret);
131 }
132 return ret;
118} 133}
119 134
120void kvm_notify_acked_irq(struct kvm *kvm, unsigned irqchip, unsigned pin) 135void kvm_notify_acked_irq(struct kvm *kvm, unsigned irqchip, unsigned pin)
@@ -232,7 +247,7 @@ int setup_routing_entry(struct kvm_kernel_irq_routing_entry *e,
232 e->set = kvm_set_pic_irq; 247 e->set = kvm_set_pic_irq;
233 break; 248 break;
234 case KVM_IRQCHIP_PIC_SLAVE: 249 case KVM_IRQCHIP_PIC_SLAVE:
235 e->set = kvm_set_pic_irq; 250 e->set = kvm_set_pic_irq;
236 delta = 8; 251 delta = 8;
237 break; 252 break;
238 case KVM_IRQCHIP_IOAPIC: 253 case KVM_IRQCHIP_IOAPIC: