diff options
Diffstat (limited to 'arch/x86')
| -rw-r--r-- | arch/x86/include/asm/cpufeature.h | 1 | ||||
| -rw-r--r-- | arch/x86/include/asm/processor.h | 19 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/amd.c | 23 | ||||
| -rw-r--r-- | arch/x86/kernel/process.c | 2 |
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 | ||
| 977 | extern const int amd_erratum_400[]; | ||
| 978 | extern 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 | |||
| 992 | extern unsigned long arch_align_stack(unsigned long sp); | 973 | extern unsigned long arch_align_stack(unsigned long sp); |
| 993 | extern void free_init_pages(char *what, unsigned long begin, unsigned long end); | 974 | extern 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 | ||
| 516 | static const int amd_erratum_383[]; | 516 | static const int amd_erratum_383[]; |
| 517 | static const int amd_erratum_400[]; | ||
| 518 | static bool cpu_has_amd_erratum(const int *erratum); | ||
| 517 | 519 | ||
| 518 | static void __cpuinit init_amd(struct cpuinfo_x86 *c) | 520 | static 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 | ||
| 866 | const 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 | |||
| 878 | static 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)); |
| 869 | EXPORT_SYMBOL_GPL(amd_erratum_400); | ||
| 870 | 881 | ||
| 871 | static const int amd_erratum_383[] = | 882 | static 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 | ||
| 874 | bool cpu_has_amd_erratum(const int *erratum) | 885 | static 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 | |||
| 916 | EXPORT_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; |
