]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.10-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 23 Jun 2014 19:15:21 +0000 (15:15 -0400)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 23 Jun 2014 19:15:21 +0000 (15:15 -0400)
added patches:
kvm-lapic-sync-highest-isr-to-hardware-apic-on-eoi.patch

queue-3.10/kvm-lapic-sync-highest-isr-to-hardware-apic-on-eoi.patch [new file with mode: 0644]
queue-3.10/series

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 (file)
index 0000000..c575e6a
--- /dev/null
@@ -0,0 +1,125 @@
+From fc57ac2c9ca8109ea97fcc594f4be436944230cc Mon Sep 17 00:00:00 2001
+From: Paolo Bonzini <pbonzini@redhat.com>
+Date: Wed, 14 May 2014 17:40:58 +0200
+Subject: KVM: lapic: sync highest ISR to hardware apic on EOI
+
+From: Paolo Bonzini <pbonzini@redhat.com>
+
+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 <yang.z.zhang@intel.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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;
index eb03b5189601987f868fec83e7e676870af505a0..2107a7b4ba160b4c455e1cd1bbc1c8dfad0bf3de 100644 (file)
@@ -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