coco/tdx-host: Expose P-SEAMLDR information via sysfs

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
This commit is contained in:
Chao Gao 2026-05-20 15:28:57 -07:00 committed by Dave Hansen
parent 0988bf698a
commit 885afcf7c8
3 changed files with 98 additions and 1 deletions

View 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.

View 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);

View 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;