]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
coco/tdx-host: Expose P-SEAMLDR information via sysfs
authorChao Gao <chao.gao@intel.com>
Wed, 20 May 2026 22:28:57 +0000 (15:28 -0700)
committerDave Hansen <dave.hansen@linux.intel.com>
Wed, 3 Jun 2026 15:14:51 +0000 (08:14 -0700)
TDX module updates require userspace to select the appropriate module
to load. Expose necessary information to facilitate this decision. Two
values are needed:

- P-SEAMLDR version: for compatibility checks between TDX module and
     P-SEAMLDR
- num_remaining_updates: indicates how many updates can be performed

Expose them as tdx-host device attributes visible only when updates
are supported.

Note that the underlying P-SEAMLDR attributes are available regardless
of update support; this only restricts their visibility to userspace.

Signed-off-by: Chao Gao <chao.gao@intel.com>
Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com>
Reviewed-by: Kiryl Shutsemau (Meta) <kas@kernel.org>
Reviewed-by: Dave Hansen <dave.hansen@linux.intel.com>
Link: https://patch.msgid.link/20260520133909.409394-11-chao.gao@intel.com
Documentation/ABI/testing/sysfs-devices-faux-tdx-host
arch/x86/include/asm/tdx.h
drivers/virt/coco/tdx-host/tdx-host.c

index 47d73cb89f1e60cbf34cc7b3b07d36bbb504eba9..c9cb273abf32037b2dc6ece5426f014e9893d7a5 100644 (file)
@@ -3,3 +3,24 @@ Contact:       linux-coco@lists.linux.dev
 Description:   (RO) Report the version of the loaded TDX module.
                Formatted as "major.minor.update". Used by TDX module
                update tooling. Example: "1.2.03".
+
+What:          /sys/devices/faux/tdx_host/seamldr_version
+Contact:       linux-coco@lists.linux.dev
+Description:   (RO) Report the version of the loaded P-SEAMLDR.
+               Formatted as a TDX module version. Used by TDX module
+               update tooling.
+
+What:          /sys/devices/faux/tdx_host/num_remaining_updates
+Contact:       linux-coco@lists.linux.dev
+Description:   (RO) Report the number of remaining updates. TDX maintains a
+               log about each TDX module that has been loaded. This log has
+               a finite size, which limits the number of TDX module updates
+               that can be performed.
+
+               After each successful update, the number reduces by one. Once it
+               reaches zero, further updates will fail until next reboot. The
+               number is always zero if the P-SEAMLDR doesn't support updates.
+
+               See Intel Trust Domain Extensions - SEAM Loader (SEAMLDR)
+               Interface Specification, Chapter "SEAMLDR_INFO" and Chapter
+               "SEAMLDR.INSTALL" for more information.
index b7f4396b5cc562bb87fcaffbfb10f3a24fa1df9a..27376db7ddaca33229f8fbfdca856bc30fa2157e 100644 (file)
@@ -110,6 +110,12 @@ void tdx_init(void);
 const char *tdx_dump_mce_info(struct mce *m);
 const struct tdx_sys_info *tdx_get_sysinfo(void);
 
+static inline bool tdx_supports_runtime_update(const struct tdx_sys_info *sysinfo)
+{
+       /* To be enabled when kernel is ready. */
+       return false;
+}
+
 int tdx_guest_keyid_alloc(void);
 u32 tdx_get_nr_guest_keyids(void);
 void tdx_guest_keyid_free(unsigned int keyid);
index ef117a836b3a733053ae72ceb619627d26f8974d..2997311f72fa8908d30be1fc9733a6e9923f0aad 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/sysfs.h>
 
 #include <asm/cpu_device_id.h>
+#include <asm/seamldr.h>
 #include <asm/tdx.h>
 
 static const struct x86_cpu_id tdx_host_ids[] = {
@@ -40,7 +41,76 @@ static struct attribute *tdx_host_attrs[] = {
        &dev_attr_version.attr,
        NULL,
 };
-ATTRIBUTE_GROUPS(tdx_host);
+
+static const struct attribute_group tdx_host_group = {
+       .attrs = tdx_host_attrs,
+};
+
+static ssize_t seamldr_version_show(struct device *dev, struct device_attribute *attr,
+                                   char *buf)
+{
+       struct seamldr_info info;
+       int ret;
+
+       ret = seamldr_get_info(&info);
+       if (ret)
+               return ret;
+
+       return sysfs_emit(buf, TDX_VERSION_FMT "\n", info.major_version,
+                                                    info.minor_version,
+                                                    info.update_version);
+}
+
+static ssize_t num_remaining_updates_show(struct device *dev,
+                                         struct device_attribute *attr,
+                                         char *buf)
+{
+       struct seamldr_info info;
+       int ret;
+
+       ret = seamldr_get_info(&info);
+       if (ret)
+               return ret;
+
+       return sysfs_emit(buf, "%u\n", info.num_remaining_updates);
+}
+
+/*
+ * These attributes are intended for managing TDX module updates. Reading
+ * them issues a slow, serialized P-SEAMLDR query, so keep them admin-only.
+ */
+static DEVICE_ATTR_ADMIN_RO(seamldr_version);
+static DEVICE_ATTR_ADMIN_RO(num_remaining_updates);
+
+static struct attribute *seamldr_attrs[] = {
+       &dev_attr_seamldr_version.attr,
+       &dev_attr_num_remaining_updates.attr,
+       NULL,
+};
+
+static umode_t seamldr_group_visible(struct kobject *kobj, struct attribute *attr, int idx)
+{
+       const struct tdx_sys_info *sysinfo = tdx_get_sysinfo();
+
+       if (!sysinfo)
+               return 0;
+
+       if (!tdx_supports_runtime_update(sysinfo))
+               return 0;
+
+       return attr->mode;
+}
+
+static const struct attribute_group seamldr_group = {
+       .attrs = seamldr_attrs,
+       .is_visible = seamldr_group_visible,
+};
+
+static const struct attribute_group *tdx_host_groups[] = {
+       &tdx_host_group,
+       &seamldr_group,
+       NULL,
+};
 
 static struct faux_device *fdev;