From: Tim Chen <tim.c.chen@linux.intel.com>
To: Thomas Gleixner <tglx@linutronix.de>,
Andy Lutomirski <luto@kernel.org>,
Linus Torvalds <torvalds@linux-foundation.org>,
Greg KH <gregkh@linuxfoundation.org>
Cc: Tim Chen <tim.c.chen@linux.intel.com>,
Dave Hansen <dave.hansen@intel.com>,
Andrea Arcangeli <aarcange@redhat.com>,
Andi Kleen <ak@linux.intel.com>,
Arjan Van De Ven <arjan.van.de.ven@intel.com>,
David Woodhouse <dwmw@amazon.co.uk>,
linux-kernel@vger.kernel.org
Subject: [PATCH v2 4/8] x86/spec_ctrl: Add sysctl knobs to enable/disable SPEC_CTRL feature
Date: Fri, 5 Jan 2018 18:12:19 -0800 [thread overview]
Message-ID: <b77c0cfc2d50ebdaa721f95012fd735cc374f04c.1515204614.git.tim.c.chen@linux.intel.com> (raw)
In-Reply-To: <cover.1515204614.git.tim.c.chen@linux.intel.com>
In-Reply-To: <cover.1515204614.git.tim.c.chen@linux.intel.com>
From: Tim Chen <tim.c.chen@linux.intel.com>
From: Andrea Arcangeli <aarcange@redhat.com>
There are 2 ways to control IBRS
1. At boot time
noibrs kernel boot parameter will disable IBRS usage
Otherwise if the above parameters are not specified, the system
will enable ibrs and ibpb usage if the cpu supports it.
2. At run time
echo 0 > /sys/kernel/debug/x86/ibrs_enabled will turn off IBRS
echo 1 > /sys/kernel/debug/x86/ibrs_enabled will turn on IBRS in kernel
echo 2 > /sys/kernel/debug/x86/ibrs_enabled will turn on IBRS in both userspace and kernel
The implementation was updated with input and suggestions from Andrea Arcangeli.
Signed-off-by: Tim Chen <tim.c.chen@linux.intel.com>
---
arch/x86/entry/calling.h | 42 ++++++++--
arch/x86/include/asm/spec_ctrl.h | 15 ++++
arch/x86/kernel/cpu/Makefile | 1 +
arch/x86/kernel/cpu/scattered.c | 2 +
arch/x86/kernel/cpu/spec_ctrl.c | 160 +++++++++++++++++++++++++++++++++++++++
5 files changed, 214 insertions(+), 6 deletions(-)
create mode 100644 arch/x86/include/asm/spec_ctrl.h
create mode 100644 arch/x86/kernel/cpu/spec_ctrl.c
diff --git a/arch/x86/entry/calling.h b/arch/x86/entry/calling.h
index 09c870d..6b65d47 100644
--- a/arch/x86/entry/calling.h
+++ b/arch/x86/entry/calling.h
@@ -373,35 +373,55 @@ For 32-bit we have the following conventions - kernel is built with
.endm
.macro ENABLE_IBRS
- ALTERNATIVE "jmp .Lskip_\@", "", X86_FEATURE_SPEC_CTRL
+ testl $1, dynamic_ibrs
+ jz .Lskip_\@
+
PUSH_MSR_REGS
WRMSR_ASM $MSR_IA32_SPEC_CTRL, $SPEC_CTRL_FEATURE_ENABLE_IBRS
POP_MSR_REGS
+ jmp .Ldone_\@
+
.Lskip_\@:
+ lfence
+.Ldone_\@:
.endm
.macro DISABLE_IBRS
- ALTERNATIVE "jmp .Lskip_\@", "", X86_FEATURE_SPEC_CTRL
+ testl $1, dynamic_ibrs
+ jz .Lskip_\@
+
PUSH_MSR_REGS
WRMSR_ASM $MSR_IA32_SPEC_CTRL, $SPEC_CTRL_FEATURE_DISABLE_IBRS
POP_MSR_REGS
+
.Lskip_\@:
.endm
.macro ENABLE_IBRS_CLOBBER
- ALTERNATIVE "jmp .Lskip_\@", "", X86_FEATURE_SPEC_CTRL
+ testl $1, dynamic_ibrs
+ jz .Lskip_\@
+
WRMSR_ASM $MSR_IA32_SPEC_CTRL, $SPEC_CTRL_FEATURE_ENABLE_IBRS
+ jmp .Ldone_\@
+
.Lskip_\@:
+ lfence
+.Ldone_\@:
.endm
.macro DISABLE_IBRS_CLOBBER
- ALTERNATIVE "jmp .Lskip_\@", "", X86_FEATURE_SPEC_CTRL
+ testl $1, dynamic_ibrs
+ jz .Lskip_\@
+
WRMSR_ASM $MSR_IA32_SPEC_CTRL, $SPEC_CTRL_FEATURE_DISABLE_IBRS
+
.Lskip_\@:
.endm
.macro ENABLE_IBRS_SAVE_AND_CLOBBER save_reg:req
- ALTERNATIVE "jmp .Lskip_\@", "", X86_FEATURE_SPEC_CTRL
+ testl $1, dynamic_ibrs
+ jz .Lskip_\@
+
movl $MSR_IA32_SPEC_CTRL, %ecx
rdmsr
movl %eax, \save_reg
@@ -409,15 +429,25 @@ For 32-bit we have the following conventions - kernel is built with
movl $0, %edx
movl $SPEC_CTRL_FEATURE_ENABLE_IBRS, %eax
wrmsr
+ jmp .Ldone_\@
+
.Lskip_\@:
+ lfence
+.Ldone_\@:
.endm
.macro RESTORE_IBRS_CLOBBER save_reg:req
- ALTERNATIVE "jmp .Lskip_\@", "", X86_FEATURE_SPEC_CTRL
+ testl $1, dynamic_ibrs
+ jz .Lskip_\@
+
/* Set IBRS to the value saved in the save_reg */
movl $MSR_IA32_SPEC_CTRL, %ecx
movl $0, %edx
movl \save_reg, %eax
wrmsr
+ jmp .Ldone_\@
+
.Lskip_\@:
+ lfence
+.Ldone_\@:
.endm
diff --git a/arch/x86/include/asm/spec_ctrl.h b/arch/x86/include/asm/spec_ctrl.h
new file mode 100644
index 0000000..4fda38b
--- /dev/null
+++ b/arch/x86/include/asm/spec_ctrl.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef _ASM_X86_SPEC_CTRL_H
+#define _ASM_X86_SPEC_CTRL_H
+
+#include <asm/msr-index.h>
+#include <asm/cpufeatures.h>
+#include <asm/microcode.h>
+
+void scan_spec_ctrl_feature(struct cpuinfo_x86 *c);
+bool ibrs_inuse(void);
+
+extern unsigned int dynamic_ibrs;
+
+#endif /* _ASM_X86_SPEC_CTRL_H */
diff --git a/arch/x86/kernel/cpu/Makefile b/arch/x86/kernel/cpu/Makefile
index 570e8bb..3ffbd24 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-y += 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..5756d14 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);
}
+ scan_spec_ctrl_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..1641bec
--- /dev/null
+++ b/arch/x86/kernel/cpu/spec_ctrl.c
@@ -0,0 +1,160 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#include <linux/mutex.h>
+#include <linux/debugfs.h>
+#include <linux/uaccess.h>
+
+#include <asm/spec_ctrl.h>
+#include <asm/cpufeature.h>
+
+unsigned int dynamic_ibrs __read_mostly;
+EXPORT_SYMBOL_GPL(dynamic_ibrs);
+
+enum {
+ IBRS_DISABLED,
+ /* in host kernel, disabled in guest and userland */
+ IBRS_ENABLED,
+ /* in host kernel and host userland, disabled in guest */
+ IBRS_ENABLED_USER,
+ IBRS_MAX = IBRS_ENABLED_USER,
+};
+static unsigned int ibrs_enabled;
+static bool ibrs_admin_disabled;
+
+/* mutex to serialize IBRS control changes */
+DEFINE_MUTEX(spec_ctrl_mutex);
+
+void scan_spec_ctrl_feature(struct cpuinfo_x86 *c)
+{
+ if ((!c->cpu_index) && (boot_cpu_has(X86_FEATURE_SPEC_CTRL))) {
+ if (!ibrs_admin_disabled) {
+ dynamic_ibrs = 1;
+ ibrs_enabled = IBRS_ENABLED;
+ }
+ }
+}
+EXPORT_SYMBOL_GPL(scan_spec_ctrl_feature);
+
+/*
+ * Used after boot phase to rescan spec_ctrl feature,
+ * serialize scan with spec_ctrl_mutex.
+ */
+void rescan_spec_ctrl_feature(struct cpuinfo_x86 *c)
+{
+ mutex_lock(&spec_ctrl_mutex);
+ if (boot_cpu_has(X86_FEATURE_SPEC_CTRL)) {
+ if (!ibrs_admin_disabled) {
+ dynamic_ibrs = 1;
+ ibrs_enabled = IBRS_ENABLED;
+ }
+ }
+ mutex_unlock(&spec_ctrl_mutex);
+}
+EXPORT_SYMBOL_GPL(rescan_spec_ctrl_feature);
+
+bool ibrs_inuse(void)
+{
+ return ibrs_enabled == IBRS_ENABLED;
+}
+EXPORT_SYMBOL_GPL(ibrs_inuse);
+
+static int __init noibrs(char *str)
+{
+ ibrs_admin_disabled = true;
+ ibrs_enabled = IBRS_DISABLED;
+
+ return 0;
+}
+early_param("noibrs", noibrs);
+
+static ssize_t __enabled_read(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos, unsigned int *field)
+{
+ char buf[32];
+ unsigned int len;
+
+ len = sprintf(buf, "%d\n", READ_ONCE(*field));
+ return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static ssize_t ibrs_enabled_read(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ return __enabled_read(file, user_buf, count, ppos, &ibrs_enabled);
+}
+
+static void spec_ctrl_flush_all_cpus(u32 msr_nr, u64 val)
+{
+ int cpu;
+
+ get_online_cpus();
+ for_each_online_cpu(cpu)
+ wrmsrl_on_cpu(cpu, msr_nr, val);
+ put_online_cpus();
+}
+
+static ssize_t ibrs_enabled_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ char buf[32];
+ ssize_t len;
+ unsigned int enable;
+
+ len = min(count, sizeof(buf) - 1);
+ if (copy_from_user(buf, user_buf, len))
+ return -EFAULT;
+
+ buf[len] = '\0';
+ if (kstrtouint(buf, 0, &enable))
+ return -EINVAL;
+
+ if (enable > IBRS_MAX)
+ return -EINVAL;
+
+ if (!boot_cpu_has(X86_FEATURE_SPEC_CTRL)) {
+ ibrs_enabled = IBRS_DISABLED;
+ return -EINVAL;
+ }
+
+ mutex_lock(&spec_ctrl_mutex);
+
+ if (enable == IBRS_DISABLED) {
+ /* disable IBRS usage */
+ ibrs_admin_disabled = true;
+ dynamic_ibrs = 0;
+ spec_ctrl_flush_all_cpus(MSR_IA32_SPEC_CTRL,
+ SPEC_CTRL_FEATURE_DISABLE_IBRS);
+
+ } else if (enable == IBRS_ENABLED) {
+ /* enable IBRS usage in kernel */
+ ibrs_admin_disabled = false;
+ dynamic_ibrs = 1;
+
+ } else if (enable == IBRS_ENABLED_USER) {
+ /* enable IBRS all the time in both userspace and kernel */
+ ibrs_admin_disabled = false;
+ dynamic_ibrs = 0;
+ spec_ctrl_flush_all_cpus(MSR_IA32_SPEC_CTRL,
+ SPEC_CTRL_FEATURE_ENABLE_IBRS);
+ }
+
+ ibrs_enabled = enable;
+
+ mutex_unlock(&spec_ctrl_mutex);
+ return count;
+}
+
+static const struct file_operations fops_ibrs_enabled = {
+ .read = ibrs_enabled_read,
+ .write = ibrs_enabled_write,
+ .llseek = default_llseek,
+};
+
+static int __init debugfs_spec_ctrl(void)
+{
+ debugfs_create_file("ibrs_enabled", S_IRUSR | S_IWUSR,
+ arch_debugfs_dir, NULL, &fops_ibrs_enabled);
+ return 0;
+}
+late_initcall(debugfs_spec_ctrl);
--
2.9.4
next prev parent reply other threads:[~2018-01-06 2:34 UTC|newest]
Thread overview: 72+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-01-06 2:12 [PATCH v2 0/8] IBRS patch series Tim Chen
2018-01-06 2:12 ` [PATCH v2 1/8] x86/feature: Detect the x86 IBRS feature to control Speculation Tim Chen
2018-01-06 12:56 ` Borislav Petkov
2018-01-07 17:14 ` Tim Chen
2018-01-07 18:31 ` Borislav Petkov
2018-01-09 18:13 ` Dave Hansen
2018-01-09 18:55 ` Borislav Petkov
2018-01-08 16:14 ` Paolo Bonzini
2018-01-09 10:39 ` Paolo Bonzini
2018-01-09 17:53 ` Tim Chen
2018-01-09 17:58 ` Paolo Bonzini
2018-01-09 22:59 ` Tim Chen
2018-01-18 23:28 ` Andy Lutomirski
2018-01-06 2:12 ` [PATCH v2 2/8] x86/enter: MACROS to set/clear IBRS Tim Chen
2018-01-07 12:03 ` Borislav Petkov
2018-01-07 17:12 ` Tim Chen
2018-01-07 18:44 ` Borislav Petkov
2018-01-08 22:24 ` Tim Chen
2018-01-06 2:12 ` [PATCH v2 3/8] x86/enter: Use IBRS on syscall and interrupts Tim Chen
2018-01-07 19:27 ` Borislav Petkov
2018-01-06 2:12 ` Tim Chen [this message]
2018-01-06 3:12 ` [PATCH v2 4/8] x86/spec_ctrl: Add sysctl knobs to enable/disable SPEC_CTRL feature Dave Hansen
2018-01-08 12:47 ` Peter Zijlstra
2018-01-08 16:14 ` Peter Zijlstra
2018-01-08 17:28 ` Tim Chen
2018-01-08 17:42 ` Peter Zijlstra
2018-01-08 19:34 ` Woodhouse, David
2018-01-08 19:52 ` Lu, Hongjiu
2018-01-09 10:40 ` Thomas Gleixner
2018-01-09 17:55 ` Tim Chen
2018-01-09 18:13 ` David Woodhouse
2018-01-09 20:31 ` Tim Chen
2018-01-27 13:59 ` Konrad Rzeszutek Wilk
2018-01-27 14:26 ` David Woodhouse
2018-01-06 8:54 ` Greg KH
2018-01-06 18:10 ` Tim Chen
2018-01-06 21:25 ` Konrad Rzeszutek Wilk
2018-01-07 8:20 ` Greg KH
2018-01-06 14:41 ` Konrad Rzeszutek Wilk
2018-01-06 17:33 ` Dave Hansen
2018-01-06 17:41 ` Van De Ven, Arjan
2018-01-06 19:22 ` Dave Hansen
2018-01-06 19:47 ` Thomas Gleixner
2018-01-06 21:32 ` Konrad Rzeszutek Wilk
2018-01-06 21:34 ` Van De Ven, Arjan
2018-01-06 21:41 ` Konrad Rzeszutek Wilk
2018-01-06 21:44 ` Van De Ven, Arjan
2018-01-06 21:39 ` Thomas Gleixner
2018-01-06 21:46 ` Is: Linus, name for 'spectre' variable. Was:Re: " Konrad Rzeszutek Wilk
2018-01-06 18:23 ` Tim Chen
2018-01-06 18:20 ` Tim Chen
2018-01-08 15:08 ` Peter Zijlstra
2018-01-08 15:29 ` Van De Ven, Arjan
2018-01-08 17:02 ` Tim Chen
2018-01-08 15:11 ` Peter Zijlstra
2018-01-08 15:15 ` Peter Zijlstra
2018-01-08 15:53 ` Peter Zijlstra
2018-01-09 0:29 ` Borislav Petkov
2018-01-09 18:05 ` Tim Chen
2018-01-06 2:12 ` [PATCH v2 5/8] x86/idle: Disable IBRS entering idle and enable it on wakeup Tim Chen
2018-01-06 2:12 ` [PATCH v2 6/8] x86/microcode: Recheck IBRS features on microcode reload Tim Chen
2018-01-06 12:09 ` Woodhouse, David
2018-01-09 0:34 ` Borislav Petkov
2018-01-06 2:12 ` [PATCH v2 7/8] x86: Do not use dynamic IBRS if retpoline is enabled Tim Chen
2018-01-06 2:12 ` [PATCH v2 8/8] x86: Use IBRS for firmware update path Tim Chen
2018-01-06 8:55 ` Greg KH
2018-01-06 8:57 ` Greg KH
2018-01-06 6:43 ` [PATCH v2 0/8] IBRS patch series Tim Chen
2018-01-06 12:00 ` Woodhouse, David
2018-01-06 12:11 ` Woodhouse, David
2018-01-08 17:43 [PATCH v2 4/8] x86/spec_ctrl: Add sysctl knobs to enable/disable SPEC_CTRL feature Alexey Dobriyan
2018-01-08 18:30 ` Andrea Arcangeli
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=b77c0cfc2d50ebdaa721f95012fd735cc374f04c.1515204614.git.tim.c.chen@linux.intel.com \
--to=tim.c.chen@linux.intel.com \
--cc=aarcange@redhat.com \
--cc=ak@linux.intel.com \
--cc=arjan.van.de.ven@intel.com \
--cc=dave.hansen@intel.com \
--cc=dwmw@amazon.co.uk \
--cc=gregkh@linuxfoundation.org \
--cc=linux-kernel@vger.kernel.org \
--cc=luto@kernel.org \
--cc=tglx@linutronix.de \
--cc=torvalds@linux-foundation.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®