diff options
author | Gleb Natapov <gleb@redhat.com> | 2009-02-04 10:28:14 -0500 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2009-03-24 05:03:11 -0400 |
commit | 4925663a079c77d95d8685228ad6675fc5639c8e (patch) | |
tree | 52e93df78b23a44ed21d015f835688f673dd351a /virt/kvm/irq_comm.c | |
parent | 452425dbaa1974e9fc489e64a8de46a47b4c2754 (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/kvm/irq_comm.c')
-rw-r--r-- | virt/kvm/irq_comm.c | 41 |
1 files changed, 28 insertions, 13 deletions
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 | ||
32 | static void kvm_set_pic_irq(struct kvm_kernel_irq_routing_entry *e, | 32 | static 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 | ||
40 | static void kvm_set_ioapic_irq(struct kvm_kernel_irq_routing_entry *e, | 42 | static 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 | ||
46 | static void kvm_set_msi(struct kvm_kernel_irq_routing_entry *e, | 48 | static 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 |
94 | void 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 | */ | ||
102 | int 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 | ||
120 | void kvm_notify_acked_irq(struct kvm *kvm, unsigned irqchip, unsigned pin) | 135 | void 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: |