[PATCH v3 4/5] x86/ibrs: Create boot option for IBRS

From: Tim Chen
Date: Tue Jan 09 2018 - 21:47:56 EST


When "spectre_v2=ibrs" is set in kernel boot option, the kernel will
enable IBRS on entry to kernel and disable IBRS on kernel exit.

The X86_FEATURE_SPEC_CTRL_IBRS will be set on the cpu
if the user opt in to use IBRS against SPECTRE V2 attack.

It is only for cases where the user require maximum level
of security.

Signed-off-by: Tim Chen <tim.c.chen@xxxxxxxxxxxxxxx>
---
Documentation/admin-guide/kernel-parameters.txt | 3 +++
arch/x86/include/asm/spec_ctrl.h | 22 ++++++++++++++++++++++
arch/x86/kernel/cpu/Makefile | 1 +
arch/x86/kernel/cpu/scattered.c | 2 ++
arch/x86/kernel/cpu/spec_ctrl.c | 23 +++++++++++++++++++++++
5 files changed, 51 insertions(+)
create mode 100644 arch/x86/include/asm/spec_ctrl.h
create mode 100644 arch/x86/kernel/cpu/spec_ctrl.c

diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index 8122b5f..c611700 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -3920,6 +3920,9 @@
off - unconditionally disable
auto - kernel detects whether your CPU model is
vulnerable
+ ibrs - Use indirect branch restricted speculation
+ (IBRS) to restrict speculation in kernel. For
+ use cases requiring maximum security.

Selecting 'on' will, and 'auto' may, choose a
mitigation method at run time according to the
diff --git a/arch/x86/include/asm/spec_ctrl.h b/arch/x86/include/asm/spec_ctrl.h
new file mode 100644
index 0000000..948959b
--- /dev/null
+++ b/arch/x86/include/asm/spec_ctrl.h
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef _ASM_X86_SPEC_CTRL_H
+#define _ASM_X86_SPEC_CTRL_H
+
+#include <asm/microcode.h>
+
+void spec_ctrl_scan_feature(struct cpuinfo_x86 *c);
+void spec_ctrl_unprotected_begin(void);
+void spec_ctrl_unprotected_end(void);
+
+static inline void __disable_indirect_speculation(void)
+{
+ native_wrmsrl(MSR_IA32_SPEC_CTRL, SPEC_CTRL_ENABLE_IBRS);
+}
+
+static inline void __enable_indirect_speculation(void)
+{
+ native_wrmsrl(MSR_IA32_SPEC_CTRL, SPEC_CTRL_DISABLE_IBRS);
+}
+
+#endif /* _ASM_X86_SPEC_CTRL_H */
diff --git a/arch/x86/kernel/cpu/Makefile b/arch/x86/kernel/cpu/Makefile
index 90cb82d..a25f1ab 100644
--- a/arch/x86/kernel/cpu/Makefile
+++ b/arch/x86/kernel/cpu/Makefile
@@ -24,6 +24,7 @@ obj-y += match.o
obj-y += bugs.o
obj-$(CONFIG_CPU_FREQ) += aperfmperf.o
obj-y += cpuid-deps.o
+obj-y += spec_ctrl.o

obj-$(CONFIG_PROC_FS) += proc.o
obj-$(CONFIG_X86_FEATURE_NAMES) += capflags.o powerflags.o
diff --git a/arch/x86/kernel/cpu/scattered.c b/arch/x86/kernel/cpu/scattered.c
index bc50c40..5b01487 100644
--- a/arch/x86/kernel/cpu/scattered.c
+++ b/arch/x86/kernel/cpu/scattered.c
@@ -8,6 +8,7 @@
#include <asm/processor.h>

#include <asm/apic.h>
+#include <asm/spec_ctrl.h>

struct cpuid_bit {
u16 feature;
@@ -57,6 +58,7 @@ void init_scattered_cpuid_features(struct cpuinfo_x86 *c)
if (regs[cb->reg] & (1 << cb->bit))
set_cpu_cap(c, cb->feature);
}
+ spec_ctrl_scan_feature(c);
}

u32 get_scattered_cpuid_leaf(unsigned int level, unsigned int sub_leaf,
diff --git a/arch/x86/kernel/cpu/spec_ctrl.c b/arch/x86/kernel/cpu/spec_ctrl.c
new file mode 100644
index 0000000..2f3d6ca
--- /dev/null
+++ b/arch/x86/kernel/cpu/spec_ctrl.c
@@ -0,0 +1,23 @@
+#include <linux/string.h>
+
+#include <asm/spec_ctrl.h>
+#include <asm/cpufeature.h>
+
+static bool ibrs_admin_enabled;
+
+void spec_ctrl_scan_feature(struct cpuinfo_x86 *c)
+{
+ if (boot_cpu_has(X86_FEATURE_SPEC_CTRL)) {
+ if (ibrs_admin_enabled)
+ set_cpu_cap(c, X86_FEATURE_SPEC_CTRL_IBRS);
+ }
+}
+
+static int __init check_ibrs_param(char *str)
+{
+ if (strcmp(str, "ibrs") == 0)
+ ibrs_admin_enabled = true;
+
+ return 0;
+}
+early_param("spectre_v2", check_ibrs_param);
--
2.9.4