From dae257366d0411c21175a0d69178be8a2e0f6eac Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 23 Jun 2014 15:15:21 -0400 Subject: [PATCH] 3.10-stable patches added patches: kvm-lapic-sync-highest-isr-to-hardware-apic-on-eoi.patch --- ...-highest-isr-to-hardware-apic-on-eoi.patch | 125 ++++++++++++++++++ queue-3.10/series | 1 + 2 files changed, 126 insertions(+) create mode 100644 queue-3.10/kvm-lapic-sync-highest-isr-to-hardware-apic-on-eoi.patch diff --git a/queue-3.10/kvm-lapic-sync-highest-isr-to-hardware-apic-on-eoi.patch b/queue-3.10/kvm-lapic-sync-highest-isr-to-hardware-apic-on-eoi.patch new file mode 100644 index 00000000000..c575e6a2a1e --- /dev/null +++ b/queue-3.10/kvm-lapic-sync-highest-isr-to-hardware-apic-on-eoi.patch @@ -0,0 +1,125 @@ +From fc57ac2c9ca8109ea97fcc594f4be436944230cc Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Wed, 14 May 2014 17:40:58 +0200 +Subject: KVM: lapic: sync highest ISR to hardware apic on EOI + +From: Paolo Bonzini + +commit fc57ac2c9ca8109ea97fcc594f4be436944230cc upstream. + +When Hyper-V enlightenments are in effect, Windows prefers to issue an +Hyper-V MSR write to issue an EOI rather than an x2apic MSR write. +The Hyper-V MSR write is not handled by the processor, and besides +being slower, this also causes bugs with APIC virtualization. The +reason is that on EOI the processor will modify the highest in-service +interrupt (SVI) field of the VMCS, as explained in section 29.1.4 of +the SDM; every other step in EOI virtualization is already done by +apic_send_eoi or on VM entry, but this one is missing. + +We need to do the same, and be careful not to muck with the isr_count +and highest_isr_cache fields that are unused when virtual interrupt +delivery is enabled. + +Reviewed-by: Yang Zhang +Signed-off-by: Paolo Bonzini +Signed-off-by: Greg Kroah-Hartman + +--- + arch/x86/kvm/lapic.c | 62 +++++++++++++++++++++++++++++++++++---------------- + 1 file changed, 43 insertions(+), 19 deletions(-) + +--- a/arch/x86/kvm/lapic.c ++++ b/arch/x86/kvm/lapic.c +@@ -370,6 +370,8 @@ static inline void apic_clear_irr(int ve + + static inline void apic_set_isr(int vec, struct kvm_lapic *apic) + { ++ /* Note that we never get here with APIC virtualization enabled. */ ++ + if (!__apic_test_and_set_vector(vec, apic->regs + APIC_ISR)) + ++apic->isr_count; + BUG_ON(apic->isr_count > MAX_APIC_VECTOR); +@@ -381,12 +383,48 @@ static inline void apic_set_isr(int vec, + apic->highest_isr_cache = vec; + } + ++static inline int apic_find_highest_isr(struct kvm_lapic *apic) ++{ ++ int result; ++ ++ /* ++ * Note that isr_count is always 1, and highest_isr_cache ++ * is always -1, with APIC virtualization enabled. ++ */ ++ if (!apic->isr_count) ++ return -1; ++ if (likely(apic->highest_isr_cache != -1)) ++ return apic->highest_isr_cache; ++ ++ result = find_highest_vector(apic->regs + APIC_ISR); ++ ASSERT(result == -1 || result >= 16); ++ ++ return result; ++} ++ + static inline void apic_clear_isr(int vec, struct kvm_lapic *apic) + { +- if (__apic_test_and_clear_vector(vec, apic->regs + APIC_ISR)) ++ struct kvm_vcpu *vcpu; ++ if (!__apic_test_and_clear_vector(vec, apic->regs + APIC_ISR)) ++ return; ++ ++ vcpu = apic->vcpu; ++ ++ /* ++ * We do get here for APIC virtualization enabled if the guest ++ * uses the Hyper-V APIC enlightenment. In this case we may need ++ * to trigger a new interrupt delivery by writing the SVI field; ++ * on the other hand isr_count and highest_isr_cache are unused ++ * and must be left alone. ++ */ ++ if (unlikely(kvm_apic_vid_enabled(vcpu->kvm))) ++ kvm_x86_ops->hwapic_isr_update(vcpu->kvm, ++ apic_find_highest_isr(apic)); ++ else { + --apic->isr_count; +- BUG_ON(apic->isr_count < 0); +- apic->highest_isr_cache = -1; ++ BUG_ON(apic->isr_count < 0); ++ apic->highest_isr_cache = -1; ++ } + } + + int kvm_lapic_find_highest_irr(struct kvm_vcpu *vcpu) +@@ -466,22 +504,6 @@ static void pv_eoi_clr_pending(struct kv + __clear_bit(KVM_APIC_PV_EOI_PENDING, &vcpu->arch.apic_attention); + } + +-static inline int apic_find_highest_isr(struct kvm_lapic *apic) +-{ +- int result; +- +- /* Note that isr_count is always 1 with vid enabled */ +- if (!apic->isr_count) +- return -1; +- if (likely(apic->highest_isr_cache != -1)) +- return apic->highest_isr_cache; +- +- result = find_highest_vector(apic->regs + APIC_ISR); +- ASSERT(result == -1 || result >= 16); +- +- return result; +-} +- + void kvm_apic_update_tmr(struct kvm_vcpu *vcpu, u32 *tmr) + { + struct kvm_lapic *apic = vcpu->arch.apic; +@@ -1619,6 +1641,8 @@ int kvm_get_apic_interrupt(struct kvm_vc + int vector = kvm_apic_has_interrupt(vcpu); + struct kvm_lapic *apic = vcpu->arch.apic; + ++ /* Note that we never get here with APIC virtualization enabled. */ ++ + if (vector == -1) + return -1; + diff --git a/queue-3.10/series b/queue-3.10/series index eb03b518960..2107a7b4ba1 100644 --- a/queue-3.10/series +++ b/queue-3.10/series @@ -24,4 +24,5 @@ rtnetlink-fix-userspace-api-breakage-for-iproute2-v3.9.0.patch vxlan-use-dev-needed_headroom-instead-of-dev-hard_header_len.patch net-mlx4_core-pass-pci_device_id.driver_data-to-__mlx4_init_one-during-reset.patch net-mlx4_core-preserve-pci_dev_data-after-__mlx4_remove_one.patch +kvm-lapic-sync-highest-isr-to-hardware-apic-on-eoi.patch arm-at91-fix-at91_sysirq_mask_rtc-for-sam9x5-socs.patch -- 2.47.3