]> git.proxmox.com Git - pve-kernel-jessie.git/commitdiff
kvm mttr fixes (pci passthrough)
authorAlexandre Derumier <aderumier@odiso.com>
Wed, 30 Dec 2015 08:58:05 +0000 (09:58 +0100)
committerDietmar Maurer <dietmar@proxmox.com>
Thu, 31 Dec 2015 11:43:25 +0000 (12:43 +0100)
Signed-off-by: Alexandre Derumier <aderumier@odiso.com>
0001-mttr.patch [new file with mode: 0644]
0002-mttr.patch [new file with mode: 0644]
0003-mttr.patch [new file with mode: 0644]
Makefile

diff --git a/0001-mttr.patch b/0001-mttr.patch
new file mode 100644 (file)
index 0000000..6ffbe38
--- /dev/null
@@ -0,0 +1,34 @@
+From a7f2d7865720ff13d5b0f2a3bb1fd80dc3d7a73f Mon Sep 17 00:00:00 2001
+From: Alexis Dambricourt <alexis.dambricourt@gmail.com>
+Date: Mon, 14 Dec 2015 15:39:34 +0100
+Subject: KVM: MTRR: fix fixed MTRR segment look up
+
+This fixes the slow-down of VM running with pci-passthrough, since some MTRR
+range changed from MTRR_TYPE_WRBACK to MTRR_TYPE_UNCACHABLE.  Memory in the
+0K-640K range was incorrectly treated as uncacheable.
+
+Fixes: f7bfb57b3e89ff89c0da9f93dedab89f68d6ca27
+Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=107561
+Cc: qemu-stable@nongnu.org
+Signed-off-by: Alexis Dambricourt <alexis.dambricourt@gmail.com>
+[Use correct BZ for "Fixes" annotation.  - Paolo]
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+---
+ arch/x86/kvm/mtrr.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/x86/kvm/mtrr.c b/arch/x86/kvm/mtrr.c
+index 9e8bf13..adc54e1 100644
+--- a/arch/x86/kvm/mtrr.c
++++ b/arch/x86/kvm/mtrr.c
+@@ -267,7 +267,7 @@ static int fixed_mtrr_addr_to_seg(u64 addr)
+       for (seg = 0; seg < seg_num; seg++) {
+               mtrr_seg = &fixed_seg_table[seg];
+-              if (mtrr_seg->start >= addr && addr < mtrr_seg->end)
++              if (mtrr_seg->start <= addr && addr < mtrr_seg->end)
+                       return seg;
+       }
+-- 
+cgit v0.11.2
diff --git a/0002-mttr.patch b/0002-mttr.patch
new file mode 100644 (file)
index 0000000..fe1c420
--- /dev/null
@@ -0,0 +1,61 @@
+From fa7c4ebd5ae0c22f9908436303106a9ffcf0cf42 Mon Sep 17 00:00:00 2001
+From: Paolo Bonzini <pbonzini@redhat.com>
+Date: Mon, 14 Dec 2015 16:57:31 +0100
+Subject: KVM: MTRR: observe maxphyaddr from guest CPUID, not host
+
+Conversion of MTRRs to ranges used the maxphyaddr from the boot CPU.
+This is wrong, because var_mtrr_range's mask variable then is discontiguous
+(like FF00FFFF000, where the first run of 0s corresponds to the bits
+between host and guest maxphyaddr).  Instead always set up the masks
+to be full 64-bit values---we know that the reserved bits at the top
+are zero, and we can restore them when reading the MSR.  This way
+var_mtrr_range gets a mask that just works.
+
+Fixes: a13842dc668b40daef4327294a6d3bdc8bd30276
+Cc: qemu-stable@nongnu.org
+Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=107561
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+---
+ arch/x86/kvm/mtrr.c | 9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+diff --git a/arch/x86/kvm/mtrr.c b/arch/x86/kvm/mtrr.c
+index adc54e1..7747b6d 100644
+--- a/arch/x86/kvm/mtrr.c
++++ b/arch/x86/kvm/mtrr.c
+@@ -300,7 +300,6 @@ static void var_mtrr_range(struct kvm_mtrr_range *range, u64 *start, u64 *end)
+       *start = range->base & PAGE_MASK;
+       mask = range->mask & PAGE_MASK;
+-      mask |= ~0ULL << boot_cpu_data.x86_phys_bits;
+       /* This cannot overflow because writing to the reserved bits of
+        * variable MTRRs causes a #GP.
+@@ -356,10 +355,14 @@ static void set_var_mtrr_msr(struct kvm_vcpu *vcpu, u32 msr, u64 data)
+       if (var_mtrr_range_is_valid(cur))
+               list_del(&mtrr_state->var_ranges[index].node);
++      /* Extend the mask with all 1 bits to the left, since those
++       * bits must implicitly be 0.  The bits are then cleared
++       * when reading them.
++       */
+       if (!is_mtrr_mask)
+               cur->base = data;
+       else
+-              cur->mask = data;
++              cur->mask = data | (-1LL << cpuid_maxphyaddr(vcpu));
+       /* add it to the list if it's enabled. */
+       if (var_mtrr_range_is_valid(cur)) {
+@@ -426,6 +429,8 @@ int kvm_mtrr_get_msr(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata)
+                       *pdata = vcpu->arch.mtrr_state.var_ranges[index].base;
+               else
+                       *pdata = vcpu->arch.mtrr_state.var_ranges[index].mask;
++
++              *pdata &= (1ULL << cpuid_maxphyaddr(vcpu)) - 1;
+       }
+       return 0;
+-- 
+cgit v0.11.2
+
diff --git a/0003-mttr.patch b/0003-mttr.patch
new file mode 100644 (file)
index 0000000..61606e4
--- /dev/null
@@ -0,0 +1,78 @@
+From e24dea2afc6a0852983dc741072d8e96155e13f5 Mon Sep 17 00:00:00 2001
+From: Paolo Bonzini <pbonzini@redhat.com>
+Date: Tue, 22 Dec 2015 15:20:00 +0100
+Subject: KVM: MTRR: treat memory as writeback if MTRR is disabled in guest
+ CPUID
+
+Virtual machines can be run with CPUID such that there are no MTRRs.
+In that case, the firmware will never enable MTRRs and it is obviously
+undesirable to run the guest entirely with UC memory.  Check out guest
+CPUID, and use WB memory if MTRR do not exist.
+
+Cc: qemu-stable@nongnu.org
+Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=107561
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+---
+ arch/x86/kvm/cpuid.h |  8 ++++++++
+ arch/x86/kvm/mtrr.c  | 14 +++++++++++---
+ 2 files changed, 19 insertions(+), 3 deletions(-)
+
+diff --git a/arch/x86/kvm/cpuid.h b/arch/x86/kvm/cpuid.h
+index 06332cb..3f5c48d 100644
+--- a/arch/x86/kvm/cpuid.h
++++ b/arch/x86/kvm/cpuid.h
+@@ -38,6 +38,14 @@ static inline bool guest_cpuid_has_xsave(struct kvm_vcpu *vcpu)
+       return best && (best->ecx & bit(X86_FEATURE_XSAVE));
+ }
++static inline bool guest_cpuid_has_mtrr(struct kvm_vcpu *vcpu)
++{
++      struct kvm_cpuid_entry2 *best;
++
++      best = kvm_find_cpuid_entry(vcpu, 1, 0);
++      return best && (best->edx & bit(X86_FEATURE_MTRR));
++}
++
+ static inline bool guest_cpuid_has_tsc_adjust(struct kvm_vcpu *vcpu)
+ {
+       struct kvm_cpuid_entry2 *best;
+diff --git a/arch/x86/kvm/mtrr.c b/arch/x86/kvm/mtrr.c
+index 7747b6d..3f8c732 100644
+--- a/arch/x86/kvm/mtrr.c
++++ b/arch/x86/kvm/mtrr.c
+@@ -120,14 +120,22 @@ static u8 mtrr_default_type(struct kvm_mtrr *mtrr_state)
+       return mtrr_state->deftype & IA32_MTRR_DEF_TYPE_TYPE_MASK;
+ }
+-static u8 mtrr_disabled_type(void)
++static u8 mtrr_disabled_type(struct kvm_vcpu *vcpu)
+ {
+       /*
+        * Intel SDM 11.11.2.2: all MTRRs are disabled when
+        * IA32_MTRR_DEF_TYPE.E bit is cleared, and the UC
+        * memory type is applied to all of physical memory.
++       *
++       * However, virtual machines can be run with CPUID such that
++       * there are no MTRRs.  In that case, the firmware will never
++       * enable MTRRs and it is obviously undesirable to run the
++       * guest entirely with UC memory and we use WB.
+        */
+-      return MTRR_TYPE_UNCACHABLE;
++      if (guest_cpuid_has_mtrr(vcpu))
++              return MTRR_TYPE_UNCACHABLE;
++      else
++              return MTRR_TYPE_WRBACK;
+ }
+ /*
+@@ -675,7 +683,7 @@ u8 kvm_mtrr_get_guest_memory_type(struct kvm_vcpu *vcpu, gfn_t gfn)
+       }
+       if (iter.mtrr_disabled)
+-              return mtrr_disabled_type();
++              return mtrr_disabled_type(vcpu);
+       /* not contained in any MTRRs. */
+       if (type == -1)
+-- 
+cgit v0.11.2
index ce86bc226fcb458744ca0ff26840f300f5e4fb96..ca3c00ab9c5e48a47e8777dd95f4b79052ee1401 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -249,6 +249,11 @@ ${KERNEL_SRC}/README ${KERNEL_CFG_ORG}: ${KERNELSRCTAR}
        cd ${KERNEL_SRC}; patch -p1 <../0007-aacraid-ioctl-fix.patch
        cd ${KERNEL_SRC}; patch -p1 <../0008-aacraid-use-pci-enable-msix-range.patch
        cd ${KERNEL_SRC}; patch -p1 <../0009-aacraid-update-driver-version.patch
+       # backport MTTR kvm fixed (pci passthrough bug) from kernel 4.4rc7
+       cd ${KERNEL_SRC}; patch -p1 <../0001-mttr.patch
+       cd ${KERNEL_SRC}; patch -p1 <../0002-mttr.patch
+       cd ${KERNEL_SRC}; patch -p1 <../0003-mttr.patch
+
        sed -i ${KERNEL_SRC}/Makefile -e 's/^EXTRAVERSION.*$$/EXTRAVERSION=${EXTRAVERSION}/'
        touch $@