From 52548dc13866e7fdd4b95f1abbc522d99758402f Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Thu, 12 May 2011 19:27:16 -0400 Subject: [PATCH] Fix yet another bug in AMD erratum checking (#704059) --- kernel.spec | 7 +++ x86-amd-fix-another-erratum-400-bug.patch | 70 +++++++++++++++++++++++ 2 files changed, 77 insertions(+) create mode 100644 x86-amd-fix-another-erratum-400-bug.patch 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 +- Fix yet another bug in AMD erratum checking (#704059) + * Thu May 12 2011 Kyle McMartin 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 + +--- 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);