@@ -196,7 +196,7 @@ int set_ibpb_enabled(unsigned int);
/* The IBRS runtime control knob */
extern unsigned int ibrs_enabled;
-void ibrs_enable(void);
+int set_ibrs_enabled(unsigned int);
/* The Spectre V2 mitigation variants */
enum spectre_v2_mitigation {
@@ -266,7 +266,7 @@ do { \
preempt_enable(); \
} while (0)
-#define restricted_branch_speculation_on() \
+#define ubuntu_restrict_branch_speculation_start() \
do { \
u64 val = x86_spec_ctrl_base | SPEC_CTRL_IBRS; \
\
@@ -274,7 +274,7 @@ do { \
native_wrmsrl(MSR_IA32_SPEC_CTRL, val); \
} while (0)
-#define restricted_branch_speculation_off() \
+#define ubuntu_restrict_branch_speculation_end() \
do { \
u64 val = x86_spec_ctrl_base; \
\
@@ -21,11 +21,13 @@
popq %rdx; \
popq %rcx; \
popq %rax
+
#define __ASM_ENABLE_IBRS_CLOBBER \
movl $MSR_IA32_SPEC_CTRL, %ecx; \
movl $0, %edx; \
movl $SPEC_CTRL_IBRS, %eax; \
wrmsr;
+
#define __ASM_DISABLE_IBRS \
pushq %rax; \
pushq %rcx; \
@@ -37,6 +39,7 @@
popq %rdx; \
popq %rcx; \
popq %rax
+
#define __ASM_STUFF_RSB \
call 1f; \
pause; \
@@ -167,14 +167,14 @@ void mwait_idle_with_hints(unsigned long ax, unsigned long cx)
if (this_cpu_has(X86_FEATURE_CLFLUSH_MONITOR))
clflush((void *)¤t_thread_info()->flags);
- restricted_branch_speculation_off();
+ ubuntu_restrict_branch_speculation_end();
__monitor((void *)¤t_thread_info()->flags, 0, 0);
smp_mb();
if (!need_resched())
__mwait(ax, cx);
- restricted_branch_speculation_on();
+ ubuntu_restrict_branch_speculation_start();
}
}
@@ -450,16 +450,17 @@ retpoline_auto:
setup_force_cpu_cap(X86_FEATURE_USE_IBRS_FW);
pr_info("Enabling Restricted Speculation for firmware calls\n");
- /*
- * Enable IBRS support if it's not turned off on the
- * commandline and we don't have full retpoline mode
- */
- if (!noibrs && mode != SPECTRE_V2_RETPOLINE_AMD &&
- mode != SPECTRE_V2_RETPOLINE_GENERIC)
- ibrs_enable();
-
- pr_info("%s Indirect Banch Restricted Speculation\n",
- ibrs_enabled ? "Enabling" : "Disabling");
+ if (noibrs ||
+ mode == SPECTRE_V2_RETPOLINE_GENERIC ||
+ mode == SPECTRE_V2_RETPOLINE_AMD) {
+ /*
+ * IBRS disabled via commandline or the kernel is
+ * retpoline compiled
+ */
+ set_ibrs_enabled(0);
+ } else {
+ set_ibrs_enabled(1);
+ }
}
/*
@@ -874,8 +875,9 @@ static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr
return sprintf(buf, "Mitigation: __user pointer sanitization\n");
case X86_BUG_SPECTRE_V2:
- return sprintf(buf, "%s%s%s\n", spectre_v2_strings[spectre_v2_enabled],
+ return sprintf(buf, "%s%s%s%s\n", spectre_v2_strings[spectre_v2_enabled],
ibpb_enabled ? ", IBPB" : "",
+ ibrs_enabled == 2 ? ", IBRS (user space)" : ibrs_enabled ? ", IBRS" : "",
boot_cpu_has(X86_FEATURE_USE_IBRS_FW) ? ", IBRS_FW" : "");
case X86_BUG_SPEC_STORE_BYPASS:
@@ -583,15 +583,15 @@ static void mwait_idle(void)
mb();
}
- restricted_branch_speculation_off();
+ ubuntu_restrict_branch_speculation_end();
__monitor((void *)¤t_thread_info()->flags, 0, 0);
if (!need_resched()) {
__sti_mwait(0, 0);
- restricted_branch_speculation_on();
+ ubuntu_restrict_branch_speculation_start();
} else {
- restricted_branch_speculation_on();
+ ubuntu_restrict_branch_speculation_start();
local_irq_enable();
}
@@ -1625,13 +1625,13 @@ void native_play_dead(void)
play_dead_common();
tboot_shutdown(TB_SHUTDOWN_WFS);
- restricted_branch_speculation_off();
+ ubuntu_restrict_branch_speculation_end();
mwait_play_dead(); /* Only returns on failure */
if (cpuidle_play_dead())
hlt_play_dead();
- restricted_branch_speculation_on();
+ ubuntu_restrict_branch_speculation_start();
}
#else /* ... !CONFIG_HOTPLUG_CPU */
@@ -249,61 +249,67 @@ static int ibpb_enabled_handler(struct ctl_table *table, int write,
}
unsigned int ibrs_enabled = 0;
-EXPORT_SYMBOL(ibrs_enabled);
+EXPORT_SYMBOL(ibrs_enabled); /* Required in some modules */
static unsigned int __ibrs_enabled = 0; /* procfs shadow variable */
-static void set_ibrs_enabled(unsigned int val)
+int set_ibrs_enabled(unsigned int val)
{
+ int error = 0;
unsigned int cpu;
mutex_lock(&spec_ctrl_mutex);
/* Only enable/disable IBRS if the CPU supports it */
- if (boot_cpu_has(X86_FEATURE_USE_IBRS_FW)) {
+ if (boot_cpu_has(X86_FEATURE_IBRS)) {
ibrs_enabled = val;
+ pr_info("Spectre V2 : Spectre v2 mitigation: %s Indirect "
+ "Branch Restricted Speculation%s\n",
+ ibrs_enabled ? "Enabling" : "Disabling",
+ ibrs_enabled == 2 ? " (user space)" : "");
+
if (ibrs_enabled == 0) {
/* Always disable IBRS */
u64 val = x86_spec_ctrl_base;
- for_each_online_cpu(cpu)
+ for_each_online_cpu(cpu) {
wrmsrl_on_cpu(cpu, MSR_IA32_SPEC_CTRL, val);
+ }
} else if (ibrs_enabled == 2) {
/* Always enable IBRS, even in user space */
u64 val = x86_spec_ctrl_base | SPEC_CTRL_IBRS;
- for_each_online_cpu(cpu)
+ for_each_online_cpu(cpu) {
wrmsrl_on_cpu(cpu, MSR_IA32_SPEC_CTRL, val);
+ }
}
} else {
ibrs_enabled = 0;
+ if (val) {
+ /* IBRS is not supported but we try to turn it on */
+ error = -EINVAL;
+ }
}
/* Update the shadow variable */
__ibrs_enabled = ibrs_enabled;
mutex_unlock(&spec_ctrl_mutex);
-}
-inline void ibrs_enable(void)
-{
- set_ibrs_enabled(1);
+ return error;
}
-EXPORT_SYMBOL(ibrs_enable);
static int ibrs_enabled_handler(struct ctl_table *table, int write,
void __user *buffer, size_t *lenp,
loff_t *ppos)
{
int error;
- unsigned int cpu;
error = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
if (error)
return error;
- set_ibrs_enabled(__ibrs_enabled);
- return 0;
+ return set_ibrs_enabled(__ibrs_enabled);
}
#endif
Cleanup the code to match Xenial. Functional changes introduced: - Return an error when someone tries to enable IBRS via procfs on HW that doesn't have IBRS support. - Write every IBRS state change to the kernel log. - Add an IBRS state entry to /sys/devices/system/cpu/vulnerabilities/spectre_v2. CVE-2017-5715 Signed-off-by: Juerg Haefliger <juergh@canonical.com> --- arch/x86/include/asm/nospec-branch.h | 6 +++--- arch/x86/include/asm/spec_ctrl.h | 3 +++ arch/x86/kernel/acpi/cstate.c | 4 ++-- arch/x86/kernel/cpu/bugs.c | 24 +++++++++++---------- arch/x86/kernel/process.c | 6 +++--- arch/x86/kernel/smpboot.c | 4 ++-- kernel/sysctl.c | 32 +++++++++++++++++----------- 7 files changed, 45 insertions(+), 34 deletions(-)