diff options
author | Wincy Van <fanwenyi0529@gmail.com> | 2014-12-23 22:14:29 -0500 |
---|---|---|
committer | Marcelo Tosatti <mtosatti@redhat.com> | 2015-03-10 09:37:43 -0400 |
commit | 5bda6eed2e3626f40f2602a8fed72007f1fafaf8 (patch) | |
tree | ddea5207022bd6dbf8e974dcbb6673374bc05106 | |
parent | ae548c5c806497b3495019f550f93dee03f6c15a (diff) |
KVM: ioapic: Record edge-triggered interrupts delivery status
This patch fixes the bug discussed in
https://www.mail-archive.com/kvm@vger.kernel.org/msg109813.html
This patch uses a new field named irr_delivered to record the
delivery status of edge-triggered interrupts, and clears the
delivered interrupts in kvm_get_ioapic. So it has the same effect
of commit 0bc830b05c667218d703f2026ec866c49df974fc
("KVM: ioapic: clear IRR for edge-triggered interrupts at delivery")
while avoids the bug of Windows guests.
Signed-off-by: Wincy Van <fanwenyi0529@gmail.com>
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
-rw-r--r-- | arch/x86/kvm/ioapic.c | 7 | ||||
-rw-r--r-- | arch/x86/kvm/ioapic.h | 1 |
2 files changed, 7 insertions, 1 deletions
diff --git a/arch/x86/kvm/ioapic.c b/arch/x86/kvm/ioapic.c index b1947e0f3e10..a2e9d961c7fe 100644 --- a/arch/x86/kvm/ioapic.c +++ b/arch/x86/kvm/ioapic.c | |||
@@ -206,6 +206,8 @@ static int ioapic_set_irq(struct kvm_ioapic *ioapic, unsigned int irq, | |||
206 | 206 | ||
207 | old_irr = ioapic->irr; | 207 | old_irr = ioapic->irr; |
208 | ioapic->irr |= mask; | 208 | ioapic->irr |= mask; |
209 | if (edge) | ||
210 | ioapic->irr_delivered &= ~mask; | ||
209 | if ((edge && old_irr == ioapic->irr) || | 211 | if ((edge && old_irr == ioapic->irr) || |
210 | (!edge && entry.fields.remote_irr)) { | 212 | (!edge && entry.fields.remote_irr)) { |
211 | ret = 0; | 213 | ret = 0; |
@@ -349,7 +351,7 @@ static int ioapic_service(struct kvm_ioapic *ioapic, int irq, bool line_status) | |||
349 | irqe.shorthand = 0; | 351 | irqe.shorthand = 0; |
350 | 352 | ||
351 | if (irqe.trig_mode == IOAPIC_EDGE_TRIG) | 353 | if (irqe.trig_mode == IOAPIC_EDGE_TRIG) |
352 | ioapic->irr &= ~(1 << irq); | 354 | ioapic->irr_delivered |= 1 << irq; |
353 | 355 | ||
354 | if (irq == RTC_GSI && line_status) { | 356 | if (irq == RTC_GSI && line_status) { |
355 | /* | 357 | /* |
@@ -597,6 +599,7 @@ static void kvm_ioapic_reset(struct kvm_ioapic *ioapic) | |||
597 | ioapic->base_address = IOAPIC_DEFAULT_BASE_ADDRESS; | 599 | ioapic->base_address = IOAPIC_DEFAULT_BASE_ADDRESS; |
598 | ioapic->ioregsel = 0; | 600 | ioapic->ioregsel = 0; |
599 | ioapic->irr = 0; | 601 | ioapic->irr = 0; |
602 | ioapic->irr_delivered = 0; | ||
600 | ioapic->id = 0; | 603 | ioapic->id = 0; |
601 | memset(ioapic->irq_eoi, 0x00, IOAPIC_NUM_PINS); | 604 | memset(ioapic->irq_eoi, 0x00, IOAPIC_NUM_PINS); |
602 | rtc_irq_eoi_tracking_reset(ioapic); | 605 | rtc_irq_eoi_tracking_reset(ioapic); |
@@ -654,6 +657,7 @@ int kvm_get_ioapic(struct kvm *kvm, struct kvm_ioapic_state *state) | |||
654 | 657 | ||
655 | spin_lock(&ioapic->lock); | 658 | spin_lock(&ioapic->lock); |
656 | memcpy(state, ioapic, sizeof(struct kvm_ioapic_state)); | 659 | memcpy(state, ioapic, sizeof(struct kvm_ioapic_state)); |
660 | state->irr &= ~ioapic->irr_delivered; | ||
657 | spin_unlock(&ioapic->lock); | 661 | spin_unlock(&ioapic->lock); |
658 | return 0; | 662 | return 0; |
659 | } | 663 | } |
@@ -667,6 +671,7 @@ int kvm_set_ioapic(struct kvm *kvm, struct kvm_ioapic_state *state) | |||
667 | spin_lock(&ioapic->lock); | 671 | spin_lock(&ioapic->lock); |
668 | memcpy(ioapic, state, sizeof(struct kvm_ioapic_state)); | 672 | memcpy(ioapic, state, sizeof(struct kvm_ioapic_state)); |
669 | ioapic->irr = 0; | 673 | ioapic->irr = 0; |
674 | ioapic->irr_delivered = 0; | ||
670 | update_handled_vectors(ioapic); | 675 | update_handled_vectors(ioapic); |
671 | kvm_vcpu_request_scan_ioapic(kvm); | 676 | kvm_vcpu_request_scan_ioapic(kvm); |
672 | kvm_ioapic_inject_all(ioapic, state->irr); | 677 | kvm_ioapic_inject_all(ioapic, state->irr); |
diff --git a/arch/x86/kvm/ioapic.h b/arch/x86/kvm/ioapic.h index c2e36d934af4..38d8402ea65c 100644 --- a/arch/x86/kvm/ioapic.h +++ b/arch/x86/kvm/ioapic.h | |||
@@ -77,6 +77,7 @@ struct kvm_ioapic { | |||
77 | struct rtc_status rtc_status; | 77 | struct rtc_status rtc_status; |
78 | struct delayed_work eoi_inject; | 78 | struct delayed_work eoi_inject; |
79 | u32 irq_eoi[IOAPIC_NUM_PINS]; | 79 | u32 irq_eoi[IOAPIC_NUM_PINS]; |
80 | u32 irr_delivered; | ||
80 | }; | 81 | }; |
81 | 82 | ||
82 | #ifdef DEBUG | 83 | #ifdef DEBUG |