aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorGleb Natapov <gleb@redhat.com>2013-06-24 08:19:15 -0400
committerGleb Natapov <gleb@redhat.com>2013-06-27 07:20:53 -0400
commit24f7bb52e952912b6a936ebcdc4e744b03e9e5cf (patch)
tree53ebca7bbfcae0eb83f678c37f9ab02fdd52179d /arch
parent489223edf29bc08f84e581c9495a2b42c9d52f08 (diff)
KVM: Fix RTC interrupt coalescing tracking
This reverts most of the f1ed0450a5fac7067590317cbf027f566b6ccbca. After the commit kvm_apic_set_irq() no longer returns accurate information about interrupt injection status if injection is done into disabled APIC. RTC interrupt coalescing tracking relies on the information to be accurate and cannot recover if it is not. Signed-off-by: Gleb Natapov <gleb@redhat.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/kvm/lapic.c53
-rw-r--r--arch/x86/kvm/lapic.h6
2 files changed, 35 insertions, 24 deletions
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index 9d751931cf84..9f4bea805bed 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -405,17 +405,17 @@ int kvm_lapic_find_highest_irr(struct kvm_vcpu *vcpu)
405 return highest_irr; 405 return highest_irr;
406} 406}
407 407
408static void __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode, 408static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
409 int vector, int level, int trig_mode, 409 int vector, int level, int trig_mode,
410 unsigned long *dest_map); 410 unsigned long *dest_map);
411 411
412void kvm_apic_set_irq(struct kvm_vcpu *vcpu, struct kvm_lapic_irq *irq, 412int kvm_apic_set_irq(struct kvm_vcpu *vcpu, struct kvm_lapic_irq *irq,
413 unsigned long *dest_map) 413 unsigned long *dest_map)
414{ 414{
415 struct kvm_lapic *apic = vcpu->arch.apic; 415 struct kvm_lapic *apic = vcpu->arch.apic;
416 416
417 __apic_accept_irq(apic, irq->delivery_mode, irq->vector, 417 return __apic_accept_irq(apic, irq->delivery_mode, irq->vector,
418 irq->level, irq->trig_mode, dest_map); 418 irq->level, irq->trig_mode, dest_map);
419} 419}
420 420
421static int pv_eoi_put_user(struct kvm_vcpu *vcpu, u8 val) 421static int pv_eoi_put_user(struct kvm_vcpu *vcpu, u8 val)
@@ -608,8 +608,7 @@ bool kvm_irq_delivery_to_apic_fast(struct kvm *kvm, struct kvm_lapic *src,
608 *r = -1; 608 *r = -1;
609 609
610 if (irq->shorthand == APIC_DEST_SELF) { 610 if (irq->shorthand == APIC_DEST_SELF) {
611 kvm_apic_set_irq(src->vcpu, irq, dest_map); 611 *r = kvm_apic_set_irq(src->vcpu, irq, dest_map);
612 *r = 1;
613 return true; 612 return true;
614 } 613 }
615 614
@@ -654,8 +653,7 @@ bool kvm_irq_delivery_to_apic_fast(struct kvm *kvm, struct kvm_lapic *src,
654 continue; 653 continue;
655 if (*r < 0) 654 if (*r < 0)
656 *r = 0; 655 *r = 0;
657 kvm_apic_set_irq(dst[i]->vcpu, irq, dest_map); 656 *r += kvm_apic_set_irq(dst[i]->vcpu, irq, dest_map);
658 *r += 1;
659 } 657 }
660 658
661 ret = true; 659 ret = true;
@@ -664,11 +662,15 @@ out:
664 return ret; 662 return ret;
665} 663}
666 664
667/* Set an IRQ pending in the lapic. */ 665/*
668static void __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode, 666 * Add a pending IRQ into lapic.
669 int vector, int level, int trig_mode, 667 * Return 1 if successfully added and 0 if discarded.
670 unsigned long *dest_map) 668 */
669static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
670 int vector, int level, int trig_mode,
671 unsigned long *dest_map)
671{ 672{
673 int result = 0;
672 struct kvm_vcpu *vcpu = apic->vcpu; 674 struct kvm_vcpu *vcpu = apic->vcpu;
673 675
674 switch (delivery_mode) { 676 switch (delivery_mode) {
@@ -682,10 +684,13 @@ static void __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
682 if (dest_map) 684 if (dest_map)
683 __set_bit(vcpu->vcpu_id, dest_map); 685 __set_bit(vcpu->vcpu_id, dest_map);
684 686
685 if (kvm_x86_ops->deliver_posted_interrupt) 687 if (kvm_x86_ops->deliver_posted_interrupt) {
688 result = 1;
686 kvm_x86_ops->deliver_posted_interrupt(vcpu, vector); 689 kvm_x86_ops->deliver_posted_interrupt(vcpu, vector);
687 else { 690 } else {
688 if (apic_test_and_set_irr(vector, apic)) { 691 result = !apic_test_and_set_irr(vector, apic);
692
693 if (!result) {
689 if (trig_mode) 694 if (trig_mode)
690 apic_debug("level trig mode repeatedly " 695 apic_debug("level trig mode repeatedly "
691 "for vector %d", vector); 696 "for vector %d", vector);
@@ -697,7 +702,7 @@ static void __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
697 } 702 }
698out: 703out:
699 trace_kvm_apic_accept_irq(vcpu->vcpu_id, delivery_mode, 704 trace_kvm_apic_accept_irq(vcpu->vcpu_id, delivery_mode,
700 trig_mode, vector, false); 705 trig_mode, vector, !result);
701 break; 706 break;
702 707
703 case APIC_DM_REMRD: 708 case APIC_DM_REMRD:
@@ -709,12 +714,14 @@ out:
709 break; 714 break;
710 715
711 case APIC_DM_NMI: 716 case APIC_DM_NMI:
717 result = 1;
712 kvm_inject_nmi(vcpu); 718 kvm_inject_nmi(vcpu);
713 kvm_vcpu_kick(vcpu); 719 kvm_vcpu_kick(vcpu);
714 break; 720 break;
715 721
716 case APIC_DM_INIT: 722 case APIC_DM_INIT:
717 if (!trig_mode || level) { 723 if (!trig_mode || level) {
724 result = 1;
718 /* assumes that there are only KVM_APIC_INIT/SIPI */ 725 /* assumes that there are only KVM_APIC_INIT/SIPI */
719 apic->pending_events = (1UL << KVM_APIC_INIT); 726 apic->pending_events = (1UL << KVM_APIC_INIT);
720 /* make sure pending_events is visible before sending 727 /* make sure pending_events is visible before sending
@@ -731,6 +738,7 @@ out:
731 case APIC_DM_STARTUP: 738 case APIC_DM_STARTUP:
732 apic_debug("SIPI to vcpu %d vector 0x%02x\n", 739 apic_debug("SIPI to vcpu %d vector 0x%02x\n",
733 vcpu->vcpu_id, vector); 740 vcpu->vcpu_id, vector);
741 result = 1;
734 apic->sipi_vector = vector; 742 apic->sipi_vector = vector;
735 /* make sure sipi_vector is visible for the receiver */ 743 /* make sure sipi_vector is visible for the receiver */
736 smp_wmb(); 744 smp_wmb();
@@ -752,6 +760,7 @@ out:
752 delivery_mode); 760 delivery_mode);
753 break; 761 break;
754 } 762 }
763 return result;
755} 764}
756 765
757int kvm_apic_compare_prio(struct kvm_vcpu *vcpu1, struct kvm_vcpu *vcpu2) 766int kvm_apic_compare_prio(struct kvm_vcpu *vcpu1, struct kvm_vcpu *vcpu2)
@@ -1461,7 +1470,7 @@ int apic_has_pending_timer(struct kvm_vcpu *vcpu)
1461 return 0; 1470 return 0;
1462} 1471}
1463 1472
1464void kvm_apic_local_deliver(struct kvm_lapic *apic, int lvt_type) 1473int kvm_apic_local_deliver(struct kvm_lapic *apic, int lvt_type)
1465{ 1474{
1466 u32 reg = kvm_apic_get_reg(apic, lvt_type); 1475 u32 reg = kvm_apic_get_reg(apic, lvt_type);
1467 int vector, mode, trig_mode; 1476 int vector, mode, trig_mode;
@@ -1470,8 +1479,10 @@ void kvm_apic_local_deliver(struct kvm_lapic *apic, int lvt_type)
1470 vector = reg & APIC_VECTOR_MASK; 1479 vector = reg & APIC_VECTOR_MASK;
1471 mode = reg & APIC_MODE_MASK; 1480 mode = reg & APIC_MODE_MASK;
1472 trig_mode = reg & APIC_LVT_LEVEL_TRIGGER; 1481 trig_mode = reg & APIC_LVT_LEVEL_TRIGGER;
1473 __apic_accept_irq(apic, mode, vector, 1, trig_mode, NULL); 1482 return __apic_accept_irq(apic, mode, vector, 1, trig_mode,
1483 NULL);
1474 } 1484 }
1485 return 0;
1475} 1486}
1476 1487
1477void kvm_apic_nmi_wd_deliver(struct kvm_vcpu *vcpu) 1488void kvm_apic_nmi_wd_deliver(struct kvm_vcpu *vcpu)
diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h
index 61a73a01ab0b..c730ac9fe801 100644
--- a/arch/x86/kvm/lapic.h
+++ b/arch/x86/kvm/lapic.h
@@ -57,9 +57,9 @@ void kvm_apic_update_tmr(struct kvm_vcpu *vcpu, u32 *tmr);
57void kvm_apic_update_irr(struct kvm_vcpu *vcpu, u32 *pir); 57void kvm_apic_update_irr(struct kvm_vcpu *vcpu, u32 *pir);
58int kvm_apic_match_physical_addr(struct kvm_lapic *apic, u16 dest); 58int kvm_apic_match_physical_addr(struct kvm_lapic *apic, u16 dest);
59int kvm_apic_match_logical_addr(struct kvm_lapic *apic, u8 mda); 59int kvm_apic_match_logical_addr(struct kvm_lapic *apic, u8 mda);
60void kvm_apic_set_irq(struct kvm_vcpu *vcpu, struct kvm_lapic_irq *irq, 60int kvm_apic_set_irq(struct kvm_vcpu *vcpu, struct kvm_lapic_irq *irq,
61 unsigned long *dest_map); 61 unsigned long *dest_map);
62void kvm_apic_local_deliver(struct kvm_lapic *apic, int lvt_type); 62int kvm_apic_local_deliver(struct kvm_lapic *apic, int lvt_type);
63 63
64bool kvm_irq_delivery_to_apic_fast(struct kvm *kvm, struct kvm_lapic *src, 64bool kvm_irq_delivery_to_apic_fast(struct kvm *kvm, struct kvm_lapic *src,
65 struct kvm_lapic_irq *irq, int *r, unsigned long *dest_map); 65 struct kvm_lapic_irq *irq, int *r, unsigned long *dest_map);