### bti (x86)
> `= List of [ thunk=retpoline|lfence|jmp, ibrs=<bool>, ibpb=<bool>, rsb_{vmexit,native}=<bool> ]`
+**WARNING: This command line option is deprecated, and superseded by
+_spec-ctrl=_ - using both options in combination is undefined.**
+
Branch Target Injection controls. By default, Xen will pick the most
appropriate BTI mitigations based on compiled in support, loaded microcode,
and hardware details.
is being interpreted as a custom timeout in milliseconds. Zero or boolean
false disable the quirk workaround, which is also the default.
+### spec-ctrl (x86)
+> `= List of [ <bool>, xen=<bool>, {pv,hvm,msr-sc,rsb}=<bool>,
+> bti-thunk=retpoline|lfence|jmp, {ibrs,ibpb}=<bool> ]`
+
+Controls for speculative execution sidechannel mitigations. By default, Xen
+will pick the most appropriate mitigations based on compiled in support,
+loaded microcode, and hardware details, and will virtualise appropriate
+mitigations for guests to use.
+
+**WARNING: Any use of this option may interfere with heuristics. Use with
+extreme care.**
+
+An overall boolean value, `spec-ctrl=no`, can be specified to turn off all
+mitigations, including pieces of infrastructure used to virtualise certain
+mitigation features for guests. Alternatively, a slightly more restricted
+`spec-ctrl=no-xen` can be used to turn off all of Xen's mitigations, while
+leaving the virtualisation support in place for guests to use. Use of a
+positive boolean value for either of these options is invalid.
+
+The booleans `pv=`, `hvm=`, `msr-sc=` and `rsb=` offer fine grained control
+over the alternative blocks used by Xen. These impact Xen's ability to
+protect itself, and Xen's ability to virtualise support for guests to use.
+
+* `pv=` and `hvm=` offer control over all suboptions for PV and HVM guests
+ respectively.
+* `msr-sc=` offers control over Xen's support for manipulating MSR\_SPEC\_CTRL
+ on entry and exit. These blocks are necessary to virtualise support for
+ guests and if disabled, guests will be unable to use IBRS/STIBP/etc.
+* `rsb=` offers control over whether to overwrite the Return Stack Buffer /
+ Return Address Stack on entry to Xen.
+
+If Xen was compiled with INDIRECT\_THUNK support, `bti-thunk=` can be used to
+select which of the thunks gets patched into the `__x86_indirect_thunk_%reg`
+locations. The default thunk is `retpoline` (generally preferred for Intel
+hardware), with the alternatives being `jmp` (a `jmp *%reg` gadget, minimal
+overhead), and `lfence` (an `lfence; jmp *%reg` gadget, preferred for AMD).
+
+On hardware supporting IBRS (Indirect Branch Restricted Speculation), the
+`ibrs=` option can be used to force or prevent Xen using the feature itself.
+If Xen is not using IBRS itself, functionality is still set up so IBRS can be
+virtualised for guests.
+
+On hardware supporting IBPB (Indirect Branch Prediction Barrier), the `ibpb=`
+option can be used to force (the default) or prevent Xen from issuing branch
+prediction barriers on vcpu context switches.
+
### sync\_console
> `= <boolean>`
#include <asm/spec_ctrl.h>
#include <asm/spec_ctrl_asm.h>
+/* Cmdline controls for Xen's alternative blocks. */
+static bool_t __initdata opt_msr_sc_pv = 1;
+static bool_t __initdata opt_msr_sc_hvm = 1;
+static bool_t __initdata opt_rsb_pv = 1;
+static bool_t __initdata opt_rsb_hvm = 1;
+
+/* Cmdline controls for Xen's speculative settings. */
static enum ind_thunk {
THUNK_DEFAULT, /* Decide which thunk to use at boot time. */
THUNK_NONE, /* Missing compiler support for thunks. */
THUNK_JMP,
} opt_thunk __initdata = THUNK_DEFAULT;
static int8_t __initdata opt_ibrs = -1;
-static bool_t __initdata opt_rsb_pv = 1;
-static bool_t __initdata opt_rsb_hvm = 1;
bool_t __read_mostly opt_ibpb = 1;
bool_t __initdata bsp_delay_spec_ctrl;
}
custom_param("bti", parse_bti);
+static int __init parse_spec_ctrl(char *s)
+{
+ char *ss;
+ int val, rc = 0;
+
+ do {
+ ss = strchr(s, ',');
+ if ( ss )
+ *ss = '\0';
+
+ /* Global and Xen-wide disable. */
+ val = parse_bool(s);
+ if ( !val )
+ {
+ opt_msr_sc_pv = 0;
+ opt_msr_sc_hvm = 0;
+
+ disable_common:
+ opt_rsb_pv = 0;
+ opt_rsb_hvm = 0;
+
+ opt_thunk = THUNK_JMP;
+ opt_ibrs = 0;
+ opt_ibpb = 0;
+ }
+ else if ( val > 0 )
+ rc = -EINVAL;
+ else if ( (val = parse_boolean("xen", s, ss)) >= 0 )
+ {
+ if ( !val )
+ goto disable_common;
+
+ rc = -EINVAL;
+ }
+
+ /* Xen's alternative blocks. */
+ else if ( (val = parse_boolean("pv", s, ss)) >= 0 )
+ {
+ opt_msr_sc_pv = val;
+ opt_rsb_pv = val;
+ }
+ else if ( (val = parse_boolean("hvm", s, ss)) >= 0 )
+ {
+ opt_msr_sc_hvm = val;
+ opt_rsb_hvm = val;
+ }
+ else if ( (val = parse_boolean("msr-sc", s, ss)) >= 0 )
+ {
+ opt_msr_sc_pv = val;
+ opt_msr_sc_hvm = val;
+ }
+ else if ( (val = parse_boolean("rsb", s, ss)) >= 0 )
+ {
+ opt_rsb_pv = val;
+ opt_rsb_hvm = val;
+ }
+
+ /* Xen's speculative sidechannel mitigation settings. */
+ else if ( !strncmp(s, "bti-thunk=", 10) )
+ {
+ s += 10;
+
+ if ( !strcmp(s, "retpoline") )
+ opt_thunk = THUNK_RETPOLINE;
+ else if ( !strcmp(s, "lfence") )
+ opt_thunk = THUNK_LFENCE;
+ else if ( !strcmp(s, "jmp") )
+ opt_thunk = THUNK_JMP;
+ else
+ rc = -EINVAL;
+ }
+ else if ( (val = parse_boolean("ibrs", s, ss)) >= 0 )
+ opt_ibrs = val;
+ else if ( (val = parse_boolean("ibpb", s, ss)) >= 0 )
+ opt_ibpb = val;
+ else
+ rc = -EINVAL;
+
+ s = ss + 1;
+ } while ( ss );
+
+ return rc;
+}
+custom_param("spec-ctrl", parse_spec_ctrl);
+
static void __init print_details(enum ind_thunk thunk, uint64_t caps)
{
+ bool_t use_spec_ctrl = (boot_cpu_has(X86_FEATURE_SC_MSR_PV) ||
+ boot_cpu_has(X86_FEATURE_SC_MSR_HVM));
unsigned int _7d0 = 0, e8b = 0, tmp;
/* Collect diagnostics about available mitigations. */
if ( boot_cpu_data.extended_cpuid_level >= 0x80000008 )
cpuid(0x80000008, &tmp, &e8b, &tmp, &tmp);
- printk(XENLOG_DEBUG "Speculative mitigation facilities:\n");
+ printk("Speculative mitigation facilities:\n");
/* Hardware features which pertain to speculative mitigations. */
- printk(XENLOG_DEBUG " Hardware features:%s%s%s%s%s%s\n",
+ printk(" Hardware features:%s%s%s%s%s%s\n",
(_7d0 & cpufeat_mask(X86_FEATURE_IBRSB)) ? " IBRS/IBPB" : "",
(_7d0 & cpufeat_mask(X86_FEATURE_STIBP)) ? " STIBP" : "",
(e8b & cpufeat_mask(X86_FEATURE_IBPB)) ? " IBPB" : "",
printk(XENLOG_DEBUG " Compiled-in support: INDIRECT_THUNK\n");
#endif
- printk(XENLOG_INFO
- "BTI mitigations: Thunk %s, Others:%s%s%s%s\n",
+ /* Settings for Xen's protection, irrespective of guests. */
+ printk(" Xen settings: BTI-Thunk %s, SPEC_CTRL: %s, Other:%s\n",
thunk == THUNK_NONE ? "N/A" :
thunk == THUNK_RETPOLINE ? "RETPOLINE" :
thunk == THUNK_LFENCE ? "LFENCE" :
thunk == THUNK_JMP ? "JMP" : "?",
+ !use_spec_ctrl ? "No" :
+ (default_xen_spec_ctrl & SPEC_CTRL_IBRS) ? "IBRS+" : "IBRS-",
+ opt_ibpb ? " IBPB" : "");
+
+ /*
+ * Alternatives blocks for protecting against and/or virtualising
+ * mitigation support for guests.
+ */
+ printk(" Support for VMs: PV:%s%s%s, HVM:%s%s%s\n",
(boot_cpu_has(X86_FEATURE_SC_MSR_PV) ||
- boot_cpu_has(X86_FEATURE_SC_MSR_HVM)) ?
- default_xen_spec_ctrl & SPEC_CTRL_IBRS ? " IBRS+" :
- " IBRS-" : "",
- opt_ibpb ? " IBPB" : "",
- boot_cpu_has(X86_FEATURE_SC_RSB_PV) ? " RSB_NATIVE" : "",
- boot_cpu_has(X86_FEATURE_SC_RSB_HVM) ? " RSB_VMEXIT" : "");
+ boot_cpu_has(X86_FEATURE_SC_RSB_PV)) ? "" : " None",
+ boot_cpu_has(X86_FEATURE_SC_MSR_PV) ? " MSR_SPEC_CTRL" : "",
+ boot_cpu_has(X86_FEATURE_SC_RSB_PV) ? " RSB" : "",
+ (boot_cpu_has(X86_FEATURE_SC_MSR_HVM) ||
+ boot_cpu_has(X86_FEATURE_SC_RSB_HVM)) ? "" : " None",
+ boot_cpu_has(X86_FEATURE_SC_MSR_HVM) ? " MSR_SPEC_CTRL" : "",
+ boot_cpu_has(X86_FEATURE_SC_RSB_HVM) ? " RSB" : "");
}
/* Calculate whether Retpoline is known-safe on this CPU. */
void __init init_speculation_mitigations(void)
{
enum ind_thunk thunk = THUNK_DEFAULT;
- bool_t ibrs = 0;
+ bool_t use_spec_ctrl = 0, ibrs = 0;
uint64_t caps = 0;
if ( boot_cpu_has(X86_FEATURE_ARCH_CAPS) )
else if ( thunk == THUNK_JMP )
__set_bit(X86_FEATURE_IND_THUNK_JMP, boot_cpu_data.x86_capability);
+ /*
+ * If we are on hardware supporting MSR_SPEC_CTRL, see about setting up
+ * the alternatives blocks so we can virtualise support for guests.
+ */
if ( boot_cpu_has(X86_FEATURE_IBRSB) )
{
- /*
- * Even if we've chosen to not have IBRS set in Xen context, we still
- * need the IBRS entry/exit logic to virtualise IBRS support for
- * guests.
- */
- __set_bit(X86_FEATURE_SC_MSR_PV, boot_cpu_data.x86_capability);
- __set_bit(X86_FEATURE_SC_MSR_HVM, boot_cpu_data.x86_capability);
+ if ( opt_msr_sc_pv )
+ {
+ use_spec_ctrl = 1;
+ __set_bit(X86_FEATURE_SC_MSR_PV, boot_cpu_data.x86_capability);
+ }
+
+ if ( opt_msr_sc_hvm )
+ {
+ use_spec_ctrl = 1;
+ __set_bit(X86_FEATURE_SC_MSR_HVM, boot_cpu_data.x86_capability);
+ }
- if ( ibrs )
- default_xen_spec_ctrl |= SPEC_CTRL_IBRS;
+ if ( use_spec_ctrl )
+ {
+ if ( ibrs )
+ default_xen_spec_ctrl |= SPEC_CTRL_IBRS;
- default_spec_ctrl_flags |= SCF_ist_wrmsr;
+ default_spec_ctrl_flags |= SCF_ist_wrmsr;
+ }
}
/*