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. Signed-off-by: Chao Gao Reviewed-by: Tony Lindgren Tested-by: Farrah Chen --- v4: - Make seamldr attribute permission "0400" [Dave] - Don't include implementation details in OS ABI docs [Dave] - Tag tdx_host_group as static [Kai] v3: - use #ifdef rather than .is_visible() to control P-SEAMLDR sysfs visibility [Yilun] --- .../ABI/testing/sysfs-devices-faux-tdx-host | 23 +++++++ drivers/virt/coco/tdx-host/tdx-host.c | 63 ++++++++++++++++++- 2 files changed, 85 insertions(+), 1 deletion(-) diff --git a/Documentation/ABI/testing/sysfs-devices-faux-tdx-host b/Documentation/ABI/testing/sysfs-devices-faux-tdx-host index 901abbae2e61..88a9c0b2bdfe 100644 --- a/Documentation/ABI/testing/sysfs-devices-faux-tdx-host +++ b/Documentation/ABI/testing/sysfs-devices-faux-tdx-host @@ -4,3 +4,26 @@ 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, TDX Module updates and etc. + +What: /sys/devices/faux/tdx_host/seamldr/version +Contact: linux-coco@lists.linux.dev +Description: (RO) Report 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 checks. + +What: /sys/devices/faux/tdx_host/seamldr/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 which has been loaded. This log has + a finite size which limits the number of TDX Module updates + which 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, Revision 343755-003, Chapter 3.3 + "SEAMLDR_INFO" and Chapter 4.2 "SEAMLDR.INSTALL" for more + information. diff --git a/drivers/virt/coco/tdx-host/tdx-host.c b/drivers/virt/coco/tdx-host/tdx-host.c index 0424933b2560..fd6ffb4f2ff1 100644 --- a/drivers/virt/coco/tdx-host/tdx-host.c +++ b/drivers/virt/coco/tdx-host/tdx-host.c @@ -11,6 +11,7 @@ #include #include +#include #include static const struct x86_cpu_id tdx_host_ids[] = { @@ -40,7 +41,67 @@ static struct attribute *tdx_host_attrs[] = { &dev_attr_version.attr, NULL, }; -ATTRIBUTE_GROUPS(tdx_host); + +static 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, "%u.%u.%02u\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); +} + +/* + * Open-code DEVICE_ATTR_ADMIN_RO to specify a different 'show' function + * for P-SEAMLDR version as version_show() is used for TDX Module version. + * + * admin-only readable as reading these attributes calls into P-SEAMLDR, + * which may have potential performance and system impact. + */ +static struct device_attribute dev_attr_seamldr_version = + __ATTR(version, 0400, seamldr_version_show, NULL); +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 struct attribute_group seamldr_group = { + .name = "seamldr", + .attrs = seamldr_attrs, +}; + +static const struct attribute_group *tdx_host_groups[] = { + &tdx_host_group, + &seamldr_group, + NULL, +}; static struct faux_device *fdev; -- 2.47.3