]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.10-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 2 Aug 2013 09:20:55 +0000 (17:20 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 2 Aug 2013 09:20:55 +0000 (17:20 +0800)
added patches:
x86-fix-proc-mtrr-with-base-size-more-than-44bits.patch

queue-3.10/series
queue-3.10/x86-fix-proc-mtrr-with-base-size-more-than-44bits.patch [new file with mode: 0644]

index 46b74aaa29dd2124d5c29afdcd1c3f0af8f41488..55a413991df3ac3cf4c7d8029401fe75bf3bbf8a 100644 (file)
@@ -96,3 +96,4 @@ iscsi-target-fix-iscsit_add_reject-usage-for-iser.patch
 iscsi-target-fix-iscsit_sequence_cmd-reject-handling-for-iser.patch
 perf-tools-revert-regression-in-configuration-of-python-support.patch
 drm-i915-correct-obj-mm_list-link-to-dev_priv-dev_priv-mm.inactive_list.patch
+x86-fix-proc-mtrr-with-base-size-more-than-44bits.patch
diff --git a/queue-3.10/x86-fix-proc-mtrr-with-base-size-more-than-44bits.patch b/queue-3.10/x86-fix-proc-mtrr-with-base-size-more-than-44bits.patch
new file mode 100644 (file)
index 0000000..2399755
--- /dev/null
@@ -0,0 +1,207 @@
+From d5c78673b1b28467354c2c30c3d4f003666ff385 Mon Sep 17 00:00:00 2001
+From: Yinghai Lu <yinghai@kernel.org>
+Date: Thu, 13 Jun 2013 15:33:35 -0700
+Subject: x86: Fix /proc/mtrr with base/size more than 44bits
+
+From: Yinghai Lu <yinghai@kernel.org>
+
+commit d5c78673b1b28467354c2c30c3d4f003666ff385 upstream.
+
+On one sytem that mtrr range is more then 44bits, in dmesg we have
+[    0.000000] MTRR default type: write-back
+[    0.000000] MTRR fixed ranges enabled:
+[    0.000000]   00000-9FFFF write-back
+[    0.000000]   A0000-BFFFF uncachable
+[    0.000000]   C0000-DFFFF write-through
+[    0.000000]   E0000-FFFFF write-protect
+[    0.000000] MTRR variable ranges enabled:
+[    0.000000]   0 [000080000000-0000FFFFFFFF] mask 3FFF80000000 uncachable
+[    0.000000]   1 [380000000000-38FFFFFFFFFF] mask 3F0000000000 uncachable
+[    0.000000]   2 [000099000000-000099FFFFFF] mask 3FFFFF000000 write-through
+[    0.000000]   3 [00009A000000-00009AFFFFFF] mask 3FFFFF000000 write-through
+[    0.000000]   4 [381FFA000000-381FFBFFFFFF] mask 3FFFFE000000 write-through
+[    0.000000]   5 [381FFC000000-381FFC0FFFFF] mask 3FFFFFF00000 write-through
+[    0.000000]   6 [0000AD000000-0000ADFFFFFF] mask 3FFFFF000000 write-through
+[    0.000000]   7 [0000BD000000-0000BDFFFFFF] mask 3FFFFF000000 write-through
+[    0.000000]   8 disabled
+[    0.000000]   9 disabled
+
+but /proc/mtrr report wrong:
+reg00: base=0x080000000 ( 2048MB), size= 2048MB, count=1: uncachable
+reg01: base=0x80000000000 (8388608MB), size=1048576MB, count=1: uncachable
+reg02: base=0x099000000 ( 2448MB), size=   16MB, count=1: write-through
+reg03: base=0x09a000000 ( 2464MB), size=   16MB, count=1: write-through
+reg04: base=0x81ffa000000 (8519584MB), size=   32MB, count=1: write-through
+reg05: base=0x81ffc000000 (8519616MB), size=    1MB, count=1: write-through
+reg06: base=0x0ad000000 ( 2768MB), size=   16MB, count=1: write-through
+reg07: base=0x0bd000000 ( 3024MB), size=   16MB, count=1: write-through
+reg08: base=0x09b000000 ( 2480MB), size=   16MB, count=1: write-combining
+
+so bit 44 and bit 45 get cut off.
+
+We have problems in arch/x86/kernel/cpu/mtrr/generic.c::generic_get_mtrr().
+1. for base, we miss cast base_lo to 64bit before shifting.
+Fix that by adding u64 casting.
+
+2. for size, it only can handle 44 bits aka 32bits + page_shift
+Fix that with 64bit mask instead of 32bit mask_lo, then range could be
+more than 44bits.
+At the same time, we need to update size_or_mask for old cpus that does
+support cpuid 0x80000008 to get phys_addr. Need to set high 32bits
+to all 1s, otherwise will not get correct size for them.
+
+Also fix mtrr_add_page: it should check base and (base + size - 1)
+instead of base and size, as base and size could be small but
+base + size could bigger enough to be out of boundary. We can
+use boot_cpu_data.x86_phys_bits directly to avoid size_or_mask.
+
+So When are we going to have size more than 44bits? that is 16TiB.
+
+after patch we have right ouput:
+reg00: base=0x080000000 ( 2048MB), size= 2048MB, count=1: uncachable
+reg01: base=0x380000000000 (58720256MB), size=1048576MB, count=1: uncachable
+reg02: base=0x099000000 ( 2448MB), size=   16MB, count=1: write-through
+reg03: base=0x09a000000 ( 2464MB), size=   16MB, count=1: write-through
+reg04: base=0x381ffa000000 (58851232MB), size=   32MB, count=1: write-through
+reg05: base=0x381ffc000000 (58851264MB), size=    1MB, count=1: write-through
+reg06: base=0x0ad000000 ( 2768MB), size=   16MB, count=1: write-through
+reg07: base=0x0bd000000 ( 3024MB), size=   16MB, count=1: write-through
+reg08: base=0x09b000000 ( 2480MB), size=   16MB, count=1: write-combining
+
+-v2: simply checking in mtrr_add_page according to hpa.
+
+[ hpa: This probably wants to go into -stable only after having sat in
+  mainline for a bit.  It is not a regression. ]
+
+Signed-off-by: Yinghai Lu <yinghai@kernel.org>
+Link: http://lkml.kernel.org/r/1371162815-29931-1-git-send-email-yinghai@kernel.org
+Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/x86/kernel/cpu/mtrr/generic.c |   21 +++++++++++----------
+ arch/x86/kernel/cpu/mtrr/main.c    |   16 +++++++++-------
+ 2 files changed, 20 insertions(+), 17 deletions(-)
+
+--- a/arch/x86/kernel/cpu/mtrr/generic.c
++++ b/arch/x86/kernel/cpu/mtrr/generic.c
+@@ -510,8 +510,9 @@ generic_get_free_region(unsigned long ba
+ static void generic_get_mtrr(unsigned int reg, unsigned long *base,
+                            unsigned long *size, mtrr_type *type)
+ {
+-      unsigned int mask_lo, mask_hi, base_lo, base_hi;
+-      unsigned int tmp, hi;
++      u32 mask_lo, mask_hi, base_lo, base_hi;
++      unsigned int hi;
++      u64 tmp, mask;
+       /*
+        * get_mtrr doesn't need to update mtrr_state, also it could be called
+@@ -532,18 +533,18 @@ static void generic_get_mtrr(unsigned in
+       rdmsr(MTRRphysBase_MSR(reg), base_lo, base_hi);
+       /* Work out the shifted address mask: */
+-      tmp = mask_hi << (32 - PAGE_SHIFT) | mask_lo >> PAGE_SHIFT;
+-      mask_lo = size_or_mask | tmp;
++      tmp = (u64)mask_hi << (32 - PAGE_SHIFT) | mask_lo >> PAGE_SHIFT;
++      mask = size_or_mask | tmp;
+       /* Expand tmp with high bits to all 1s: */
+-      hi = fls(tmp);
++      hi = fls64(tmp);
+       if (hi > 0) {
+-              tmp |= ~((1<<(hi - 1)) - 1);
++              tmp |= ~((1ULL<<(hi - 1)) - 1);
+-              if (tmp != mask_lo) {
++              if (tmp != mask) {
+                       printk(KERN_WARNING "mtrr: your BIOS has configured an incorrect mask, fixing it.\n");
+                       add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_STILL_OK);
+-                      mask_lo = tmp;
++                      mask = tmp;
+               }
+       }
+@@ -551,8 +552,8 @@ static void generic_get_mtrr(unsigned in
+        * This works correctly if size is a power of two, i.e. a
+        * contiguous range:
+        */
+-      *size = -mask_lo;
+-      *base = base_hi << (32 - PAGE_SHIFT) | base_lo >> PAGE_SHIFT;
++      *size = -mask;
++      *base = (u64)base_hi << (32 - PAGE_SHIFT) | base_lo >> PAGE_SHIFT;
+       *type = base_lo & 0xff;
+ out_put_cpu:
+--- a/arch/x86/kernel/cpu/mtrr/main.c
++++ b/arch/x86/kernel/cpu/mtrr/main.c
+@@ -305,7 +305,8 @@ int mtrr_add_page(unsigned long base, un
+               return -EINVAL;
+       }
+-      if (base & size_or_mask || size & size_or_mask) {
++      if ((base | (base + size - 1)) >>
++          (boot_cpu_data.x86_phys_bits - PAGE_SHIFT)) {
+               pr_warning("mtrr: base or size exceeds the MTRR width\n");
+               return -EINVAL;
+       }
+@@ -583,6 +584,7 @@ static struct syscore_ops mtrr_syscore_o
+ int __initdata changed_by_mtrr_cleanup;
++#define SIZE_OR_MASK_BITS(n)  (~((1ULL << ((n) - PAGE_SHIFT)) - 1))
+ /**
+  * mtrr_bp_init - initialize mtrrs on the boot CPU
+  *
+@@ -600,7 +602,7 @@ void __init mtrr_bp_init(void)
+       if (cpu_has_mtrr) {
+               mtrr_if = &generic_mtrr_ops;
+-              size_or_mask = 0xff000000;                      /* 36 bits */
++              size_or_mask = SIZE_OR_MASK_BITS(36);
+               size_and_mask = 0x00f00000;
+               phys_addr = 36;
+@@ -619,7 +621,7 @@ void __init mtrr_bp_init(void)
+                            boot_cpu_data.x86_mask == 0x4))
+                               phys_addr = 36;
+-                      size_or_mask = ~((1ULL << (phys_addr - PAGE_SHIFT)) - 1);
++                      size_or_mask = SIZE_OR_MASK_BITS(phys_addr);
+                       size_and_mask = ~size_or_mask & 0xfffff00000ULL;
+               } else if (boot_cpu_data.x86_vendor == X86_VENDOR_CENTAUR &&
+                          boot_cpu_data.x86 == 6) {
+@@ -627,7 +629,7 @@ void __init mtrr_bp_init(void)
+                        * VIA C* family have Intel style MTRRs,
+                        * but don't support PAE
+                        */
+-                      size_or_mask = 0xfff00000;              /* 32 bits */
++                      size_or_mask = SIZE_OR_MASK_BITS(32);
+                       size_and_mask = 0;
+                       phys_addr = 32;
+               }
+@@ -637,21 +639,21 @@ void __init mtrr_bp_init(void)
+                       if (cpu_has_k6_mtrr) {
+                               /* Pre-Athlon (K6) AMD CPU MTRRs */
+                               mtrr_if = mtrr_ops[X86_VENDOR_AMD];
+-                              size_or_mask = 0xfff00000;      /* 32 bits */
++                              size_or_mask = SIZE_OR_MASK_BITS(32);
+                               size_and_mask = 0;
+                       }
+                       break;
+               case X86_VENDOR_CENTAUR:
+                       if (cpu_has_centaur_mcr) {
+                               mtrr_if = mtrr_ops[X86_VENDOR_CENTAUR];
+-                              size_or_mask = 0xfff00000;      /* 32 bits */
++                              size_or_mask = SIZE_OR_MASK_BITS(32);
+                               size_and_mask = 0;
+                       }
+                       break;
+               case X86_VENDOR_CYRIX:
+                       if (cpu_has_cyrix_arr) {
+                               mtrr_if = mtrr_ops[X86_VENDOR_CYRIX];
+-                              size_or_mask = 0xfff00000;      /* 32 bits */
++                              size_or_mask = SIZE_OR_MASK_BITS(32);
+                               size_and_mask = 0;
+                       }
+                       break;