]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
coco/tdx-host: Expose TDX module version
authorChao Gao <chao.gao@intel.com>
Wed, 20 May 2026 22:28:53 +0000 (15:28 -0700)
committerDave Hansen <dave.hansen@linux.intel.com>
Wed, 3 Jun 2026 15:14:51 +0000 (08:14 -0700)
For TDX module updates, userspace needs to select compatible update
versions based on the current module version.

For example, the 1.5.x series runs on Sapphire Rapids but not Granite
Rapids, which needs 2.0.x. Updates are also constrained by version
distance, so a 1.5.6 module might permit updates to 1.5.7 but not to
1.5.20.

Start the process of punting the version selection logic to userspace.
Expose the TDX module version in the new faux device.

Define TDX_VERSION_FMT macro for the TDX version format since it will be
used multiple times. Also convert an existing print statement to use it.

== Background ==

For posterity, here's what other firmware mechanisms do:

1. AMD SEV leverages an existing PCI device for the PSP to expose
   metadata. TDX uses a faux device as it doesn't have PCI device
   in its architecture.

2. Microcode uses per-CPU virtual devices to report microcode revisions
   because CPUs can have different revisions. But, there is only a
   single TDX module, so exposing the TDX module version through a global
   TDX faux device is appropriate

3. ARM's CCA implementation isn't in-tree yet, but will likely follow a
   similar faux device approach, though it's unclear whether they need
   to expose firmware version information

[ dhansen: trim changelog ]

Signed-off-by: Chao Gao <chao.gao@intel.com>
Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com>
Reviewed-by: Binbin Wu <binbin.wu@linux.intel.com>
Reviewed-by: Tony Lindgren <tony.lindgren@linux.intel.com>
Reviewed-by: Xu Yilun <yilun.xu@linux.intel.com>
Reviewed-by: Kai Huang <kai.huang@intel.com>
Reviewed-by: Kiryl Shutsemau (Meta) <kas@kernel.org>
Reviewed-by: Xiaoyao Li <xiaoyao.li@intel.com>
Reviewed-by: Dave Hansen <dave.hansen@linux.intel.com>
Link: https://lore.kernel.org/all/2025073035-bulginess-rematch-b92e@gregkh/
Link: https://patch.msgid.link/20260520133909.409394-8-chao.gao@intel.com
Documentation/ABI/testing/sysfs-devices-faux-tdx-host [new file with mode: 0644]
arch/x86/include/asm/tdx.h
arch/x86/virt/vmx/tdx/tdx_global_metadata.c
drivers/virt/coco/tdx-host/tdx-host.c

diff --git a/Documentation/ABI/testing/sysfs-devices-faux-tdx-host b/Documentation/ABI/testing/sysfs-devices-faux-tdx-host
new file mode 100644 (file)
index 0000000..47d73cb
--- /dev/null
@@ -0,0 +1,5 @@
+What:          /sys/devices/faux/tdx_host/version
+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".
index 8b739ac01479341d28360c55ba256690e8fcc30d..b7f4396b5cc562bb87fcaffbfb10f3a24fa1df9a 100644 (file)
 #include <asm/tdx_global_metadata.h>
 #include <linux/pgtable.h>
 
+/*
+ * TDX module and P-SEAMLDR version convention: "major.minor.update"
+ * (e.g., "1.5.08") with zero-padded two-digit update field.
+ */
+#define TDX_VERSION_FMT "%u.%u.%02u"
+
 /*
  * Used by the #VE exception handler to gather the #VE exception
  * info from the TDX module. This is a software only structure
index c7db393a9cfb1080e34a1dc5d08843de9642ce05..d54d4227990c202c34ee224b9fce1a63dbbe224c 100644 (file)
@@ -106,7 +106,7 @@ static __init int get_tdx_sys_info(struct tdx_sys_info *sysinfo)
 
        ret = ret ?: get_tdx_sys_info_version(&sysinfo->version);
 
-       pr_info("Module version: %u.%u.%02u\n",
+       pr_info("Module version: " TDX_VERSION_FMT "\n",
                sysinfo->version.major_version,
                sysinfo->version.minor_version,
                sysinfo->version.update_version);
index c77885392b093ca18f48d86da64f2b70609fb44c..ef117a836b3a733053ae72ceb619627d26f8974d 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/device/faux.h>
 #include <linux/module.h>
 #include <linux/mod_devicetable.h>
+#include <linux/sysfs.h>
 
 #include <asm/cpu_device_id.h>
 #include <asm/tdx.h>
@@ -18,6 +19,29 @@ static const struct x86_cpu_id tdx_host_ids[] = {
 };
 MODULE_DEVICE_TABLE(x86cpu, tdx_host_ids);
 
+static ssize_t version_show(struct device *dev, struct device_attribute *attr,
+                           char *buf)
+{
+       const struct tdx_sys_info *tdx_sysinfo = tdx_get_sysinfo();
+       const struct tdx_sys_info_version *ver;
+
+       if (!tdx_sysinfo)
+               return -ENXIO;
+
+       ver = &tdx_sysinfo->version;
+
+       return sysfs_emit(buf, TDX_VERSION_FMT "\n", ver->major_version,
+                                                    ver->minor_version,
+                                                    ver->update_version);
+}
+static DEVICE_ATTR_RO(version);
+
+static struct attribute *tdx_host_attrs[] = {
+       &dev_attr_version.attr,
+       NULL,
+};
+ATTRIBUTE_GROUPS(tdx_host);
+
 static struct faux_device *fdev;
 
 static int __init tdx_host_init(void)
@@ -25,7 +49,7 @@ static int __init tdx_host_init(void)
        if (!x86_match_cpu(tdx_host_ids) || !tdx_get_sysinfo())
                return -ENODEV;
 
-       fdev = faux_device_create(KBUILD_MODNAME, NULL, NULL);
+       fdev = faux_device_create_with_groups(KBUILD_MODNAME, NULL, NULL, tdx_host_groups);
        if (!fdev)
                return -ENODEV;