ab31640
From db6ca8176ccc4ff7dfe3c06969af9ebfab0d7b04 Mon Sep 17 00:00:00 2001
ab31640
From: Andrew Cooper <andrew.cooper3@citrix.com>
ab31640
Date: Tue, 12 Jul 2022 11:13:33 +0200
ab31640
Subject: [PATCH] x86/spec-ctrl: Knobs for STIBP and PSFD, and follow hardware
ab31640
 STIBP hint
ab31640
MIME-Version: 1.0
ab31640
Content-Type: text/plain; charset=utf8
ab31640
Content-Transfer-Encoding: 8bit
ab31640
ab31640
STIBP and PSFD are slightly weird bits, because they're both implied by other
ab31640
bits in MSR_SPEC_CTRL.  Add fine grain controls for them, and take the
ab31640
implications into account when setting IBRS/SSBD.
ab31640
ab31640
Rearrange the IBPB text/variables/logic to keep all the MSR_SPEC_CTRL bits
ab31640
together, for consistency.
ab31640
ab31640
However, AMD have a hardware hint CPUID bit recommending that STIBP be set
ab31640
unilaterally.  This is advertised on Zen3, so follow the recommendation.
ab31640
Furthermore, in such cases, set STIBP behind the guest's back for now.  This
ab31640
has negligible overhead for the guest, but saves a WRMSR on vmentry.  This is
ab31640
the only default change.
ab31640
ab31640
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
ab31640
Reviewed-by: Jan Beulich <jbeulich@suse.com>
ab31640
Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>
ab31640
master commit: fef244b179c06fcdfa581f7d57fa6e578c49ff50
ab31640
master date: 2022-06-30 18:07:13 +0100
ab31640
---
ab31640
 docs/misc/xen-command-line.pandoc | 21 +++++++---
ab31640
 xen/arch/x86/hvm/svm/vmcb.c       |  9 +++++
ab31640
 xen/arch/x86/spec_ctrl.c          | 65 ++++++++++++++++++++++++++-----
ab31640
 3 files changed, 81 insertions(+), 14 deletions(-)
ab31640
ab31640
diff --git a/docs/misc/xen-command-line.pandoc b/docs/misc/xen-command-line.pandoc
ab31640
index a642e43476..46e9c58d35 100644
ab31640
--- a/docs/misc/xen-command-line.pandoc
ab31640
+++ b/docs/misc/xen-command-line.pandoc
ab31640
@@ -2234,8 +2234,9 @@ By default SSBD will be mitigated at runtime (i.e `ssbd=runtime`).
ab31640
 
ab31640
 ### spec-ctrl (x86)
