| From: Borislav Petkov <bp@suse.de> |
| Date: Wed, 20 Mar 2013 15:07:23 +0100 |
| Subject: x86, cpu: Expand cpufeature facility to include cpu bugs |
| |
| commit 65fc985b37dc241c4db7cd32adcbc989193fe3c8 upstream. |
| |
| 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 <bp@suse.de> |
| Link: http://lkml.kernel.org/r/1363788448-31325-2-git-send-email-bp@alien8.de |
| Signed-off-by: H. Peter Anvin <hpa@zytor.com> |
| [bwh: Backported to 3.2: adjust context] |
| Signed-off-by: Ben Hutchings <ben@decadent.org.uk> |
| --- |
| 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(-) |
| |
| --- a/arch/x86/include/asm/cpufeature.h |
| +++ b/arch/x86/include/asm/cpufeature.h |
| @@ -7,6 +7,7 @@ |
| #include <asm/required-features.h> |
| |
| #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 |
| @@ -208,6 +209,11 @@ |
| #define X86_FEATURE_INVPCID (9*32+10) /* Invalidate Processor Context ID */ |
| #define X86_FEATURE_RTM (9*32+11) /* Restricted Transactional Memory */ |
| |
| +/* |
| + * BUG word(s) |
| + */ |
| +#define X86_BUG(x) (NCAPINTS*32 + (x)) |
| + |
| #if defined(__KERNEL__) && !defined(__ASSEMBLY__) |
| |
| #include <asm/asm.h> |
| @@ -397,6 +403,13 @@ static __always_inline __pure bool __sta |
| #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 */ |
| --- a/arch/x86/include/asm/processor.h |
| +++ b/arch/x86/include/asm/processor.h |
| @@ -86,7 +86,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: */ |
| --- a/arch/x86/kernel/alternative.c |
| +++ b/arch/x86/kernel/alternative.c |
| @@ -359,7 +359,7 @@ void __init_or_module apply_alternatives |
| instr = (u8 *)&a->instr_offset + a->instr_offset; |
| replacement = (u8 *)&a->repl_offset + a->repl_offset; |
| 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)) { |
| if (a->padlen > 1) |
| optimize_nops(a, instr); |
| --- a/arch/x86/kernel/cpu/common.c |
| +++ b/arch/x86/kernel/cpu/common.c |
| @@ -954,6 +954,10 @@ static void __cpuinit identify_cpu(struc |
| /* 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. */ |