diff options
Diffstat (limited to 'virt/kvm/ioapic.c')
-rw-r--r-- | virt/kvm/ioapic.c | 23 |
1 files changed, 16 insertions, 7 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, |