aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2016-12-18 15:47:54 -0500
committerRadim Krčmář <rkrcmar@redhat.com>2017-01-09 08:48:01 -0500
commitb3c045d33218fe291b04d30e24b6eab0431987e6 (patch)
treeb803f5aadf5501746a7f56d985e6b52eb50083da
parenteb90f3417a0cc4880e979ccc84e41890d410ea5b (diff)
KVM: lapic: remove unnecessary KVM_REQ_EVENT on PPR update
PPR needs to be updated whenever on every IRR read because we may have missed TPR writes that _increased_ PPR. However, these writes need not generate KVM_REQ_EVENT, because either KVM_REQ_EVENT has been set already in __apic_accept_irq, or we are going to process the interrupt right away. Reviewed-by: Roman Kagan <rkagan@virtuozzo.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
-rw-r--r--arch/x86/kvm/lapic.c36
1 files changed, 24 insertions, 12 deletions
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index 6b1d3a76c1d0..a878e33119a3 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -570,7 +570,15 @@ static void pv_eoi_clr_pending(struct kvm_vcpu *vcpu)
570 __clear_bit(KVM_APIC_PV_EOI_PENDING, &vcpu->arch.apic_attention); 570 __clear_bit(KVM_APIC_PV_EOI_PENDING, &vcpu->arch.apic_attention);
571} 571}
572 572
573static void apic_update_ppr(struct kvm_lapic *apic) 573static int apic_has_interrupt_for_ppr(struct kvm_lapic *apic, u32 ppr)
574{
575 int highest_irr = apic_find_highest_irr(apic);
576 if (highest_irr == -1 || (highest_irr & 0xF0) <= ppr)
577 return -1;
578 return highest_irr;
579}
580
581static bool __apic_update_ppr(struct kvm_lapic *apic, u32 *new_ppr)
574{ 582{
575 u32 tpr, isrv, ppr, old_ppr; 583 u32 tpr, isrv, ppr, old_ppr;
576 int isr; 584 int isr;
@@ -588,11 +596,19 @@ static void apic_update_ppr(struct kvm_lapic *apic)
588 apic_debug("vlapic %p, ppr 0x%x, isr 0x%x, isrv 0x%x", 596 apic_debug("vlapic %p, ppr 0x%x, isr 0x%x, isrv 0x%x",
589 apic, ppr, isr, isrv); 597 apic, ppr, isr, isrv);
590 598
591 if (old_ppr != ppr) { 599 *new_ppr = ppr;
600 if (old_ppr != ppr)
592 kvm_lapic_set_reg(apic, APIC_PROCPRI, ppr); 601 kvm_lapic_set_reg(apic, APIC_PROCPRI, ppr);
593 if (ppr < old_ppr) 602
594 kvm_make_request(KVM_REQ_EVENT, apic->vcpu); 603 return ppr < old_ppr;
595 } 604}
605
606static void apic_update_ppr(struct kvm_lapic *apic)
607{
608 u32 ppr;
609
610 if (__apic_update_ppr(apic, &ppr))
611 kvm_make_request(KVM_REQ_EVENT, apic->vcpu);
596} 612}
597 613
598void kvm_apic_update_ppr(struct kvm_vcpu *vcpu) 614void kvm_apic_update_ppr(struct kvm_vcpu *vcpu)
@@ -2056,17 +2072,13 @@ nomem:
2056int kvm_apic_has_interrupt(struct kvm_vcpu *vcpu) 2072int kvm_apic_has_interrupt(struct kvm_vcpu *vcpu)
2057{ 2073{
2058 struct kvm_lapic *apic = vcpu->arch.apic; 2074 struct kvm_lapic *apic = vcpu->arch.apic;
2059 int highest_irr; 2075 u32 ppr;
2060 2076
2061 if (!apic_enabled(apic)) 2077 if (!apic_enabled(apic))
2062 return -1; 2078 return -1;
2063 2079
2064 apic_update_ppr(apic); 2080 __apic_update_ppr(apic, &ppr);
2065 highest_irr = apic_find_highest_irr(apic); 2081 return apic_has_interrupt_for_ppr(apic, ppr);
2066 if ((highest_irr == -1) ||
2067 ((highest_irr & 0xF0) <= kvm_lapic_get_reg(apic, APIC_PROCPRI)))
2068 return -1;
2069 return highest_irr;
2070} 2082}
2071 2083
2072int kvm_apic_accept_pic_intr(struct kvm_vcpu *vcpu) 2084int kvm_apic_accept_pic_intr(struct kvm_vcpu *vcpu)