From 65fc985b37dc241c4db7cd32adcbc989193fe3c8 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Wed, 20 Mar 2013 15:07:23 +0100 Subject: [PATCH 1/9] x86, cpu: Expand cpufeature facility to include cpu bugs We add another 32-bit vector at the end of the ->x86_capability bitvector which collects bugs present in CPUs. After all, a CPU bug is a kind of a capability, albeit a strange one. Signed-off-by: Borislav Petkov Link: http://lkml.kernel.org/r/1363788448-31325-2-git-send-email-bp@alien8.de Signed-off-by: H. Peter Anvin --- arch/x86/include/asm/cpufeature.h | 13 +++++++++++++ arch/x86/include/asm/processor.h | 2 +- arch/x86/kernel/alternative.c | 2 +- arch/x86/kernel/cpu/common.c | 4 ++++ 4 files changed, 19 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index 93fe929d1cee..16190abd8905 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h @@ -9,6 +9,7 @@ #endif #define NCAPINTS 10 /* N 32-bit words worth of info */ +#define NBUGINTS 1 /* N 32-bit bug flags */ /* * Note: If the comment begins with a quoted string, that string is used @@ -216,6 +217,11 @@ #define X86_FEATURE_ADX (9*32+19) /* The ADCX and ADOX instructions */ #define X86_FEATURE_SMAP (9*32+20) /* Supervisor Mode Access Prevention */ +/* + * BUG word(s) + */ +#define X86_BUG(x) (NCAPINTS*32 + (x)) + #if defined(__KERNEL__) && !defined(__ASSEMBLY__) #include @@ -401,6 +407,13 @@ static __always_inline __pure bool __static_cpu_has(u16 bit) #define static_cpu_has(bit) boot_cpu_has(bit) #endif +#define cpu_has_bug(c, bit) cpu_has(c, (bit)) +#define set_cpu_bug(c, bit) set_cpu_cap(c, (bit)) +#define clear_cpu_bug(c, bit) clear_cpu_cap(c, (bit)); + +#define static_cpu_has_bug(bit) static_cpu_has((bit)) +#define boot_cpu_has_bug(bit) cpu_has_bug(&boot_cpu_data, (bit)) + #endif /* defined(__KERNEL__) && !defined(__ASSEMBLY__) */ #endif /* _ASM_X86_CPUFEATURE_H */ diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index 3270116b1488..23c8081d3870 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -107,7 +107,7 @@ struct cpuinfo_x86 { __u32 extended_cpuid_level; /* Maximum supported CPUID level, -1=no CPUID: */ int cpuid_level; - __u32 x86_capability[NCAPINTS]; + __u32 x86_capability[NCAPINTS + NBUGINTS]; char x86_vendor_id[16]; char x86_model_id[64]; /* in KB - valid for CPUS which support this call: */ diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c index ef5ccca79a6c..c15cf9a25e27 100644 --- a/arch/x86/kernel/alternative.c +++ b/arch/x86/kernel/alternative.c @@ -271,7 +271,7 @@ void __init_or_module apply_alternatives(struct alt_instr *start, replacement = (u8 *)&a->repl_offset + a->repl_offset; BUG_ON(a->replacementlen > a->instrlen); BUG_ON(a->instrlen > sizeof(insnbuf)); - BUG_ON(a->cpuid >= NCAPINTS*32); + BUG_ON(a->cpuid >= (NCAPINTS + NBUGINTS) * 32); if (!boot_cpu_has(a->cpuid)) continue; diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index d814772c5bed..22018f70a671 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -920,6 +920,10 @@ static void __cpuinit identify_cpu(struct cpuinfo_x86 *c) /* AND the already accumulated flags with these */ for (i = 0; i < NCAPINTS; i++) boot_cpu_data.x86_capability[i] &= c->x86_capability[i]; + + /* OR, i.e. replicate the bug flags */ + for (i = NCAPINTS; i < NCAPINTS + NBUGINTS; i++) + c->x86_capability[i] |= boot_cpu_data.x86_capability[i]; } /* Init Machine Check Exception if available. */ From e2604b49e8a8827e8bc5b61bc0c5a889e028fdad Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Wed, 20 Mar 2013 15:07:24 +0100 Subject: [PATCH 2/9] x86, cpu: Convert F00F bug detection ... to using the new facility and drop the cpuinfo_x86 member. Signed-off-by: Borislav Petkov Link: http://lkml.kernel.org/r/1363788448-31325-3-git-send-email-bp@alien8.de Signed-off-by: H. Peter Anvin --- arch/x86/include/asm/cpufeature.h | 2 ++ arch/x86/include/asm/processor.h | 1 - arch/x86/kernel/cpu/intel.c | 4 ++-- arch/x86/kernel/cpu/proc.c | 2 +- arch/x86/mm/fault.c | 2 +- 5 files changed, 6 insertions(+), 5 deletions(-) diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index 16190abd8905..c0ad7e75815c 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h @@ -222,6 +222,8 @@ */ #define X86_BUG(x) (NCAPINTS*32 + (x)) +#define X86_BUG_F00F X86_BUG(0) /* Intel F00F */ + #if defined(__KERNEL__) && !defined(__ASSEMBLY__) #include diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index 23c8081d3870..1e55e2d543b5 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -92,7 +92,6 @@ struct cpuinfo_x86 { char hard_math; char rfu; char fdiv_bug; - char f00f_bug; char coma_bug; char pad0; #else diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c index 1905ce98bee0..1acdd42d86d1 100644 --- a/arch/x86/kernel/cpu/intel.c +++ b/arch/x86/kernel/cpu/intel.c @@ -209,11 +209,11 @@ static void __cpuinit intel_workarounds(struct cpuinfo_x86 *c) * system. * Note that the workaround only should be initialized once... */ - c->f00f_bug = 0; + clear_cpu_bug(c, X86_BUG_F00F); if (!paravirt_enabled() && c->x86 == 5) { static int f00f_workaround_enabled; - c->f00f_bug = 1; + set_cpu_bug(c, X86_BUG_F00F); if (!f00f_workaround_enabled) { trap_init_f00f_bug(); printk(KERN_NOTICE "Intel Pentium with F0 0F bug - workaround enabled.\n"); diff --git a/arch/x86/kernel/cpu/proc.c b/arch/x86/kernel/cpu/proc.c index e280253f6f94..2d60b2bec01c 100644 --- a/arch/x86/kernel/cpu/proc.c +++ b/arch/x86/kernel/cpu/proc.c @@ -35,7 +35,7 @@ static void show_cpuinfo_misc(struct seq_file *m, struct cpuinfo_x86 *c) "cpuid level\t: %d\n" "wp\t\t: %s\n", c->fdiv_bug ? "yes" : "no", - c->f00f_bug ? "yes" : "no", + static_cpu_has_bug(X86_BUG_F00F) ? "yes" : "no", c->coma_bug ? "yes" : "no", c->hard_math ? "yes" : "no", c->hard_math ? "yes" : "no", diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index 2b97525246d4..a1ce1facbacc 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c @@ -555,7 +555,7 @@ static int is_f00f_bug(struct pt_regs *regs, unsigned long address) /* * Pentium F0 0F C7 C8 bug workaround: */ - if (boot_cpu_data.f00f_bug) { + if (boot_cpu_has_bug(X86_BUG_F00F)) { nr = (address - idt_descr.address) >> 3; if (nr == 6) { From 93a829e8e2c292f1d30155f64803101ca1cb7d3d Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Wed, 20 Mar 2013 15:07:25 +0100 Subject: [PATCH 3/9] x86, cpu: Convert FDIV bug detection ... to the new facility. Add a reference to the wikipedia article explaining the FDIV test we're doing here. Signed-off-by: Borislav Petkov Link: http://lkml.kernel.org/r/1363788448-31325-4-git-send-email-bp@alien8.de Signed-off-by: H. Peter Anvin --- arch/x86/include/asm/cpufeature.h | 1 + arch/x86/include/asm/processor.h | 1 - arch/x86/kernel/cpu/bugs.c | 7 ++++--- arch/x86/kernel/cpu/proc.c | 2 +- arch/x86/kernel/setup.c | 2 -- 5 files changed, 6 insertions(+), 7 deletions(-) diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index c0ad7e75815c..25eb9488a9a5 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h @@ -223,6 +223,7 @@ #define X86_BUG(x) (NCAPINTS*32 + (x)) #define X86_BUG_F00F X86_BUG(0) /* Intel F00F */ +#define X86_BUG_FDIV X86_BUG(1) /* FPU FDIV */ #if defined(__KERNEL__) && !defined(__ASSEMBLY__) diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index 1e55e2d543b5..ea22dfaf6c5e 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -91,7 +91,6 @@ struct cpuinfo_x86 { /* Problems on some 486Dx4's and old 386's: */ char hard_math; char rfu; - char fdiv_bug; char coma_bug; char pad0; #else diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c index af6455e3fcc9..c59635ecbbb8 100644 --- a/arch/x86/kernel/cpu/bugs.c +++ b/arch/x86/kernel/cpu/bugs.c @@ -59,7 +59,7 @@ static void __init check_fpu(void) * trap_init() enabled FXSR and company _before_ testing for FP * problems here. * - * Test for the divl bug.. + * Test for the divl bug: http://en.wikipedia.org/wiki/Fdiv_bug */ __asm__("fninit\n\t" "fldl %1\n\t" @@ -75,9 +75,10 @@ static void __init check_fpu(void) kernel_fpu_end(); - boot_cpu_data.fdiv_bug = fdiv_bug; - if (boot_cpu_data.fdiv_bug) + if (fdiv_bug) { + set_cpu_bug(&boot_cpu_data, X86_BUG_FDIV); pr_warn("Hmm, FPU with FDIV bug\n"); + } } /* diff --git a/arch/x86/kernel/cpu/proc.c b/arch/x86/kernel/cpu/proc.c index 2d60b2bec01c..5dfb6c65138f 100644 --- a/arch/x86/kernel/cpu/proc.c +++ b/arch/x86/kernel/cpu/proc.c @@ -34,7 +34,7 @@ static void show_cpuinfo_misc(struct seq_file *m, struct cpuinfo_x86 *c) "fpu_exception\t: %s\n" "cpuid level\t: %d\n" "wp\t\t: %s\n", - c->fdiv_bug ? "yes" : "no", + static_cpu_has_bug(X86_BUG_FDIV) ? "yes" : "no", static_cpu_has_bug(X86_BUG_F00F) ? "yes" : "no", c->coma_bug ? "yes" : "no", c->hard_math ? "yes" : "no", diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 90d8cc930f5e..29258c75a2f3 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -173,12 +173,10 @@ static struct resource bss_resource = { /* cpu data as detected by the assembly code in head.S */ struct cpuinfo_x86 new_cpu_data __cpuinitdata = { .wp_works_ok = -1, - .fdiv_bug = -1, }; /* common cpu data for all cpus */ struct cpuinfo_x86 boot_cpu_data __read_mostly = { .wp_works_ok = -1, - .fdiv_bug = -1, }; EXPORT_SYMBOL(boot_cpu_data); From c5b41a67505cc3c9744d8f105c63a3bf3c443a01 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Wed, 20 Mar 2013 15:07:26 +0100 Subject: [PATCH 4/9] x86, cpu: Convert Cyrix coma bug detection ... to the new facility. Signed-off-by: Borislav Petkov Link: http://lkml.kernel.org/r/1363788448-31325-5-git-send-email-bp@alien8.de Signed-off-by: H. Peter Anvin --- arch/x86/include/asm/cpufeature.h | 1 + arch/x86/include/asm/processor.h | 1 - arch/x86/kernel/cpu/cyrix.c | 5 +++-- arch/x86/kernel/cpu/proc.c | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index 25eb9488a9a5..a2b65c11081e 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h @@ -224,6 +224,7 @@ #define X86_BUG_F00F X86_BUG(0) /* Intel F00F */ #define X86_BUG_FDIV X86_BUG(1) /* FPU FDIV */ +#define X86_BUG_COMA X86_BUG(2) /* Cyrix 6x86 coma */ #if defined(__KERNEL__) && !defined(__ASSEMBLY__) diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index ea22dfaf6c5e..4e2fa2859e39 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -91,7 +91,6 @@ struct cpuinfo_x86 { /* Problems on some 486Dx4's and old 386's: */ char hard_math; char rfu; - char coma_bug; char pad0; #else /* Number of 4K pages in DTLB/ITLB combined(in pages): */ diff --git a/arch/x86/kernel/cpu/cyrix.c b/arch/x86/kernel/cpu/cyrix.c index 4fbd384fb645..d048d5ca43c1 100644 --- a/arch/x86/kernel/cpu/cyrix.c +++ b/arch/x86/kernel/cpu/cyrix.c @@ -249,7 +249,7 @@ static void __cpuinit init_cyrix(struct cpuinfo_x86 *c) /* Emulate MTRRs using Cyrix's ARRs. */ set_cpu_cap(c, X86_FEATURE_CYRIX_ARR); /* 6x86's contain this bug */ - c->coma_bug = 1; + set_cpu_bug(c, X86_BUG_COMA); break; case 4: /* MediaGX/GXm or Geode GXM/GXLV/GX1 */ @@ -317,7 +317,8 @@ static void __cpuinit init_cyrix(struct cpuinfo_x86 *c) /* Enable MMX extensions (App note 108) */ setCx86_old(CX86_CCR7, getCx86_old(CX86_CCR7)|1); } else { - c->coma_bug = 1; /* 6x86MX, it has the bug. */ + /* A 6x86MX - it has the bug. */ + set_cpu_bug(c, X86_BUG_COMA); } tmp = (!(dir0_lsn & 7) || dir0_lsn & 1) ? 2 : 0; Cx86_cb[tmp] = cyrix_model_mult2[dir0_lsn & 7]; diff --git a/arch/x86/kernel/cpu/proc.c b/arch/x86/kernel/cpu/proc.c index 5dfb6c65138f..37a198bd48c8 100644 --- a/arch/x86/kernel/cpu/proc.c +++ b/arch/x86/kernel/cpu/proc.c @@ -36,7 +36,7 @@ static void show_cpuinfo_misc(struct seq_file *m, struct cpuinfo_x86 *c) "wp\t\t: %s\n", static_cpu_has_bug(X86_BUG_FDIV) ? "yes" : "no", static_cpu_has_bug(X86_BUG_F00F) ? "yes" : "no", - c->coma_bug ? "yes" : "no", + static_cpu_has_bug(X86_BUG_COMA) ? "yes" : "no", c->hard_math ? "yes" : "no", c->hard_math ? "yes" : "no", c->cpuid_level, From e6ee94d58dfd06ec64c55f91581f00d4f98bf1f6 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Wed, 20 Mar 2013 15:07:27 +0100 Subject: [PATCH 5/9] x86, cpu: Convert AMD Erratum 383 Convert the AMD erratum 383 testing code to the bug infrastructure. This allows keeping the AMD-specific erratum testing machinery private to amd.c and not export symbols to modules needlessly. Signed-off-by: Borislav Petkov Link: http://lkml.kernel.org/r/1363788448-31325-6-git-send-email-bp@alien8.de Signed-off-by: H. Peter Anvin --- arch/x86/include/asm/cpufeature.h | 1 + arch/x86/include/asm/processor.h | 1 - arch/x86/kernel/cpu/amd.c | 8 ++++++-- arch/x86/kvm/svm.c | 2 +- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index a2b65c11081e..4cfb5c9f6029 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h @@ -225,6 +225,7 @@ #define X86_BUG_F00F X86_BUG(0) /* Intel F00F */ #define X86_BUG_FDIV X86_BUG(1) /* FPU FDIV */ #define X86_BUG_COMA X86_BUG(2) /* Cyrix 6x86 coma */ +#define X86_BUG_AMD_TLB_MMATCH X86_BUG(3) /* AMD Erratum 383 */ #if defined(__KERNEL__) && !defined(__ASSEMBLY__) diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index 4e2fa2859e39..e044ef35f91f 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -974,7 +974,6 @@ unsigned long calc_aperfmperf_ratio(struct aperfmperf *old, * AMD errata checking */ #ifdef CONFIG_CPU_SUP_AMD -extern const int amd_erratum_383[]; extern const int amd_erratum_400[]; extern bool cpu_has_amd_erratum(const int *); diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index fa96eb0d02fb..85f84e13d2dd 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c @@ -513,6 +513,8 @@ static void __cpuinit early_init_amd(struct cpuinfo_x86 *c) #endif } +static const int amd_erratum_383[]; + static void __cpuinit init_amd(struct cpuinfo_x86 *c) { u32 dummy; @@ -727,6 +729,9 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c) rdmsrl_safe(MSR_AMD64_BU_CFG2, &value); value &= ~(1ULL << 24); wrmsrl_safe(MSR_AMD64_BU_CFG2, value); + + if (cpu_has_amd_erratum(amd_erratum_383)) + set_cpu_bug(c, X86_BUG_AMD_TLB_MMATCH); } rdmsr_safe(MSR_AMD64_PATCH_LEVEL, &c->microcode, &dummy); @@ -863,9 +868,8 @@ const int amd_erratum_400[] = AMD_MODEL_RANGE(0x10, 0x2, 0x1, 0xff, 0xf)); EXPORT_SYMBOL_GPL(amd_erratum_400); -const int amd_erratum_383[] = +static const int amd_erratum_383[] = AMD_OSVW_ERRATUM(3, AMD_MODEL_RANGE(0x10, 0, 0, 0xff, 0xf)); -EXPORT_SYMBOL_GPL(amd_erratum_383); bool cpu_has_amd_erratum(const int *erratum) { diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index e1b1ce21bc00..7d39d70647e3 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -555,7 +555,7 @@ static void svm_init_erratum_383(void) int err; u64 val; - if (!cpu_has_amd_erratum(amd_erratum_383)) + if (!static_cpu_has_bug(X86_BUG_AMD_TLB_MMATCH)) return; /* Use _safe variants to not break nested virtualization */ From 7d7dc116e56c8a1ba4beb36d06a77a48fe5f750b Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Wed, 20 Mar 2013 15:07:28 +0100 Subject: [PATCH 6/9] x86, cpu: Convert AMD Erratum 400 Convert AMD erratum 400 to the bug infrastructure. Then, retract all exports for modules since they're not needed now and make the AMD erratum checking machinery local to amd.c. Use forward declarations to avoid shuffling too much code around needlessly. Signed-off-by: Borislav Petkov Link: http://lkml.kernel.org/r/1363788448-31325-7-git-send-email-bp@alien8.de Signed-off-by: H. Peter Anvin --- arch/x86/include/asm/cpufeature.h | 1 + arch/x86/include/asm/processor.h | 19 ------------------- arch/x86/kernel/cpu/amd.c | 23 ++++++++++++++++------- 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 @@ #define X86_BUG_FDIV X86_BUG(1) /* FPU FDIV */ #define X86_BUG_COMA X86_BUG(2) /* Cyrix 6x86 coma */ #define X86_BUG_AMD_TLB_MMATCH X86_BUG(3) /* AMD Erratum 383 */ +#define X86_BUG_AMD_APIC_C1E X86_BUG(4) /* AMD Erratum 400 */ #if defined(__KERNEL__) && !defined(__ASSEMBLY__) 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, return ratio; } -/* - * AMD errata checking - */ -#ifdef CONFIG_CPU_SUP_AMD -extern const int amd_erratum_400[]; -extern bool cpu_has_amd_erratum(const int *); - -#define AMD_LEGACY_ERRATUM(...) { -1, __VA_ARGS__, 0 } -#define AMD_OSVW_ERRATUM(osvw_id, ...) { osvw_id, __VA_ARGS__, 0 } -#define AMD_MODEL_RANGE(f, m_start, s_start, m_end, s_end) \ - ((f << 24) | (m_start << 16) | (s_start << 12) | (m_end << 4) | (s_end)) -#define AMD_MODEL_RANGE_FAMILY(range) (((range) >> 24) & 0xff) -#define AMD_MODEL_RANGE_START(range) (((range) >> 12) & 0xfff) -#define AMD_MODEL_RANGE_END(range) ((range) & 0xfff) - -#else -#define cpu_has_amd_erratum(x) (false) -#endif /* CONFIG_CPU_SUP_AMD */ - extern unsigned long arch_align_stack(unsigned long sp); extern void free_init_pages(char *what, unsigned long begin, unsigned long end); 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) } static const int amd_erratum_383[]; +static const int amd_erratum_400[]; +static bool cpu_has_amd_erratum(const int *erratum); static void __cpuinit init_amd(struct cpuinfo_x86 *c) { @@ -734,6 +736,9 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c) set_cpu_bug(c, X86_BUG_AMD_TLB_MMATCH); } + if (cpu_has_amd_erratum(amd_erratum_400)) + set_cpu_bug(c, X86_BUG_AMD_APIC_C1E); + rdmsr_safe(MSR_AMD64_PATCH_LEVEL, &c->microcode, &dummy); } @@ -852,8 +857,7 @@ cpu_dev_register(amd_cpu_dev); * AMD_OSVW_ERRATUM() macros. The latter is intended for newer errata that * have an OSVW id assigned, which it takes as first argument. Both take a * variable number of family-specific model-stepping ranges created by - * AMD_MODEL_RANGE(). Each erratum also has to be declared as extern const - * int[] in arch/x86/include/asm/processor.h. + * AMD_MODEL_RANGE(). * * Example: * @@ -863,15 +867,22 @@ cpu_dev_register(amd_cpu_dev); * AMD_MODEL_RANGE(0x10, 0x9, 0x0, 0x9, 0x0)); */ -const int amd_erratum_400[] = +#define AMD_LEGACY_ERRATUM(...) { -1, __VA_ARGS__, 0 } +#define AMD_OSVW_ERRATUM(osvw_id, ...) { osvw_id, __VA_ARGS__, 0 } +#define AMD_MODEL_RANGE(f, m_start, s_start, m_end, s_end) \ + ((f << 24) | (m_start << 16) | (s_start << 12) | (m_end << 4) | (s_end)) +#define AMD_MODEL_RANGE_FAMILY(range) (((range) >> 24) & 0xff) +#define AMD_MODEL_RANGE_START(range) (((range) >> 12) & 0xfff) +#define AMD_MODEL_RANGE_END(range) ((range) & 0xfff) + +static const int amd_erratum_400[] = AMD_OSVW_ERRATUM(1, AMD_MODEL_RANGE(0xf, 0x41, 0x2, 0xff, 0xf), AMD_MODEL_RANGE(0x10, 0x2, 0x1, 0xff, 0xf)); -EXPORT_SYMBOL_GPL(amd_erratum_400); static const int amd_erratum_383[] = AMD_OSVW_ERRATUM(3, AMD_MODEL_RANGE(0x10, 0, 0, 0xff, 0xf)); -bool cpu_has_amd_erratum(const int *erratum) +static bool cpu_has_amd_erratum(const int *erratum) { struct cpuinfo_x86 *cpu = __this_cpu_ptr(&cpu_info); int osvw_id = *erratum++; @@ -912,5 +923,3 @@ bool cpu_has_amd_erratum(const int *erratum) return false; } - -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) if (x86_idle) return; - if (cpu_has_amd_erratum(amd_erratum_400)) { + if (cpu_has_bug(c, X86_BUG_AMD_APIC_C1E)) { /* E400: APIC timer interrupt does not wake up CPU from C1e */ pr_info("using AMD E400 aware idle routine\n"); x86_idle = amd_e400_idle; From 55a36b65ee7107d6bb557c96fd202c4e90164542 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Mon, 8 Apr 2013 17:57:44 +0200 Subject: [PATCH 7/9] x86: Fold-in trivial check_config function Fold it into its single call site. No functionality change. Signed-off-by: Borislav Petkov Link: http://lkml.kernel.org/r/1365436666-9837-3-git-send-email-bp@alien8.de Signed-off-by: H. Peter Anvin --- arch/x86/kernel/cpu/bugs.c | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c index c59635ecbbb8..4112be9a4659 100644 --- a/arch/x86/kernel/cpu/bugs.c +++ b/arch/x86/kernel/cpu/bugs.c @@ -81,21 +81,6 @@ static void __init check_fpu(void) } } -/* - * Check whether we are able to run this kernel safely on SMP. - * - * - i386 is no longer supported. - * - In order to run on anything without a TSC, we need to be - * compiled for a i486. - */ - -static void __init check_config(void) -{ - if (boot_cpu_data.x86 < 4) - panic("Kernel requires i486+ for 'invlpg' and other features"); -} - - void __init check_bugs(void) { identify_boot_cpu(); @@ -103,7 +88,17 @@ void __init check_bugs(void) pr_info("CPU: "); print_cpu_info(&boot_cpu_data); #endif - check_config(); + + /* + * Check whether we are able to run this kernel safely on SMP. + * + * - i386 is no longer supported. + * - In order to run on anything without a TSC, we need to be + * compiled for a i486. + */ + if (boot_cpu_data.x86 < 4) + panic("Kernel requires i486+ for 'invlpg' and other features"); + init_utsname()->machine[1] = '0' + (boot_cpu_data.x86 > 6 ? 6 : boot_cpu_data.x86); alternative_instructions(); From 682469a5db6fade318a72406935b5000186e5643 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Mon, 8 Apr 2013 17:57:45 +0200 Subject: [PATCH 8/9] x86, AMD: Correct {rd,wr}msr_amd_safe warnings The idea with those routines is to slowly phase them out and not call them on anything else besides K8. They even have a check for that which, when called too early, fails. Let me explain: It gets the cpuinfo_x86 pointer from the per_cpu array and when this happens for cpu0, before its boot_cpu_data has been copied back to the per_cpu array in smp_store_boot_cpu_info(), we get an empty struct and thus the check fails. Use boot_cpu_data directly instead. Signed-off-by: Borislav Petkov Link: http://lkml.kernel.org/r/1365436666-9837-4-git-send-email-bp@alien8.de Signed-off-by: H. Peter Anvin --- arch/x86/kernel/cpu/amd.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index 9a2a71669c5d..cea02d703bca 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c @@ -20,11 +20,11 @@ static inline int rdmsrl_amd_safe(unsigned msr, unsigned long long *p) { - struct cpuinfo_x86 *c = &cpu_data(smp_processor_id()); u32 gprs[8] = { 0 }; int err; - WARN_ONCE((c->x86 != 0xf), "%s should only be used on K8!\n", __func__); + WARN_ONCE((boot_cpu_data.x86 != 0xf), + "%s should only be used on K8!\n", __func__); gprs[1] = msr; gprs[7] = 0x9c5a203a; @@ -38,10 +38,10 @@ static inline int rdmsrl_amd_safe(unsigned msr, unsigned long long *p) static inline int wrmsrl_amd_safe(unsigned msr, unsigned long long val) { - struct cpuinfo_x86 *c = &cpu_data(smp_processor_id()); u32 gprs[8] = { 0 }; - WARN_ONCE((c->x86 != 0xf), "%s should only be used on K8!\n", __func__); + WARN_ONCE((boot_cpu_data.x86 != 0xf), + "%s should only be used on K8!\n", __func__); gprs[0] = (u32)val; gprs[1] = msr; From 1077c932db63ecc571c31df1c24d4a44e30928e5 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Mon, 8 Apr 2013 17:57:46 +0200 Subject: [PATCH 9/9] x86, CPU, AMD: Drop useless label All we want to do is return from this function so stop jumping around like a flea for no good reason. Signed-off-by: Borislav Petkov Link: http://lkml.kernel.org/r/1365436666-9837-5-git-send-email-bp@alien8.de Signed-off-by: H. Peter Anvin --- arch/x86/kernel/cpu/amd.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index cea02d703bca..5013a48d1aff 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c @@ -192,11 +192,11 @@ static void __cpuinit amd_k7_smp_check(struct cpuinfo_x86 *c) /* Athlon 660/661 is valid. */ if ((c->x86_model == 6) && ((c->x86_mask == 0) || (c->x86_mask == 1))) - goto valid_k7; + return; /* Duron 670 is valid */ if ((c->x86_model == 7) && (c->x86_mask == 0)) - goto valid_k7; + return; /* * Athlon 662, Duron 671, and Athlon >model 7 have capability @@ -209,7 +209,7 @@ static void __cpuinit amd_k7_smp_check(struct cpuinfo_x86 *c) ((c->x86_model == 7) && (c->x86_mask >= 1)) || (c->x86_model > 7)) if (cpu_has_mp) - goto valid_k7; + return; /* If we get here, not a certified SMP capable AMD system. */ @@ -220,9 +220,6 @@ static void __cpuinit amd_k7_smp_check(struct cpuinfo_x86 *c) WARN_ONCE(1, "WARNING: This combination of AMD" " processors is not suitable for SMP.\n"); add_taint(TAINT_UNSAFE_SMP, LOCKDEP_NOW_UNRELIABLE); - -valid_k7: - ; } static void __cpuinit init_amd_k7(struct cpuinfo_x86 *c)