diff mbox series

[v2,1/5] x86/speculation: Provide a debugfs file to dump SPEC_CTRL MSRs

Message ID 20230620140625.1001886-2-longman@redhat.com (mailing list archive)
State Handled Elsewhere, archived
Headers show
Series x86/speculation: Disable IBRS when idle | expand

Commit Message

Waiman Long June 20, 2023, 2:06 p.m. UTC
Sometimes it is useful to know the states the SPEC_CTRL MSRs to see what
mitigations are enabled at run time. Provide a new x86/spec_ctrl_msrs
debugfs file to dump the cached versions of the current SPEC_CTRL MSRs.

Signed-off-by: Waiman Long <longman@redhat.com>
---
 arch/x86/kernel/cpu/bugs.c | 79 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 79 insertions(+)

Comments

Peter Zijlstra June 21, 2023, 7:41 a.m. UTC | #1
On Tue, Jun 20, 2023 at 10:06:21AM -0400, Waiman Long wrote:
> Sometimes it is useful to know the states the SPEC_CTRL MSRs to see what
> mitigations are enabled at run time. Provide a new x86/spec_ctrl_msrs
> debugfs file to dump the cached versions of the current SPEC_CTRL MSRs.
> 

Pff, clearly I can't even read email anymore..

We don't do this for any of the other MSRs, so why start now?
Borislav Petkov June 21, 2023, 8:24 a.m. UTC | #2
On Wed, Jun 21, 2023 at 09:41:05AM +0200, Peter Zijlstra wrote:
> On Tue, Jun 20, 2023 at 10:06:21AM -0400, Waiman Long wrote:
> > Sometimes it is useful to know the states the SPEC_CTRL MSRs to see what
> > mitigations are enabled at run time. Provide a new x86/spec_ctrl_msrs
> > debugfs file to dump the cached versions of the current SPEC_CTRL MSRs.
> > 
> 
> Pff, clearly I can't even read email anymore..
> 
> We don't do this for any of the other MSRs, so why start now?

Hell no.

There's /sys/devices/system/cpu/vulnerabilities/ for that.

We are abstracting MSRs away from APIs - not do the backwards thing.
Waiman Long June 21, 2023, 1:47 p.m. UTC | #3
On 6/21/23 03:41, Peter Zijlstra wrote:
> On Tue, Jun 20, 2023 at 10:06:21AM -0400, Waiman Long wrote:
>> Sometimes it is useful to know the states the SPEC_CTRL MSRs to see what
>> mitigations are enabled at run time. Provide a new x86/spec_ctrl_msrs
>> debugfs file to dump the cached versions of the current SPEC_CTRL MSRs.
>>
> Pff, clearly I can't even read email anymore..
>
> We don't do this for any of the other MSRs, so why start now?

That is true since most of the MSRs are static. IOW, they don't change 
once they are set. The current way to read the content of the MSRs is 
via the /dev/cpu/<n>/msr files. There are user space tools to do that.

SPEC_CTRL, however, can be subjected to frequent changes especially when 
X86_FEATURE_KERNEL_IBRS is set. As a result, the current way of reading 
MSRs from /dev/cpu/<n>/msr doesn't quite work for SPEC_CTRL as the IBRS 
bit is always set due to the fact that the reading is done internally 
via an IPI in kernel space. That is the main reason that I add this 
debugfs file to get a good snapshot of the current set of cached 
SPEC_CTRL MSR values without the need to disturb what the CPUs are 
currently doing at that point in time.

This patch is not central to the main purpose of this patch series, but 
it does enable me to quickly verify the other patches are working 
correctly. I can take it out if people don't think it is a good idea.

