Fix yet another bug in AMD erratum checking (#704059)

This commit is contained in:
Chuck Ebbert 2011-05-12 19:27:16 -04:00
parent d8616baf4a
commit 52548dc138
2 changed files with 77 additions and 0 deletions

View File

@ -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 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 Patch12402: mm-slub-default-slub_max_order-to-0.patch
Patch12500: x86-amd-fix-another-erratum-400-bug.patch
%endif %endif
BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root 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-do-not-take-expensive-steps-for-slubs-speculative-high-order-allocations.patch
ApplyPatch mm-slub-default-slub_max_order-to-0.patch ApplyPatch mm-slub-default-slub_max_order-to-0.patch
ApplyPatch x86-amd-fix-another-erratum-400-bug.patch
# END OF PATCH APPLICATIONS # END OF PATCH APPLICATIONS
%endif %endif
@ -1933,6 +1937,9 @@ fi
# and build. # and build.
%changelog %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 * 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. - Switch on release builds until 2.6.39 releases and we branch off 2.6.40-git.

View File

@ -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);