x86/speculation: Add support for STIBP always-on preferred mode
authorThomas Lendacky <Thomas.Lendacky@amd.com>
Thu, 13 Dec 2018 23:03:54 +0000 (23:03 +0000)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 20 Jun 2020 08:23:17 +0000 (10:23 +0200)
[ Upstream commit 20c3a2c33e9fdc82e9e8e8d2a6445b3256d20191 ]

Different AMD processors may have different implementations of STIBP.
When STIBP is conditionally enabled, some implementations would benefit
from having STIBP always on instead of toggling the STIBP bit through MSR
writes. This preference is advertised through a CPUID feature bit.

When conditional STIBP support is requested at boot and the CPU advertises
STIBP always-on mode as preferred, switch to STIBP "on" support. To show
that this transition has occurred, create a new spectre_v2_user_mitigation
value and a new spectre_v2_user_strings message. The new mitigation value
is used in spectre_v2_user_select_mitigation() to print the new mitigation
message as well as to return a new string from stibp_state().

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Andrea Arcangeli <aarcange@redhat.com>
Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Cc: Jiri Kosina <jkosina@suse.cz>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Tim Chen <tim.c.chen@linux.intel.com>
Cc: David Woodhouse <dwmw@amazon.co.uk>
Link: https://lkml.kernel.org/r/20181213230352.6937.74943.stgit@tlendack-t1.amdoffice.net
Signed-off-by: Sasha Levin <sashal@kernel.org>
arch/x86/include/asm/cpufeatures.h
arch/x86/include/asm/nospec-branch.h
arch/x86/kernel/cpu/bugs.c

index 492889d921468fc758229aebd445891a3e5217d7..7c7fc50060176f2f0da16d8d4cf12eb15b164bae 100644 (file)
 #define X86_FEATURE_AMD_IBPB   (13*32+12) /* "" Indirect Branch Prediction Barrier */
 #define X86_FEATURE_AMD_IBRS   (13*32+14) /* "" Indirect Branch Restricted Speculation */
 #define X86_FEATURE_AMD_STIBP  (13*32+15) /* "" Single Thread Indirect Branch Predictors */
+#define X86_FEATURE_AMD_STIBP_ALWAYS_ON        (13*32+17) /* "" Single Thread Indirect Branch Predictors always-on preferred */
 #define X86_FEATURE_AMD_SSBD   (13*32+24) /* "" Speculative Store Bypass Disable */
 #define X86_FEATURE_VIRT_SSBD  (13*32+25) /* Virtualized Speculative Store Bypass Disable */
 #define X86_FEATURE_AMD_SSB_NO (13*32+26) /* "" Speculative Store Bypass is fixed in hardware. */
 #define X86_FEATURE_SUCCOR     (17*32+1) /* Uncorrectable error containment and recovery */
 #define X86_FEATURE_SMCA       (17*32+3) /* Scalable MCA */
 
-
 /* Intel-defined CPU features, CPUID level 0x00000007:0 (EDX), word 18 */
 #define X86_FEATURE_AVX512_4VNNIW      (18*32+ 2) /* AVX-512 Neural Network Instructions */
 #define X86_FEATURE_AVX512_4FMAPS      (18*32+ 3) /* AVX-512 Multiply Accumulation Single precision */