Cheers,
Longman
Waiman Long June 21, 2023, 2:02 p.m. UTC | #4
On 6/21/23 04:24, Borislav Petkov wrote:
> On Wed, Jun 21, 2023 at 09:41:05AM +0200, Peter Zijlstra wrote:
>> On Tue, Jun 20, 2023 at 10:06:21AM -0400, Waiman Long wrote:
>>> Sometimes it is useful to know the states the SPEC_CTRL MSRs to see what
>>> mitigations are enabled at run time. Provide a new x86/spec_ctrl_msrs
>>> debugfs file to dump the cached versions of the current SPEC_CTRL MSRs.
>>>
>> Pff, clearly I can't even read email anymore..
>>
>> We don't do this for any of the other MSRs, so why start now?
> Hell no.
>
> There's /sys/devices/system/cpu/vulnerabilities/ for that.
>
> We are abstracting MSRs away from APIs - not do the backwards thing.
>
OK, as I have said. This is not central to the main purpose of this 
patch series. It is mostly there for verification purpose. I can 
certainly take this out.

Cheers,
Longman
diff mbox series

Patch

diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
index 182af64387d0..f6e5910a4a2d 100644
--- a/arch/x86/kernel/cpu/bugs.c
+++ b/arch/x86/kernel/cpu/bugs.c
@@ -17,6 +17,7 @@ 
 #include <linux/sched/smt.h>
 #include <linux/pgtable.h>
 #include <linux/bpf.h>
+#include <linux/debugfs.h>
 
 #include <asm/spec-ctrl.h>
 #include <asm/cmdline.h>
@@ -1733,6 +1734,84 @@  void cpu_bugs_smt_update(void)
 	mutex_unlock(&spec_ctrl_mutex);
 }
 
+#ifdef CONFIG_DEBUG_FS
+/*
+ * Provide a debugfs file to dump SPEC_CTRL MSRs of all the CPUs
+ * Consecutive MSR values are collapsed together if they are the same.
+ */
+static ssize_t spec_ctrl_msrs_read(struct file *file, char __user *user_buf,
+				   size_t count, loff_t *ppos)
+{
+	int bufsiz = min(count, PAGE_SIZE);
+	int cpu, prev_cpu, len, cnt = 0;
+	u64 val, prev_val;
+	char *buf;
+
+	/*
+	 * The MSRs info should be small enough that the whole buffer is
+	 * copied out in one call. However, user space may read it again
+	 * to see if there is any data left. Rereading the cached SPEC_CTRL
+	 * MSR values may produce a different result causing corruption in
+	 * output data. So skipping the call if *ppos is not starting from 0.
+	 */
+	if (*ppos)
+		return 0;
+
+	buf = kmalloc(bufsiz, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	for_each_possible_cpu(cpu) {
+		val = per_cpu(x86_spec_ctrl_current, cpu);
+
+		if (!cpu)
+			goto next;
+
+		if (val == prev_val)
+			continue;
+
+		if (prev_cpu == cpu - 1)
+			len = snprintf(buf + cnt, bufsiz - cnt, "CPU  %d: 0x%llx\n",
+				       prev_cpu, prev_val);
+		else
+			len = snprintf(buf + cnt, bufsiz - cnt, "CPUs %d-%d: 0x%llx\n",
+					prev_cpu, cpu - 1, prev_val);
+
+		cnt += len;
+		if (!len)
+			break;	/* Out of buffer */
+next:
+		prev_cpu = cpu;
+		prev_val = val;
+	}
+
+	if (prev_cpu == cpu - 1)
+		cnt += snprintf(buf + cnt, bufsiz - cnt, "CPU  %d: 0x%llx\n",
+			       prev_cpu, prev_val);
+	else
+		cnt += snprintf(buf + cnt, bufsiz - cnt, "CPUs %d-%d: 0x%llx\n",
+				prev_cpu, cpu - 1, prev_val);
+
+	count = simple_read_from_buffer(user_buf, count, ppos, buf, cnt);
+	kfree(buf);
+	return count;
+}
+
+static const struct file_operations fops_spec_ctrl = {
+	.read = spec_ctrl_msrs_read,
+	.llseek = default_llseek,
+};
+
+static int __init init_spec_ctrl_debugfs(void)
+{
+	if (!debugfs_create_file("spec_ctrl_msrs", 0400, arch_debugfs_dir,
+				 NULL, &fops_spec_ctrl))
+		return -ENOMEM;
+	return 0;
+}
+fs_initcall(init_spec_ctrl_debugfs);
+#endif
+
 #undef pr_fmt
 #define pr_fmt(fmt)	"Speculative Store Bypass: " fmt