aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/include/asm/cpufeature.h1
-rw-r--r--arch/x86/include/asm/processor.h19
-rw-r--r--arch/x86/kernel/cpu/amd.c23
-rw-r--r--arch/x86/kernel/process.c2
4 files changed, 18 insertions, 27 deletions
diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h
index 4cfb5c9f6029..272fdccda5d5 100644
--- a/arch/x86/include/asm/cpufeature.h
+++ b/arch/x86/include/asm/cpufeature.h
@@ -226,6 +226,7 @@
226#define X86_BUG_FDIV X86_BUG(1) /* FPU FDIV */ 226#define X86_BUG_FDIV X86_BUG(1) /* FPU FDIV */
227#define X86_BUG_COMA X86_BUG(2) /* Cyrix 6x86 coma */ 227#define X86_BUG_COMA X86_BUG(2) /* Cyrix 6x86 coma */
228#define X86_BUG_AMD_TLB_MMATCH X86_BUG(3) /* AMD Erratum 383 */ 228#define X86_BUG_AMD_TLB_MMATCH X86_BUG(3) /* AMD Erratum 383 */
229#define X86_BUG_AMD_APIC_C1E X86_BUG(4) /* AMD Erratum 400 */
229 230
230#if defined(__KERNEL__) && !defined(__ASSEMBLY__) 231#if defined(__KERNEL__) && !defined(__ASSEMBLY__)
231 232
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index e044ef35f91f..22224b3b43bb 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -970,25 +970,6 @@ unsigned long calc_aperfmperf_ratio(struct aperfmperf *old,
970 return ratio; 970 return ratio;
971} 971}
972 972
973/*
974 * AMD errata checking
975 */
976#ifdef CONFIG_CPU_SUP_AMD
977extern const int amd_erratum_400[];
978extern bool cpu_has_amd_erratum(const int *);
979
980#define AMD_LEGACY_ERRATUM(...) { -1, __VA_ARGS__, 0 }
981#define AMD_OSVW_ERRATUM(osvw_id, ...) { osvw_id, __VA_ARGS__, 0 }
982#define AMD_MODEL_RANGE(f, m_start, s_start, m_end, s_end) \
983 ((f << 24) | (m_start << 16) | (s_start << 12) | (m_end << 4) | (s_end))
984#define AMD_MODEL_RANGE_FAMILY(range) (((range) >> 24) & 0xff)
985#define AMD_MODEL_RANGE_START(range) (((range) >> 12) & 0xfff)
986#define AMD_MODEL_RANGE_END(range) ((range) & 0xfff)
987
988#else
989#define cpu_has_amd_erratum(x) (false)
990#endif /* CONFIG_CPU_SUP_AMD */
991
992extern unsigned long arch_align_stack(unsigned long sp); 973extern unsigned long arch_align_stack(unsigned long sp);
993extern void free_init_pages(char *what, unsigned long begin, unsigned long end); 974extern void free_init_pages(char *what, unsigned long begin, unsigned long end);
994 975
diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
index 85f84e13d2dd..9a2a71669c5d 100644
--- a/arch/x86/kernel/cpu/amd.c
+++ b/arch/x86/kernel/cpu/amd.c
@@ -514,6 +514,8 @@ static void __cpuinit early_init_amd(struct cpuinfo_x86 *c)
514} 514}
515 515
516static const int amd_erratum_383[]; 516static const int amd_erratum_383[];
517static const int amd_erratum_400[];
518static bool cpu_has_amd_erratum(const int *erratum);
517 519
518static void __cpuinit init_amd(struct cpuinfo_x86 *c) 520static void __cpuinit init_amd(struct cpuinfo_x86 *c)
519{ 521{
@@ -734,6 +736,9 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
734 set_cpu_bug(c, X86_BUG_AMD_TLB_MMATCH); 736 set_cpu_bug(c, X86_BUG_AMD_TLB_MMATCH);
735 } 737 }
736 738
739 if (cpu_has_amd_erratum(amd_erratum_400))
740 set_cpu_bug(c, X86_BUG_AMD_APIC_C1E);
741
737 rdmsr_safe(MSR_AMD64_PATCH_LEVEL, &c->microcode, &dummy); 742 rdmsr_safe(MSR_AMD64_PATCH_LEVEL, &c->microcode, &dummy);
738} 743}
739 744
@@ -852,8 +857,7 @@ cpu_dev_register(amd_cpu_dev);
852 * AMD_OSVW_ERRATUM() macros. The latter is intended for newer errata that 857 * AMD_OSVW_ERRATUM() macros. The latter is intended for newer errata that
853 * have an OSVW id assigned, which it takes as first argument. Both take a 858 * have an OSVW id assigned, which it takes as first argument. Both take a
854 * variable number of family-specific model-stepping ranges created by 859 * variable number of family-specific model-stepping ranges created by
855 * AMD_MODEL_RANGE(). Each erratum also has to be declared as extern const 860 * AMD_MODEL_RANGE().
856 * int[] in arch/x86/include/asm/processor.h.
857 * 861 *
858 * Example: 862 * Example:
859 * 863 *
@@ -863,15 +867,22 @@ cpu_dev_register(amd_cpu_dev);
863 * AMD_MODEL_RANGE(0x10, 0x9, 0x0, 0x9, 0x0)); 867 * AMD_MODEL_RANGE(0x10, 0x9, 0x0, 0x9, 0x0));
864 */ 868 */
865 869
866const int amd_erratum_400[] = 870#define AMD_LEGACY_ERRATUM(...) { -1, __VA_ARGS__, 0 }
871#define AMD_OSVW_ERRATUM(osvw_id, ...) { osvw_id, __VA_ARGS__, 0 }
872#define AMD_MODEL_RANGE(f, m_start, s_start, m_end, s_end) \
873 ((f << 24) | (m_start << 16) | (s_start << 12) | (m_end << 4) | (s_end))
874#define AMD_MODEL_RANGE_FAMILY(range) (((range) >> 24) & 0xff)
875#define AMD_MODEL_RANGE_START(range) (((range) >> 12) & 0xfff)
876#define AMD_MODEL_RANGE_END(range) ((range) & 0xfff)
877
878static const int amd_erratum_400[] =
867 AMD_OSVW_ERRATUM(1, AMD_MODEL_RANGE(0xf, 0x41, 0x2, 0xff, 0xf), 879 AMD_OSVW_ERRATUM(1, AMD_MODEL_RANGE(0xf, 0x41, 0x2, 0xff, 0xf),
868 AMD_MODEL_RANGE(0x10, 0x2, 0x1, 0xff, 0xf)); 880 AMD_MODEL_RANGE(0x10, 0x2, 0x1, 0xff, 0xf));
869EXPORT_SYMBOL_GPL(amd_erratum_400);
870 881
871static const int amd_erratum_383[] = 882static const int amd_erratum_383[] =
872 AMD_OSVW_ERRATUM(3, AMD_MODEL_RANGE(0x10, 0, 0, 0xff, 0xf)); 883 AMD_OSVW_ERRATUM(3, AMD_MODEL_RANGE(0x10, 0, 0, 0xff, 0xf));
873 884
874bool cpu_has_amd_erratum(const int *erratum) 885static bool cpu_has_amd_erratum(const int *erratum)
875{ 886{
876 struct cpuinfo_x86 *cpu = __this_cpu_ptr(&cpu_info); 887 struct cpuinfo_x86 *cpu = __this_cpu_ptr(&cpu_info);
877 int osvw_id = *erratum++; 888 int osvw_id = *erratum++;
@@ -912,5 +923,3 @@ bool cpu_has_amd_erratum(const int *erratum)
912 923
913 return false; 924 return false;
914} 925}
915
916EXPORT_SYMBOL_GPL(cpu_has_amd_erratum);
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
index 14ae10031ff0..e718f150c880 100644
--- a/arch/x86/kernel/process.c
+++ b/arch/x86/kernel/process.c
@@ -495,7 +495,7 @@ void __cpuinit select_idle_routine(const struct cpuinfo_x86 *c)
495 if (x86_idle) 495 if (x86_idle)
496 return; 496 return;
497 497
498 if (cpu_has_amd_erratum(amd_erratum_400)) { 498 if (cpu_has_bug(c, X86_BUG_AMD_APIC_C1E)) {
499 /* E400: APIC timer interrupt does not wake up CPU from C1e */ 499 /* E400: APIC timer interrupt does not wake up CPU from C1e */
500 pr_info("using AMD E400 aware idle routine\n"); 500 pr_info("using AMD E400 aware idle routine\n");
501 x86_idle = amd_e400_idle; 501 x86_idle = amd_e400_idle;