ab31640
 > `= List of [ <bool>, xen=<bool>, {pv,hvm,msr-sc,rsb,md-clear}=<bool>,
ab31640
->              bti-thunk=retpoline|lfence|jmp, {ibrs,ibpb,ssbd,eager-fpu,
ab31640
->              l1d-flush,branch-harden,srb-lock,unpriv-mmio}=<bool> ]`
ab31640
+>              bti-thunk=retpoline|lfence|jmp, {ibrs,ibpb,ssbd,psfd,
ab31640
+>              eager-fpu,l1d-flush,branch-harden,srb-lock,
ab31640
+>              unpriv-mmio}=<bool> ]`
ab31640
 
ab31640
 Controls for speculative execution sidechannel mitigations.  By default, Xen
ab31640
 will pick the most appropriate mitigations based on compiled in support,
ab31640
@@ -2285,9 +2286,10 @@ On hardware supporting IBRS (Indirect Branch Restricted Speculation), the
ab31640
 If Xen is not using IBRS itself, functionality is still set up so IBRS can be
ab31640
 virtualised for guests.
ab31640
 
ab31640
-On hardware supporting IBPB (Indirect Branch Prediction Barrier), the `ibpb=`
ab31640
-option can be used to force (the default) or prevent Xen from issuing branch
ab31640
-prediction barriers on vcpu context switches.
ab31640
+On hardware supporting STIBP (Single Thread Indirect Branch Predictors), the
ab31640
+`stibp=` option can be used to force or prevent Xen using the feature itself.
ab31640
+By default, Xen will use STIBP when IBRS is in use (IBRS implies STIBP), and
ab31640
+when hardware hints recommend using it as a blanket setting.
ab31640
 
ab31640
 On hardware supporting SSBD (Speculative Store Bypass Disable), the `ssbd=`
ab31640
 option can be used to force or prevent Xen using the feature itself.  On AMD
ab31640
@@ -2295,6 +2297,15 @@ hardware, this is a global option applied at boot, and not virtualised for
ab31640
 guest use.  On Intel hardware, the feature is virtualised for guests,
ab31640
 independently of Xen's choice of setting.
ab31640
 
ab31640
+On hardware supporting PSFD (Predictive Store Forwarding Disable), the `psfd=`
ab31640
+option can be used to force or prevent Xen using the feature itself.  By
ab31640
+default, Xen will not use PSFD.  PSFD is implied by SSBD, and SSBD is off by
ab31640
+default.
ab31640
+
ab31640
+On hardware supporting IBPB (Indirect Branch Prediction Barrier), the `ibpb=`
ab31640
+option can be used to force (the default) or prevent Xen from issuing branch
ab31640
+prediction barriers on vcpu context switches.
ab31640
+
ab31640
 On all hardware, the `eager-fpu=` option can be used to force or prevent Xen
ab31640
 from using fully eager FPU context switches.  This is currently implemented as
ab31640
 a global control.  By default, Xen will choose to use fully eager context
ab31640
diff --git a/xen/arch/x86/hvm/svm/vmcb.c b/xen/arch/x86/hvm/svm/vmcb.c
ab31640
index 565e997155..ef7224eb5d 100644
ab31640
--- a/xen/arch/x86/hvm/svm/vmcb.c
ab31640
+++ b/xen/arch/x86/hvm/svm/vmcb.c
ab31640
@@ -29,6 +29,7 @@
ab31640
 #include <asm/hvm/support.h>
ab31640
 #include <asm/hvm/svm/svm.h>
ab31640
 #include <asm/hvm/svm/svmdebug.h>
ab31640
+#include <asm/spec_ctrl.h>
ab31640
 
ab31640
 struct vmcb_struct *alloc_vmcb(void)
ab31640
 {
ab31640
@@ -176,6 +177,14 @@ static int construct_vmcb(struct vcpu *v)
ab31640
             vmcb->_pause_filter_thresh = SVM_PAUSETHRESH_INIT;
ab31640
     }
ab31640
 
ab31640
+    /*
ab31640
+     * When default_xen_spec_ctrl simply SPEC_CTRL_STIBP, default this behind
ab31640
+     * the back of the VM too.  Our SMT topology isn't accurate, the overhead
ab31640
+     * is neglegable, and doing this saves a WRMSR on the vmentry path.
ab31640
+     */
ab31640
+    if ( default_xen_spec_ctrl == SPEC_CTRL_STIBP )
ab31640
+        v->arch.msrs->spec_ctrl.raw = SPEC_CTRL_STIBP;
ab31640
+
ab31640
     return 0;
ab31640
 }
ab31640
 
ab31640
diff --git a/xen/arch/x86/spec_ctrl.c b/xen/arch/x86/spec_ctrl.c
ab31640
index 1ed5ceda8b..dfdd45c358 100644
ab31640
--- a/xen/arch/x86/spec_ctrl.c
ab31640
+++ b/xen/arch/x86/spec_ctrl.c
ab31640
@@ -48,9 +48,13 @@ static enum ind_thunk {
ab31640
     THUNK_LFENCE,
ab31640
     THUNK_JMP,
ab31640
 } opt_thunk __initdata = THUNK_DEFAULT;
ab31640
+
ab31640
 static int8_t __initdata opt_ibrs = -1;
ab31640
+int8_t __initdata opt_stibp = -1;
ab31640
+bool __read_mostly opt_ssbd;
ab31640
+int8_t __initdata opt_psfd = -1;
ab31640
+
ab31640
 bool __read_mostly opt_ibpb = true;
ab31640
-bool __read_mostly opt_ssbd = false;
ab31640
 int8_t __read_mostly opt_eager_fpu = -1;
ab31640
 int8_t __read_mostly opt_l1d_flush = -1;
ab31640
 static bool __initdata opt_branch_harden = true;
ab31640
@@ -172,12 +176,20 @@ static int __init parse_spec_ctrl(const char *s)
ab31640
             else
ab31640
                 rc = -EINVAL;
ab31640
         }
ab31640
+
ab31640
+        /* Bits in MSR_SPEC_CTRL. */
ab31640
         else if ( (val = parse_boolean("ibrs", s, ss)) >= 0 )
ab31640
             opt_ibrs = val;
ab31640
-        else if ( (val = parse_boolean("ibpb", s, ss)) >= 0 )
ab31640
-            opt_ibpb = val;
ab31640
+        else if ( (val = parse_boolean("stibp", s, ss)) >= 0 )
ab31640
+            opt_stibp = val;
ab31640
         else if ( (val = parse_boolean("ssbd", s, ss)) >= 0 )
ab31640
             opt_ssbd = val;
ab31640
+        else if ( (val = parse_boolean("psfd", s, ss)) >= 0 )
ab31640
+            opt_psfd = val;
ab31640
+
ab31640
+        /* Misc settings. */
ab31640
+        else if ( (val = parse_boolean("ibpb", s, ss)) >= 0 )
ab31640
+            opt_ibpb = val;
ab31640
         else if ( (val = parse_boolean("eager-fpu", s, ss)) >= 0 )
ab31640
             opt_eager_fpu = val;
ab31640
         else if ( (val = parse_boolean("l1d-flush", s, ss)) >= 0 )
ab31640
@@ -376,7 +388,7 @@ static void __init print_details(enum ind_thunk thunk, uint64_t caps)
ab31640
                "\n");
ab31640
 
ab31640
     /* Settings for Xen's protection, irrespective of guests. */
ab31640
-    printk("  Xen settings: BTI-Thunk %s, SPEC_CTRL: %s%s%s%s, Other:%s%s%s%s%s\n",
ab31640
+    printk("  Xen settings: BTI-Thunk %s, SPEC_CTRL: %s%s%s%s%s, Other:%s%s%s%s%s\n",
ab31640
            thunk == THUNK_NONE      ? "N/A" :
ab31640
            thunk == THUNK_RETPOLINE ? "RETPOLINE" :
ab31640
            thunk == THUNK_LFENCE    ? "LFENCE" :
ab31640
@@ -390,6 +402,9 @@ static void __init print_details(enum ind_thunk thunk, uint64_t caps)
ab31640
            (!boot_cpu_has(X86_FEATURE_SSBD) &&
ab31640
             !boot_cpu_has(X86_FEATURE_AMD_SSBD))     ? "" :
ab31640
            (default_xen_spec_ctrl & SPEC_CTRL_SSBD)  ? " SSBD+" : " SSBD-",
ab31640
+           (!boot_cpu_has(X86_FEATURE_PSFD) &&
ab31640
+            !boot_cpu_has(X86_FEATURE_INTEL_PSFD))   ? "" :
ab31640
+           (default_xen_spec_ctrl & SPEC_CTRL_PSFD)  ? " PSFD+" : " PSFD-",
ab31640
            !(caps & ARCH_CAPS_TSX_CTRL)              ? "" :
ab31640
            (opt_tsx & 1)                             ? " TSX+" : " TSX-",
ab31640
            !cpu_has_srbds_ctrl                       ? "" :
ab31640
@@ -979,10 +994,7 @@ void __init init_speculation_mitigations(void)
ab31640
         if ( !has_spec_ctrl )
ab31640
             printk(XENLOG_WARNING "?!? CET active, but no MSR_SPEC_CTRL?\n");
ab31640
         else if ( opt_ibrs == -1 )
ab31640
-        {
ab31640
             opt_ibrs = ibrs = true;
ab31640
-            default_xen_spec_ctrl |= SPEC_CTRL_IBRS | SPEC_CTRL_STIBP;
ab31640
-        }
ab31640
 
ab31640
         if ( opt_thunk == THUNK_DEFAULT || opt_thunk == THUNK_RETPOLINE )
ab31640
             thunk = THUNK_JMP;
ab31640
@@ -1086,14 +1098,49 @@ void __init init_speculation_mitigations(void)
ab31640
             setup_force_cpu_cap(X86_FEATURE_SC_MSR_HVM);
ab31640
     }
ab31640
 
ab31640
-    /* If we have IBRS available, see whether we should use it. */
ab31640
+    /* Figure out default_xen_spec_ctrl. */
ab31640
     if ( has_spec_ctrl && ibrs )
ab31640
+    {
ab31640
+        /* IBRS implies STIBP.  */
ab31640
+        if ( opt_stibp == -1 )
ab31640
+            opt_stibp = 1;
ab31640
+
ab31640
         default_xen_spec_ctrl |= SPEC_CTRL_IBRS;
ab31640
+    }
ab31640
+
ab31640
+    /*
ab31640
+     * Use STIBP by default if the hardware hint is set.  Otherwise, leave it
ab31640
+     * off as it a severe performance pentalty on pre-eIBRS Intel hardware
ab31640
+     * where it was retrofitted in microcode.
ab31640
+     */
ab31640
+    if ( opt_stibp == -1 )
ab31640
+        opt_stibp = !!boot_cpu_has(X86_FEATURE_STIBP_ALWAYS);
ab31640
+
ab31640
+    if ( opt_stibp && (boot_cpu_has(X86_FEATURE_STIBP) ||
ab31640
+                       boot_cpu_has(X86_FEATURE_AMD_STIBP)) )
ab31640
+        default_xen_spec_ctrl |= SPEC_CTRL_STIBP;
ab31640
 
ab31640
-    /* If we have SSBD available, see whether we should use it. */
ab31640
     if ( opt_ssbd && (boot_cpu_has(X86_FEATURE_SSBD) ||
ab31640
                       boot_cpu_has(X86_FEATURE_AMD_SSBD)) )
ab31640
+    {
ab31640
+        /* SSBD implies PSFD */
ab31640
+        if ( opt_psfd == -1 )
ab31640
+            opt_psfd = 1;
ab31640
+
ab31640
         default_xen_spec_ctrl |= SPEC_CTRL_SSBD;
ab31640
+    }
ab31640
+
ab31640
+    /*
ab31640
+     * Don't use PSFD by default.  AMD designed the predictor to
ab31640
+     * auto-clear on privilege change.  PSFD is implied by SSBD, which is
ab31640
+     * off by default.
ab31640
+     */
ab31640
+    if ( opt_psfd == -1 )
ab31640
+        opt_psfd = 0;
ab31640
+
ab31640
+    if ( opt_psfd && (boot_cpu_has(X86_FEATURE_PSFD) ||
ab31640
+                      boot_cpu_has(X86_FEATURE_INTEL_PSFD)) )
ab31640
+        default_xen_spec_ctrl |= SPEC_CTRL_PSFD;
ab31640
 
ab31640
     /*
ab31640
      * PV guests can create RSB entries for any linear address they control,
ab31640
-- 
ab31640
2.30.2
ab31640