diff options
-rw-r--r-- | arch/x86/kvm/lapic.c | 18 |
1 files changed, 12 insertions, 6 deletions
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index 6e8ce5a1a05d..e0e5642dae41 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c | |||
@@ -341,8 +341,12 @@ EXPORT_SYMBOL_GPL(kvm_apic_update_irr); | |||
341 | 341 | ||
342 | static inline void apic_set_irr(int vec, struct kvm_lapic *apic) | 342 | static inline void apic_set_irr(int vec, struct kvm_lapic *apic) |
343 | { | 343 | { |
344 | apic->irr_pending = true; | ||
345 | apic_set_vector(vec, apic->regs + APIC_IRR); | 344 | apic_set_vector(vec, apic->regs + APIC_IRR); |
345 | /* | ||
346 | * irr_pending must be true if any interrupt is pending; set it after | ||
347 | * APIC_IRR to avoid race with apic_clear_irr | ||
348 | */ | ||
349 | apic->irr_pending = true; | ||
346 | } | 350 | } |
347 | 351 | ||
348 | static inline int apic_search_irr(struct kvm_lapic *apic) | 352 | static inline int apic_search_irr(struct kvm_lapic *apic) |
@@ -374,13 +378,15 @@ static inline void apic_clear_irr(int vec, struct kvm_lapic *apic) | |||
374 | 378 | ||
375 | vcpu = apic->vcpu; | 379 | vcpu = apic->vcpu; |
376 | 380 | ||
377 | apic_clear_vector(vec, apic->regs + APIC_IRR); | 381 | if (unlikely(kvm_apic_vid_enabled(vcpu->kvm))) { |
378 | if (unlikely(kvm_apic_vid_enabled(vcpu->kvm))) | ||
379 | /* try to update RVI */ | 382 | /* try to update RVI */ |
383 | apic_clear_vector(vec, apic->regs + APIC_IRR); | ||
380 | kvm_make_request(KVM_REQ_EVENT, vcpu); | 384 | kvm_make_request(KVM_REQ_EVENT, vcpu); |
381 | else { | 385 | } else { |
382 | vec = apic_search_irr(apic); | 386 | apic->irr_pending = false; |
383 | apic->irr_pending = (vec != -1); | 387 | apic_clear_vector(vec, apic->regs + APIC_IRR); |
388 | if (apic_search_irr(apic) != -1) | ||
389 | apic->irr_pending = true; | ||
384 | } | 390 | } |
385 | } | 391 | } |
386 | 392 | ||