diff options
author | Paolo Bonzini <pbonzini@redhat.com> | 2016-12-18 15:47:54 -0500 |
---|---|---|
committer | Radim Krčmář <rkrcmar@redhat.com> | 2017-01-09 08:48:01 -0500 |
commit | b3c045d33218fe291b04d30e24b6eab0431987e6 (patch) | |
tree | b803f5aadf5501746a7f56d985e6b52eb50083da | |
parent | eb90f3417a0cc4880e979ccc84e41890d410ea5b (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.c | 36 |
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 | ||
573 | static void apic_update_ppr(struct kvm_lapic *apic) | 573 | static 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 | |||
581 | static 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 | |||
606 | static 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 | ||
598 | void kvm_apic_update_ppr(struct kvm_vcpu *vcpu) | 614 | void kvm_apic_update_ppr(struct kvm_vcpu *vcpu) |
@@ -2056,17 +2072,13 @@ nomem: | |||
2056 | int kvm_apic_has_interrupt(struct kvm_vcpu *vcpu) | 2072 | int 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 | ||
2072 | int kvm_apic_accept_pic_intr(struct kvm_vcpu *vcpu) | 2084 | int kvm_apic_accept_pic_intr(struct kvm_vcpu *vcpu) |