aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2016-12-09 13:29:09 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-01-19 14:18:01 -0500
commitbd7e769457f964b0bb857e599fb0a914e0c05a3a (patch)
tree9c280a0bf4f1a1ee7403b4f4e70d668b9182139e
parente2d9ad2c540bf15958812189700a812110b452bf (diff)
x86/bugs: Separate AMD E400 erratum and C1E bug
commit 3344ed30791af66dbbad5f375008f3d1863b6c99 upstream. The workaround for the AMD Erratum E400 (Local APIC timer stops in C1E state) is a two step process: - Selection of the E400 aware idle routine - Detection whether the platform is affected The idle routine selection happens for possibly affected CPUs depending on family/model/stepping information. These range of CPUs is not necessarily affected as the decision whether to enable the C1E feature is made by the firmware. Unfortunately there is no way to query this at early boot. The current implementation polls a MSR in the E400 aware idle routine to detect whether the CPU is affected. This is inefficient on non affected CPUs because every idle entry has to do the MSR read. There is a better way to detect this before going idle for the first time which requires to seperate the bug flags: X86_BUG_AMD_E400 - Selects the E400 aware idle routine and enables the detection X86_BUG_AMD_APIC_C1E - Set when the platform is affected by E400 Replace the current X86_BUG_AMD_APIC_C1E usage by the new X86_BUG_AMD_E400 bug bit to select the idle routine which currently does an unconditional detection poll. X86_BUG_AMD_APIC_C1E is going to be used in later patches to remove the MSR polling and simplify the handling of this misfeature. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Borislav Petkov <bp@suse.de> Cc: Jiri Olsa <jolsa@redhat.com> Link: http://lkml.kernel.org/r/20161209182912.2726-3-bp@alien8.de Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--arch/x86/include/asm/cpufeatures.h2
-rw-r--r--arch/x86/kernel/cpu/amd.c20
-rw-r--r--arch/x86/kernel/process.c3
3 files changed, 16 insertions, 9 deletions
diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h
index a39629206864..ed10b5bf9b93 100644
--- a/arch/x86/include/asm/cpufeatures.h
+++ b/arch/x86/include/asm/cpufeatures.h
@@ -311,4 +311,6 @@
311#define X86_BUG_NULL_SEG X86_BUG(10) /* Nulling a selector preserves the base */ 311#define X86_BUG_NULL_SEG X86_BUG(10) /* Nulling a selector preserves the base */
312#define X86_BUG_SWAPGS_FENCE X86_BUG(11) /* SWAPGS without input dep on GS */ 312#define X86_BUG_SWAPGS_FENCE X86_BUG(11) /* SWAPGS without input dep on GS */
313#define X86_BUG_MONITOR X86_BUG(12) /* IPI required to wake up remote CPU */ 313#define X86_BUG_MONITOR X86_BUG(12) /* IPI required to wake up remote CPU */
314#define X86_BUG_AMD_E400 X86_BUG(13) /* CPU is among the affected by Erratum 400 */
315
314#endif /* _ASM_X86_CPUFEATURES_H */ 316#endif /* _ASM_X86_CPUFEATURES_H */
diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
index 4daad1e39352..71cae73a5076 100644
--- a/arch/x86/kernel/cpu/amd.c
+++ b/arch/x86/kernel/cpu/amd.c
@@ -20,6 +20,10 @@
20 20
21#include "cpu.h" 21#include "cpu.h"
22 22
23static const int amd_erratum_383[];
24static const int amd_erratum_400[];
25static bool cpu_has_amd_erratum(struct cpuinfo_x86 *cpu, const int *erratum);
26
23/* 27/*
24 * nodes_per_socket: Stores the number of nodes per socket. 28 * nodes_per_socket: Stores the number of nodes per socket.
25 * Refer to Fam15h Models 00-0fh BKDG - CPUID Fn8000_001E_ECX 29 * Refer to Fam15h Models 00-0fh BKDG - CPUID Fn8000_001E_ECX
@@ -592,11 +596,16 @@ static void early_init_amd(struct cpuinfo_x86 *c)
592 /* F16h erratum 793, CVE-2013-6885 */ 596 /* F16h erratum 793, CVE-2013-6885 */
593 if (c->x86 == 0x16 && c->x86_model <= 0xf) 597 if (c->x86 == 0x16 && c->x86_model <= 0xf)
594 msr_set_bit(MSR_AMD64_LS_CFG, 15); 598 msr_set_bit(MSR_AMD64_LS_CFG, 15);
595}
596 599
597static const int amd_erratum_383[]; 600 /*
598static const int amd_erratum_400[]; 601 * Check whether the machine is affected by erratum 400. This is
599static bool cpu_has_amd_erratum(struct cpuinfo_x86 *cpu, const int *erratum); 602 * used to select the proper idle routine and to enable the check
603 * whether the machine is affected in arch_post_acpi_init(), which
604 * sets the X86_BUG_AMD_APIC_C1E bug depending on the MSR check.
605 */
606 if (cpu_has_amd_erratum(c, amd_erratum_400))
607 set_cpu_bug(c, X86_BUG_AMD_E400);
608}
600 609
601static void init_amd_k8(struct cpuinfo_x86 *c) 610static void init_amd_k8(struct cpuinfo_x86 *c)
602{ 611{
@@ -777,9 +786,6 @@ static void init_amd(struct cpuinfo_x86 *c)
777 if (c->x86 > 0x11) 786 if (c->x86 > 0x11)
778 set_cpu_cap(c, X86_FEATURE_ARAT); 787 set_cpu_cap(c, X86_FEATURE_ARAT);
779 788
780 if (cpu_has_amd_erratum(c, amd_erratum_400))
781 set_cpu_bug(c, X86_BUG_AMD_APIC_C1E);
782
783 rdmsr_safe(MSR_AMD64_PATCH_LEVEL, &c->microcode, &dummy); 789 rdmsr_safe(MSR_AMD64_PATCH_LEVEL, &c->microcode, &dummy);
784 790
785 /* 3DNow or LM implies PREFETCHW */ 791 /* 3DNow or LM implies PREFETCHW */
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
index 0888a879120f..8e10e72bf6ee 100644
--- a/arch/x86/kernel/process.c
+++ b/arch/x86/kernel/process.c
@@ -448,8 +448,7 @@ void select_idle_routine(const struct cpuinfo_x86 *c)
448 if (x86_idle || boot_option_idle_override == IDLE_POLL) 448 if (x86_idle || boot_option_idle_override == IDLE_POLL)
449 return; 449 return;
450 450
451 if (cpu_has_bug(c, X86_BUG_AMD_APIC_C1E)) { 451 if (boot_cpu_has_bug(X86_BUG_AMD_E400)) {
452 /* E400: APIC timer interrupt does not wake up CPU from C1e */
453 pr_info("using AMD E400 aware idle routine\n"); 452 pr_info("using AMD E400 aware idle routine\n");
454 x86_idle = amd_e400_idle; 453 x86_idle = amd_e400_idle;
455 } else if (prefer_mwait_c1_over_halt(c)) { 454 } else if (prefer_mwait_c1_over_halt(c)) {