diff options
Diffstat (limited to 'virt')
-rw-r--r-- | virt/kvm/ioapic.c | 23 | ||||
-rw-r--r-- | virt/kvm/ioapic.h | 2 | ||||
-rw-r--r-- | virt/kvm/irq_comm.c | 41 |
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 | ||
86 | static void ioapic_service(struct kvm_ioapic *ioapic, unsigned int idx) | 86 | static 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 | ||
101 | static void ioapic_write_indirect(struct kvm_ioapic *ioapic, u32 val) | 104 | static 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 | ||
276 | void kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level) | 283 | int 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 | ||
296 | static void __kvm_ioapic_update_eoi(struct kvm_ioapic *ioapic, int pin, | 305 | static 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); |
84 | void kvm_ioapic_update_eoi(struct kvm *kvm, int vector, int trigger_mode); | 84 | void kvm_ioapic_update_eoi(struct kvm *kvm, int vector, int trigger_mode); |
85 | int kvm_ioapic_init(struct kvm *kvm); | 85 | int kvm_ioapic_init(struct kvm *kvm); |
86 | void kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level); | 86 | int kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level); |
87 | void kvm_ioapic_reset(struct kvm_ioapic *ioapic); | 87 | void kvm_ioapic_reset(struct kvm_ioapic *ioapic); |
88 | u32 kvm_ioapic_get_delivery_bitmask(struct kvm_ioapic *ioapic, u8 dest, | 88 | u32 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 | ||
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: |