is being interpreted as a custom timeout in milliseconds. Zero or boolean
false disable the quirk workaround, which is also the default.
+### spec-ctrl (Arm)
+> `= List of [ ssbd=force-disable|runtime|force-enable ]`
+
+Controls for speculative execution sidechannel mitigations.
+
+The option `ssbd=` is used to control the state of Speculative Store
+Bypass Disable (SSBD) mitigation.
+
+* `ssbd=force-disable` will keep the mitigation permanently off. The guest
+will not be able to control the state of the mitigation.
+* `ssbd=runtime` will always turn on the mitigation when running in the
+hypervisor context. The guest will be to turn on/off the mitigation for
+itself by using the firmware interface ARCH\_WORKAROUND\_2.
+* `ssbd=force-enable` will keep the mitigation permanently on. The guest will
+not be able to control the state of the mitigation.
+
+By default SSBD will be mitigated at runtime (i.e `ssbd=runtime`).
+
### spec-ctrl (x86)
> `= List of [ <bool>, xen=<bool>, {pv,hvm,msr-sc,rsb}=<bool>,
> bti-thunk=retpoline|lfence|jmp, {ibrs,ibpb,ssbd}=<bool> ]`
#ifdef CONFIG_ARM_SSBD
+enum ssbd_state ssbd_state = ARM_SSBD_RUNTIME;
+
+static int __init parse_spec_ctrl(const char *s)
+{
+ const char *ss;
+ int rc = 0;
+
+ do {
+ ss = strchr(s, ',');
+ if ( !ss )
+ ss = strchr(s, '\0');
+
+ if ( !strncmp(s, "ssbd=", 5) )
+ {
+ s += 5;
+
+ if ( !strncmp(s, "force-disable", ss - s) )
+ ssbd_state = ARM_SSBD_FORCE_DISABLE;
+ else if ( !strncmp(s, "runtime", ss - s) )
+ ssbd_state = ARM_SSBD_RUNTIME;
+ else if ( !strncmp(s, "force-enable", ss - s) )
+ ssbd_state = ARM_SSBD_FORCE_ENABLE;
+ else
+ rc = -EINVAL;
+ }
+ else
+ rc = -EINVAL;
+
+ s = ss + 1;
+ } while ( *ss );
+
+ return rc;
+}
+custom_param("spec-ctrl", parse_spec_ctrl);
+
/*
* Assembly code may use the variable directly, so we need to make sure
* it fits in a register.
if ( smccc_ver < SMCCC_VERSION(1, 1) )
return false;
- /*
- * The probe function return value is either negative (unsupported
- * or mitigated), positive (unaffected), or zero (requires
- * mitigation). We only need to do anything in the last case.
- */
arm_smccc_1_1_smc(ARM_SMCCC_ARCH_FEATURES_FID,
ARM_SMCCC_ARCH_WORKAROUND_2_FID, &res);
switch ( (int)res.a0 )
{
case ARM_SMCCC_NOT_SUPPORTED:
+ ssbd_state = ARM_SSBD_UNKNOWN;
return false;
case ARM_SMCCC_NOT_REQUIRED:
+ ssbd_state = ARM_SSBD_MITIGATED;
return false;
case ARM_SMCCC_SUCCESS:
return false;
}
- if ( required )
- this_cpu(ssbd_callback_required) = 1;
+ switch ( ssbd_state )
+ {
+ case ARM_SSBD_FORCE_DISABLE:
+ {
+ static bool once = true;
+
+ if ( once )
+ printk("%s disabled from command-line\n", entry->desc);
+ once = false;
+
+ arm_smccc_1_1_smc(ARM_SMCCC_ARCH_WORKAROUND_2_FID, 0, NULL);
+ required = false;
+
+ break;
+ }
+
+ case ARM_SSBD_RUNTIME:
+ if ( required )
+ {
+ this_cpu(ssbd_callback_required) = 1;
+ arm_smccc_1_1_smc(ARM_SMCCC_ARCH_WORKAROUND_2_FID, 1, NULL);
+ }
+
+ break;
+
+ case ARM_SSBD_FORCE_ENABLE:
+ {
+ static bool once = true;
+
+ if ( once )
+ printk("%s forced from command-line\n", entry->desc);
+ once = false;
+
+ arm_smccc_1_1_smc(ARM_SMCCC_ARCH_WORKAROUND_2_FID, 1, NULL);
+ required = true;
+
+ break;
+ }
+
+ default:
+ ASSERT_UNREACHABLE();
+ return false;
+ }
return required;
}
#endif
#ifdef CONFIG_ARM_SSBD
{
+ .desc = "Speculative Store Bypass Disabled",
.capability = ARM_SSBD,
.matches = has_ssbd_mitigation,
},
#undef CHECK_WORKAROUND_HELPER
+enum ssbd_state
+{
+ ARM_SSBD_UNKNOWN,
+ ARM_SSBD_FORCE_DISABLE,
+ ARM_SSBD_RUNTIME,
+ ARM_SSBD_FORCE_ENABLE,
+ ARM_SSBD_MITIGATED,
+};
+
#ifdef CONFIG_ARM_SSBD
#include <asm/current.h>
+extern enum ssbd_state ssbd_state;
+
+static inline enum ssbd_state get_ssbd_state(void)
+{
+ return ssbd_state;
+}
+
DECLARE_PER_CPU(register_t, ssbd_callback_required);
static inline bool cpu_require_ssbd_mitigation(void)
return false;
}
+static inline enum ssbd_state get_ssbd_state(void)
+{
+ return ARM_SSBD_UNKNOWN;
+}
+
#endif
#endif /* __ARM_CPUERRATA_H__ */