summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChuck Ebbert <cebbert@redhat.com>2011-05-12 19:27:16 -0400
committerChuck Ebbert <cebbert@redhat.com>2011-05-12 19:27:16 -0400
commit52548dc13866e7fdd4b95f1abbc522d99758402f (patch)
tree10d2c79ca0b0808da5135af401e8ba3dd79e9015
parentd8616baf4a532cc414d3db9ec4dda4d62eee21ef (diff)
downloadkernel-52548dc13866e7fdd4b95f1abbc522d99758402f.tar.gz
kernel-52548dc13866e7fdd4b95f1abbc522d99758402f.tar.xz
kernel-52548dc13866e7fdd4b95f1abbc522d99758402f.zip
Fix yet another bug in AMD erratum checking (#704059)
-rw-r--r--kernel.spec7
-rw-r--r--x86-amd-fix-another-erratum-400-bug.patch70
2 files changed, 77 insertions, 0 deletions
diff --git a/kernel.spec b/kernel.spec
index 9a9a57360..3e743bc86 100644
--- a/kernel.spec
+++ b/kernel.spec
@@ -715,6 +715,8 @@ Patch12400: mm-slub-do-not-wake-kswapd-for-slubs-speculative-high-order-allocati
Patch12401: mm-slub-do-not-take-expensive-steps-for-slubs-speculative-high-order-allocations.patch
Patch12402: mm-slub-default-slub_max_order-to-0.patch
+Patch12500: x86-amd-fix-another-erratum-400-bug.patch
+
%endif
BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root
@@ -1325,6 +1327,8 @@ ApplyPatch mm-slub-do-not-wake-kswapd-for-slubs-speculative-high-order-allocatio
ApplyPatch mm-slub-do-not-take-expensive-steps-for-slubs-speculative-high-order-allocations.patch
ApplyPatch mm-slub-default-slub_max_order-to-0.patch
+ApplyPatch x86-amd-fix-another-erratum-400-bug.patch
+
# END OF PATCH APPLICATIONS
%endif
@@ -1933,6 +1937,9 @@ fi
# and build.
%changelog
+* Thu May 12 2011 Chuck Ebbert <cebbert@redhat.com>
+- Fix yet another bug in AMD erratum checking (#704059)
+
* Thu May 12 2011 Kyle McMartin <kmcmartin@redhat.com> 2.6.39-0.rc7.git3.0
- Switch on release builds until 2.6.39 releases and we branch off 2.6.40-git.
diff --git a/x86-amd-fix-another-erratum-400-bug.patch b/x86-amd-fix-another-erratum-400-bug.patch
new file mode 100644
index 000000000..f07e1a334
--- /dev/null
+++ b/x86-amd-fix-another-erratum-400-bug.patch
@@ -0,0 +1,70 @@
+Fix a bug that causes CPU hangs due to missing timer interrupts,
+introduced by these three patches:
+
+(1) commit d78d671db478eb8b14c78501c0cee1cc7baf6967
+ "x86, cpu: AMD errata checking framework"
+
+(2) commit 9d8888c2a214aece2494a49e699a097c2ba9498b
+ "x86, cpu: Clean up AMD erratum 400 workaround"
+
+(3) commit b87cf80af3ba4b4c008b4face3c68d604e1715c6
+ "x86, AMD: Set ARAT feature on AMD processors"
+
+Patch (1) introduced a new framework that allowed checking for errata
+using AMD's OSVW (OS visible workaround) feature combined with
+explicit lists of models. It checked OSVW first, and completely
+relied on that if it was present and usable.
+
+Patch (2) switched the checking for erratum 400 to use the new
+framework. But the original code checked for an explicit model range
+first, then used OSVW if the CPU was not within that range. Patch (1)
+also inexplicably added a second model range (for Family 10h) that
+was never in the original code.
+
+Then patch (3) used the new erratum 400 checks to decide whether
+to enable the ARAT feature (always running APIC timer.) However,
+this causes notebooks using the Sempron processor (Family 10h
+Model 6 Stepping 2) to enable ARAT when they shouldn't because the
+explicit check for that model gets skipped.
+
+The fix is to check the model list first, then use OSVW if the CPU
+is not in that list.
+
+Signed-off-by: Chuck Ebbert <cebbert@redhat.com>
+
+--- a/arch/x86/kernel/cpu/amd.c
++++ b/arch/x86/kernel/cpu/amd.c
+@@ -723,6 +723,17 @@ bool cpu_has_amd_erratum(const int *erra
+ if (cpu->x86_vendor != X86_VENDOR_AMD)
+ return false;
+
++ /*
++ * Must match family-model-stepping range first so that the
++ * range checks will override OSVW checking.
++ */
++ ms = (cpu->x86_model << 4) | cpu->x86_mask;
++ while ((range = *erratum++))
++ if ((cpu->x86 == AMD_MODEL_RANGE_FAMILY(range)) &&
++ (ms >= AMD_MODEL_RANGE_START(range)) &&
++ (ms <= AMD_MODEL_RANGE_END(range)))
++ return true;
++
+ if (osvw_id >= 0 && osvw_id < 65536 &&
+ cpu_has(cpu, X86_FEATURE_OSVW)) {
+ u64 osvw_len;
+@@ -737,15 +748,6 @@ bool cpu_has_amd_erratum(const int *erra
+ }
+ }
+
+- /* OSVW unavailable or ID unknown, match family-model-stepping range */
+- ms = (cpu->x86_model << 4) | cpu->x86_mask;
+- while ((range = *erratum++))
+- if ((cpu->x86 == AMD_MODEL_RANGE_FAMILY(range)) &&
+- (ms >= AMD_MODEL_RANGE_START(range)) &&
+- (ms <= AMD_MODEL_RANGE_END(range)))
+- return true;
+-
+ return false;
+ }
+-
+ EXPORT_SYMBOL_GPL(cpu_has_amd_erratum);