]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
retpoline: microcode incorrectly reported as broken during early boot
authorChuck Anderson <chuck.anderson@oracle.com>
Thu, 22 Feb 2018 22:01:24 +0000 (14:01 -0800)
committerChuck Anderson <chuck.anderson@oracle.com>
Sat, 3 Mar 2018 01:58:03 +0000 (17:58 -0800)
init_scattered_cpuid_features() is called on each CPU to set its
capabilities based on features enumerated by the cpuid instruction.
If the CPU supports IBRS or STIBP, a call is made through
bad_spectre_microcode() to detect a microcode level that makes it
unsafe to use IBRS as a mitigation for Spectre.  A warning is issued
if the microcode is unsafe:

    Intel Spectre v2 broken microcode detected; disabling SPEC_CTRL/IBR

init_scattered_cpuid_features() may be called early during boot on the
boot CPU.  The microcode level from BIOS may be broken, triggering the
message above.  A subsequent microcode update made during early boot
could install a level that is IBRS/STIBP/IPBP safe making the warning
message misleading.  This patch skips the microcode check during early
boot.  The check is made during a subsequent call to
init_scattered_cpuid_features() after a potential microcode update.

Orabug: 27625404
Signed-off-by: Chuck Anderson <chuck.anderson@oracle.com>
Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Reviewed-by: Darren Kenny <darren.kenny@oracle.com>
arch/x86/include/asm/processor.h
arch/x86/kernel/cpu/common.c
arch/x86/kernel/cpu/cpu.h
arch/x86/kernel/cpu/intel.c
arch/x86/kernel/cpu/microcode/core.c
arch/x86/kernel/cpu/scattered.c

index 1d70864c19b01b3a5b79a9b10d193ec5a1dfec6f..7007b2f6a2318a911ac925e4f45dcd264feded2a 100644 (file)
@@ -153,6 +153,11 @@ extern struct tss_struct   doublefault_tss;
 extern __u32                   cpu_caps_cleared[NCAPINTS];
 extern __u32                   cpu_caps_set[NCAPINTS];
 
+enum get_cpu_cap_behavior {
+       GET_CPU_CAP_MINIMUM,
+       GET_CPU_CAP_FULL,
+};
+
 #ifdef CONFIG_SMP
 DECLARE_PER_CPU_READ_MOSTLY(struct cpuinfo_x86, cpu_info);
 #define cpu_data(cpu)          per_cpu(cpu_info, cpu)
@@ -173,7 +178,8 @@ extern void identify_boot_cpu(void);
 extern void identify_secondary_cpu(struct cpuinfo_x86 *);
 extern void print_cpu_info(struct cpuinfo_x86 *);
 void print_cpu_msr(struct cpuinfo_x86 *);
-extern void init_scattered_cpuid_features(struct cpuinfo_x86 *c);
+extern void init_scattered_cpuid_features(struct cpuinfo_x86 *c,
+                                         enum get_cpu_cap_behavior behavior);
 extern unsigned int init_intel_cacheinfo(struct cpuinfo_x86 *c);
 extern void init_amd_cacheinfo(struct cpuinfo_x86 *c);
 
index 4dbac25c0aec1130aa21d63ed4a2ac06a45a8c94..73ada6d4600462eb9ff2937c50f3db00578a8478 100644 (file)
@@ -682,7 +682,7 @@ void cpu_detect(struct cpuinfo_x86 *c)
        }
 }
 
-void get_cpu_cap(struct cpuinfo_x86 *c)
+void get_cpu_cap(struct cpuinfo_x86 *c, enum get_cpu_cap_behavior behavior)
 {
        u32 tfms, xlvl;
        u32 ebx;
@@ -772,7 +772,7 @@ void get_cpu_cap(struct cpuinfo_x86 *c)
        if (c->extended_cpuid_level >= 0x80000007)
                c->x86_power = cpuid_edx(0x80000007);
 
-       init_scattered_cpuid_features(c);
+       init_scattered_cpuid_features(c, behavior);
 }
 
 static void identify_cpu_without_cpuid(struct cpuinfo_x86 *c)
@@ -870,7 +870,7 @@ static void __init early_identify_cpu(struct cpuinfo_x86 *c)
 
        cpu_detect(c);
        get_cpu_vendor(c);
-       get_cpu_cap(c);
+       get_cpu_cap(c, GET_CPU_CAP_MINIMUM);
        fpu_detect(c);
 
        if (this_cpu->c_early_init)
@@ -959,7 +959,7 @@ static void generic_identify(struct cpuinfo_x86 *c)
 
        get_cpu_vendor(c);
 
-       get_cpu_cap(c);
+       get_cpu_cap(c, GET_CPU_CAP_FULL);
 
        if (c->cpuid_level >= 0x00000001) {
                c->initial_apicid = (cpuid_ebx(1) >> 24) & 0xFF;
index c37dc37e8317f107bc1b79b118b5eab13368482d..ac7c209e289bb1b0f456928db6fbb196debc1333 100644 (file)
@@ -43,6 +43,7 @@ struct _tlb_table {
 extern const struct cpu_dev *const __x86_cpu_dev_start[],
                            *const __x86_cpu_dev_end[];
 
-extern void get_cpu_cap(struct cpuinfo_x86 *c);
+extern void get_cpu_cap(struct cpuinfo_x86 *c,
+                       enum get_cpu_cap_behavior behavior);
 extern void cpu_detect_cache_sizes(struct cpuinfo_x86 *c);
 #endif /* ARCH_X86_CPU_H */
index 50163fa9034f0d2f4db28767432a249ad9e0cb35..23f86bde85d17cfec21dd4b0e8834cf083614505 100644 (file)
@@ -34,7 +34,7 @@ static void early_init_intel(struct cpuinfo_x86 *c)
                if (msr_clear_bit(MSR_IA32_MISC_ENABLE,
                                  MSR_IA32_MISC_ENABLE_LIMIT_CPUID_BIT) > 0) {
                        c->cpuid_level = cpuid_eax(0);
-                       get_cpu_cap(c);
+                       get_cpu_cap(c, GET_CPU_CAP_FULL);
                }
        }
 
index 2f83c508c1ccdbc00f6daa72346585aeeaa95603..808f33974cd36437b0bf79a429edfcd92ced6ed8 100644 (file)
@@ -233,7 +233,7 @@ static ssize_t microcode_write(struct file *file, const char __user *buf,
                perf_check_microcode();
 
        /* check spec_ctrl capabilities */
-       init_scattered_cpuid_features(&boot_cpu_data);
+       init_scattered_cpuid_features(&boot_cpu_data, GET_CPU_CAP_FULL);
 
        mutex_unlock(&microcode_mutex);
        put_online_cpus();
index 39e16bb62490a0f5805234d049fcc316bc6ff0c9..67a1ea0173d038781ac0f486b96508a443f1e0be 100644 (file)
@@ -86,7 +86,8 @@ static bool bad_spectre_microcode(struct cpuinfo_x86 *c)
        return false;
 }
 
-void init_scattered_cpuid_features(struct cpuinfo_x86 *c)
+void init_scattered_cpuid_features(struct cpuinfo_x86 *c,
+                                  enum get_cpu_cap_behavior behavior)
 {
        u32 max_level;
        u32 regs[4];
@@ -150,6 +151,9 @@ void init_scattered_cpuid_features(struct cpuinfo_x86 *c)
        if (cpu_has(c, X86_FEATURE_IBRS))
                set_cpu_cap(c, X86_FEATURE_IBPB);
 
+       if (behavior == GET_CPU_CAP_MINIMUM)
+               return;
+
        if (!c->cpu_index) {
                bool ignore = false;