[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250523095322.88774-8-chao.gao@intel.com>
Date: Fri, 23 May 2025 02:52:30 -0700
From: Chao Gao <chao.gao@...el.com>
To: linux-coco@...ts.linux.dev,
x86@...nel.org,
kvm@...r.kernel.org
Cc: seanjc@...gle.com,
pbonzini@...hat.com,
eddie.dong@...el.com,
kirill.shutemov@...el.com,
dave.hansen@...el.com,
dan.j.williams@...el.com,
kai.huang@...el.com,
isaku.yamahata@...el.com,
elena.reshetova@...el.com,
rick.p.edgecombe@...el.com,
Chao Gao <chao.gao@...el.com>,
Farrah Chen <farrah.chen@...el.com>,
"Kirill A. Shutemov" <kirill.shutemov@...ux.intel.com>,
Dave Hansen <dave.hansen@...ux.intel.com>,
Thomas Gleixner <tglx@...utronix.de>,
Ingo Molnar <mingo@...hat.com>,
Borislav Petkov <bp@...en8.de>,
"H. Peter Anvin" <hpa@...or.com>,
linux-kernel@...r.kernel.org
Subject: [RFC PATCH 07/20] x86/virt/tdx: Expose SEAMLDR information via sysfs
TD-Preserving updates depend on a userspace tool to select the appropriate
module to load. To facilitate this decision-making process, expose the
necessary information to userspace.
SEAMLDR version information can be used for compatibility check and
num_remaining_updates indicates how many updates can still be performed.
SEAMLDR serves as the foundation of TDX, as it is responsible for loading
the TDX module and, in other words, enabling the entire TDX system.
Therefore, attach its attributes to the root device of the new TDX virtual
subsystem.
Signed-off-by: Chao Gao <chao.gao@...el.com>
Tested-by: Farrah Chen <farrah.chen@...el.com>
---
Documentation/ABI/testing/sysfs-devices-tdx | 24 ++++++++++++++
arch/x86/virt/vmx/tdx/seamldr.c | 35 ++++++++++++++++++++-
arch/x86/virt/vmx/tdx/seamldr.h | 14 +++++++++
arch/x86/virt/vmx/tdx/tdx.c | 14 ++++++++-
4 files changed, 85 insertions(+), 2 deletions(-)
create mode 100644 arch/x86/virt/vmx/tdx/seamldr.h
diff --git a/Documentation/ABI/testing/sysfs-devices-tdx b/Documentation/ABI/testing/sysfs-devices-tdx
index ccbe6431241e..112f0738253b 100644
--- a/Documentation/ABI/testing/sysfs-devices-tdx
+++ b/Documentation/ABI/testing/sysfs-devices-tdx
@@ -6,3 +6,27 @@ Description: (RO) Report the version of the loaded TDX module. The TDX module
version is formatted as x.y.z, where "x" is the major version,
"y" is the minor version and "z" is the update version. Versions
are used for bug reporting, TD-Preserving updates and etc.
+
+What: /sys/devices/virtual/tdx/seamldr/version
+Date: March 2025
+KernelVersion: v6.15
+Contact: linux-coco@...ts.linux.dev
+Description: (RO) Reports the version of the loaded SEAM loader. The SEAM
+ loader version is formatted as x.y.z, where "x" is the major
+ version, "y" is the minor version and "z" is the update version.
+ Versions are used for bug reporting and compatibility check.
+
+What: /sys/devices/virtual/tdx/seamldr/num_remaining_updates
+Date: March 2025
+KernelVersion: v6.15
+Contact: linux-coco@...ts.linux.dev
+Description: (RO) Reports the number of remaining updates that can be
+ performed via TD-Preserving updates. It is always zero if
+ SEAMLDR doesn't TD-Preserving updates. Otherwise, it is an
+ arch-specific value after bootup. This value decreases by one
+ after each successful TD-Preserving update. Once it reaches
+ zero, further TD-Preserving updates will fail until next reboot.
+
+ See IntelĀ® Trust Domain Extensions - SEAM Loader (SEAMLDR)
+ Interface Specification Chapter 3.3 "SEAMLDR_INFO" and Chapter
+ 4.2 "SEAMLDR.INSTALL" for more information.
diff --git a/arch/x86/virt/vmx/tdx/seamldr.c b/arch/x86/virt/vmx/tdx/seamldr.c
index c2771323729c..b628555daf55 100644
--- a/arch/x86/virt/vmx/tdx/seamldr.c
+++ b/arch/x86/virt/vmx/tdx/seamldr.c
@@ -7,9 +7,13 @@
#define pr_fmt(fmt) "seamldr: " fmt
#include <linux/cleanup.h>
+#include <linux/device.h>
+#include <linux/kobject.h>
+#include <linux/sysfs.h>
#include "tdx.h"
#include "../vmx.h"
+#include "seamldr.h"
/* P-SEAMLDR SEAMCALL leaf function */
#define P_SEAMLDR_INFO 0x8000000000000000
@@ -62,7 +66,36 @@ static inline int seamldr_call(u64 fn, struct tdx_module_args *args)
return ret;
}
-static __maybe_unused int get_seamldr_info(void)
+static ssize_t version_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ return sysfs_emit(buf, "%u.%u.%u\n", seamldr_info.major_version,
+ seamldr_info.minor_version,
+ seamldr_info.update_version);
+}
+
+static ssize_t num_remaining_updates_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return sysfs_emit(buf, "%u\n", seamldr_info.num_remaining_updates);
+}
+
+static DEVICE_ATTR_RO(version);
+static DEVICE_ATTR_RO(num_remaining_updates);
+
+static struct attribute *seamldr_attrs[] = {
+ &dev_attr_version.attr,
+ &dev_attr_num_remaining_updates.attr,
+ NULL,
+};
+
+struct attribute_group seamldr_group = {
+ .name = "seamldr",
+ .attrs = seamldr_attrs,
+};
+
+int get_seamldr_info(void)
{
struct tdx_module_args args = { .rcx = __pa(&seamldr_info) };
diff --git a/arch/x86/virt/vmx/tdx/seamldr.h b/arch/x86/virt/vmx/tdx/seamldr.h
new file mode 100644
index 000000000000..15597cb5036d
--- /dev/null
+++ b/arch/x86/virt/vmx/tdx/seamldr.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _X86_VIRT_VMX_TDX_SEAMLDR_H
+#define _X86_VIRT_VMX_TDX_SEAMLDR_H
+
+#ifdef CONFIG_INTEL_TDX_MODULE_UPDATE
+extern struct attribute_group seamldr_group;
+#define SEAMLDR_GROUP (&seamldr_group)
+int get_seamldr_info(void);
+#else
+#define SEAMLDR_GROUP NULL
+static inline int get_seamldr_info(void) { return 0; }
+#endif
+
+#endif
diff --git a/arch/x86/virt/vmx/tdx/tdx.c b/arch/x86/virt/vmx/tdx/tdx.c
index 5f1f463ddfe1..aa6a23d46494 100644
--- a/arch/x86/virt/vmx/tdx/tdx.c
+++ b/arch/x86/virt/vmx/tdx/tdx.c
@@ -41,6 +41,7 @@
#include <asm/processor.h>
#include <asm/mce.h>
#include "tdx.h"
+#include "seamldr.h"
static u32 tdx_global_keyid __ro_after_init;
static u32 tdx_guest_keyid_start __ro_after_init;
@@ -1147,13 +1148,24 @@ static struct tdx_tsm *init_tdx_tsm(void)
return no_free_ptr(tsm);
}
+static const struct attribute_group *tdx_subsys_groups[] = {
+ SEAMLDR_GROUP,
+ NULL,
+};
+
static void tdx_subsys_init(void)
{
struct tdx_tsm *tdx_tsm;
int err;
+ err = get_seamldr_info();
+ if (err) {
+ pr_err("failed to get seamldr info %d\n", err);
+ return;
+ }
+
/* Establish subsystem for global TDX module attributes */
- err = subsys_virtual_register(&tdx_subsys, NULL);
+ err = subsys_virtual_register(&tdx_subsys, tdx_subsys_groups);
if (err) {
pr_err("failed to register tdx_subsys %d\n", err);
return;
--
2.47.1
Powered by blists - more mailing lists