index 783f0711895b321e401460d42ee004112b261264..664e8505ccd63aa2873bacac1b02676057cef0b4 100644 (file)
@@ -178,6 +178,7 @@ enum spectre_v2_mitigation {
 enum spectre_v2_user_mitigation {
        SPECTRE_V2_USER_NONE,
        SPECTRE_V2_USER_STRICT,
+       SPECTRE_V2_USER_STRICT_PREFERRED,
        SPECTRE_V2_USER_PRCTL,
        SPECTRE_V2_USER_SECCOMP,
 };
index 9fddbdcc18744f42a896cdacf72836c5d98321e5..6ee7d81fe3399a6d7f07d065c9323c2639f2d4fd 100644 (file)
@@ -609,10 +609,11 @@ enum spectre_v2_user_cmd {
 };
 
 static const char * const spectre_v2_user_strings[] = {
-       [SPECTRE_V2_USER_NONE]          = "User space: Vulnerable",
-       [SPECTRE_V2_USER_STRICT]        = "User space: Mitigation: STIBP protection",
-       [SPECTRE_V2_USER_PRCTL]         = "User space: Mitigation: STIBP via prctl",
-       [SPECTRE_V2_USER_SECCOMP]       = "User space: Mitigation: STIBP via seccomp and prctl",
+       [SPECTRE_V2_USER_NONE]                  = "User space: Vulnerable",
+       [SPECTRE_V2_USER_STRICT]                = "User space: Mitigation: STIBP protection",
+       [SPECTRE_V2_USER_STRICT_PREFERRED]      = "User space: Mitigation: STIBP always-on protection",
+       [SPECTRE_V2_USER_PRCTL]                 = "User space: Mitigation: STIBP via prctl",
+       [SPECTRE_V2_USER_SECCOMP]               = "User space: Mitigation: STIBP via seccomp and prctl",
 };
 
 static const struct {
@@ -701,6 +702,15 @@ spectre_v2_user_select_mitigation(enum spectre_v2_mitigation_cmd v2_cmd)
                break;
        }
 
+       /*
+        * At this point, an STIBP mode other than "off" has been set.
+        * If STIBP support is not being forced, check if STIBP always-on
+        * is preferred.
+        */
+       if (mode != SPECTRE_V2_USER_STRICT &&
+           boot_cpu_has(X86_FEATURE_AMD_STIBP_ALWAYS_ON))
+               mode = SPECTRE_V2_USER_STRICT_PREFERRED;
+
        /* Initialize Indirect Branch Prediction Barrier */
        if (boot_cpu_has(X86_FEATURE_IBPB)) {
                setup_force_cpu_cap(X86_FEATURE_USE_IBPB);
@@ -983,6 +993,7 @@ void arch_smt_update(void)
        case SPECTRE_V2_USER_NONE:
                break;
        case SPECTRE_V2_USER_STRICT:
+       case SPECTRE_V2_USER_STRICT_PREFERRED:
                update_stibp_strict();
                break;
        case SPECTRE_V2_USER_PRCTL:
@@ -1217,7 +1228,8 @@ static int ib_prctl_set(struct task_struct *task, unsigned long ctrl)
                 * Indirect branch speculation is always disabled in strict
                 * mode.
                 */
-               if (spectre_v2_user == SPECTRE_V2_USER_STRICT)
+               if (spectre_v2_user == SPECTRE_V2_USER_STRICT ||
+                   spectre_v2_user == SPECTRE_V2_USER_STRICT_PREFERRED)
                        return -EPERM;
                task_clear_spec_ib_disable(task);
                task_update_spec_tif(task);
@@ -1230,7 +1242,8 @@ static int ib_prctl_set(struct task_struct *task, unsigned long ctrl)
                 */
                if (spectre_v2_user == SPECTRE_V2_USER_NONE)
                        return -EPERM;
-               if (spectre_v2_user == SPECTRE_V2_USER_STRICT)
+               if (spectre_v2_user == SPECTRE_V2_USER_STRICT ||
+                   spectre_v2_user == SPECTRE_V2_USER_STRICT_PREFERRED)
                        return 0;
                task_set_spec_ib_disable(task);
                if (ctrl == PR_SPEC_FORCE_DISABLE)
@@ -1301,6 +1314,7 @@ static int ib_prctl_get(struct task_struct *task)
                        return PR_SPEC_PRCTL | PR_SPEC_DISABLE;
                return PR_SPEC_PRCTL | PR_SPEC_ENABLE;
        case SPECTRE_V2_USER_STRICT:
+       case SPECTRE_V2_USER_STRICT_PREFERRED:
                return PR_SPEC_DISABLE;
        default:
                return PR_SPEC_NOT_AFFECTED;
@@ -1450,6 +1464,8 @@ static char *stibp_state(void)
                return ", STIBP: disabled";
        case SPECTRE_V2_USER_STRICT:
                return ", STIBP: forced";
+       case SPECTRE_V2_USER_STRICT_PREFERRED:
+               return ", STIBP: always-on";
        case SPECTRE_V2_USER_PRCTL:
        case SPECTRE_V2_USER_SECCOMP:
                if (static_key_enabled(&switch_to_cond_stibp))