x86/srso: Set CPUID feature bits independently of bug or mitigation status
authorJosh Poimboeuf <jpoimboe@kernel.org>
Tue, 5 Sep 2023 05:04:46 +0000 (22:04 -0700)
committerBorislav Petkov (AMD) <bp@alien8.de>
Tue, 19 Sep 2023 08:54:07 +0000 (10:54 +0200)
Booting with mitigations=off incorrectly prevents the
X86_FEATURE_{IBPB_BRTYPE,SBPB} CPUID bits from getting set.

Also, future CPUs without X86_BUG_SRSO might still have IBPB with branch
type prediction flushing, in which case SBPB should be used instead of
IBPB.  The current code doesn't allow for that.

Also, cpu_has_ibpb_brtype_microcode() has some surprising side effects
and the setting of these feature bits really doesn't belong in the
mitigation code anyway.  Move it to earlier.

Fixes: fb3bd914b3ec ("x86/srso: Add a Speculative RAS Overflow mitigation")
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
Reviewed-by: Nikolay Borisov <nik.borisov@suse.com>
Reviewed-by: Borislav Petkov (AMD) <bp@alien8.de>
Acked-by: Borislav Petkov (AMD) <bp@alien8.de>
Link: https://lore.kernel.org/r/869a1709abfe13b673bdd10c2f4332ca253a40bc.1693889988.git.jpoimboe@kernel.org
arch/x86/include/asm/processor.h
arch/x86/kernel/cpu/amd.c
arch/x86/kernel/cpu/bugs.c

index 0086920..a3669a7 100644 (file)
@@ -683,13 +683,11 @@ extern u16 get_llc_id(unsigned int cpu);
 #ifdef CONFIG_CPU_SUP_AMD
 extern u32 amd_get_nodes_per_socket(void);
 extern u32 amd_get_highest_perf(void);
-extern bool cpu_has_ibpb_brtype_microcode(void);
 extern void amd_clear_divider(void);
 extern void amd_check_microcode(void);
 #else
 static inline u32 amd_get_nodes_per_socket(void)       { return 0; }
 static inline u32 amd_get_highest_perf(void)           { return 0; }
-static inline bool cpu_has_ibpb_brtype_microcode(void) { return false; }
 static inline void amd_clear_divider(void)             { }
 static inline void amd_check_microcode(void)           { }
 #endif
index dd8379d..afacc48 100644 (file)
@@ -766,6 +766,15 @@ static void early_init_amd(struct cpuinfo_x86 *c)
 
        if (cpu_has(c, X86_FEATURE_TOPOEXT))
                smp_num_siblings = ((cpuid_ebx(0x8000001e) >> 8) & 0xff) + 1;
+
+       if (!cpu_has(c, X86_FEATURE_IBPB_BRTYPE)) {
+               if (c->x86 == 0x17 && boot_cpu_has(X86_FEATURE_AMD_IBPB))
+                       setup_force_cpu_cap(X86_FEATURE_IBPB_BRTYPE);
+               else if (c->x86 >= 0x19 && !wrmsrl_safe(MSR_IA32_PRED_CMD, PRED_CMD_SBPB)) {
+                       setup_force_cpu_cap(X86_FEATURE_IBPB_BRTYPE);
+                       setup_force_cpu_cap(X86_FEATURE_SBPB);
+               }
+       }
 }
 
 static void init_amd_k8(struct cpuinfo_x86 *c)
@@ -1301,25 +1310,6 @@ void amd_check_microcode(void)
        on_each_cpu(zenbleed_check_cpu, NULL, 1);
 }
 
-bool cpu_has_ibpb_brtype_microcode(void)
-{
-       switch (boot_cpu_data.x86) {
-       /* Zen1/2 IBPB flushes branch type predictions too. */
-       case 0x17:
-               return boot_cpu_has(X86_FEATURE_AMD_IBPB);
-       case 0x19:
-               /* Poke the MSR bit on Zen3/4 to check its presence. */
-               if (!wrmsrl_safe(MSR_IA32_PRED_CMD, PRED_CMD_SBPB)) {
-                       setup_force_cpu_cap(X86_FEATURE_SBPB);
-                       return true;
-               } else {
-                       return false;
-               }
-       default:
-               return false;
-       }
-}
-
 /*
  * Issue a DIV 0/1 insn to clear any division data from previous DIV
  * operations.
index bdd3e29..b0ae985 100644 (file)
@@ -2404,26 +2404,15 @@ early_param("spec_rstack_overflow", srso_parse_cmdline);
 
 static void __init srso_select_mitigation(void)
 {
-       bool has_microcode;
+       bool has_microcode = boot_cpu_has(X86_FEATURE_IBPB_BRTYPE);
 
        if (!boot_cpu_has_bug(X86_BUG_SRSO) || cpu_mitigations_off())
                goto pred_cmd;
 
-       /*
-        * The first check is for the kernel running as a guest in order
-        * for guests to verify whether IBPB is a viable mitigation.
-        */
-       has_microcode = boot_cpu_has(X86_FEATURE_IBPB_BRTYPE) || cpu_has_ibpb_brtype_microcode();
        if (!has_microcode) {
                pr_warn("IBPB-extending microcode not applied!\n");
                pr_warn(SRSO_NOTICE);
        } else {
-               /*
-                * Enable the synthetic (even if in a real CPUID leaf)
-                * flags for guests.
-                */
-               setup_force_cpu_cap(X86_FEATURE_IBPB_BRTYPE);
-
                /*
                 * Zen1/2 with SMT off aren't vulnerable after the right
                 * IBPB microcode has been applied.