| From 7a0fc404ae663776e96db43879a0fa24fec1fa3a Mon Sep 17 00:00:00 2001 |
| From: H. Peter Anvin <hpa@linux.intel.com> |
| Date: Tue, 13 Apr 2010 14:40:54 -0700 |
| Subject: x86: Disable large pages on CPUs with Atom erratum AAE44 |
| |
| From: H. Peter Anvin <hpa@linux.intel.com> |
| |
| commit 7a0fc404ae663776e96db43879a0fa24fec1fa3a upstream. |
| |
| Atom erratum AAE44/AAF40/AAG38/AAH41: |
| |
| "If software clears the PS (page size) bit in a present PDE (page |
| directory entry), that will cause linear addresses mapped through this |
| PDE to use 4-KByte pages instead of using a large page after old TLB |
| entries are invalidated. Due to this erratum, if a code fetch uses |
| this PDE before the TLB entry for the large page is invalidated then |
| it may fetch from a different physical address than specified by |
| either the old large page translation or the new 4-KByte page |
| translation. This erratum may also cause speculative code fetches from |
| incorrect addresses." |
| |
| [http://download.intel.com/design/processor/specupdt/319536.pdf] |
| |
| Where as commit 211b3d03c7400f48a781977a50104c9d12f4e229 seems to |
| workaround errata AAH41 (mixed 4K TLBs) it reduces the window of |
| opportunity for the bug to occur and does not totally remove it. This |
| patch disables mixed 4K/4MB page tables totally avoiding the page |
| splitting and not tripping this processor issue. |
| |
| This is based on an original patch by Colin King. |
| |
| Originally-by: Colin Ian King <colin.king@canonical.com> |
| Cc: Colin Ian King <colin.king@canonical.com> |
| Cc: Ingo Molnar <mingo@elte.hu> |
| Signed-off-by: H. Peter Anvin <hpa@linux.intel.com> |
| LKML-Reference: <1269271251-19775-1-git-send-email-colin.king@canonical.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> |
| |
| --- |
| arch/x86/kernel/cpu/intel.c | 21 +++++++++++++++++++++ |
| 1 file changed, 21 insertions(+) |
| |
| --- a/arch/x86/kernel/cpu/intel.c |
| +++ b/arch/x86/kernel/cpu/intel.c |
| @@ -47,6 +47,27 @@ static void __cpuinit early_init_intel(s |
| (c->x86 == 0x6 && c->x86_model >= 0x0e)) |
| set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC); |
| |
| + /* |
| + * Atom erratum AAE44/AAF40/AAG38/AAH41: |
| + * |
| + * A race condition between speculative fetches and invalidating |
| + * a large page. This is worked around in microcode, but we |
| + * need the microcode to have already been loaded... so if it is |
| + * not, recommend a BIOS update and disable large pages. |
| + */ |
| + if (c->x86 == 6 && c->x86_model == 0x1c && c->x86_mask <= 2) { |
| + u32 ucode, junk; |
| + |
| + wrmsr(MSR_IA32_UCODE_REV, 0, 0); |
| + sync_core(); |
| + rdmsr(MSR_IA32_UCODE_REV, junk, ucode); |
| + |
| + if (ucode < 0x20e) { |
| + printk(KERN_WARNING "Atom PSE erratum detected, BIOS microcode update recommended\n"); |
| + clear_cpu_cap(c, X86_FEATURE_PSE); |
| + } |
| + } |
| + |
| #ifdef CONFIG_X86_64 |
| set_cpu_cap(c, X86_FEATURE_SYSENTER32); |
| #else |