[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20251202050844.2520762-6-yilun.xu@linux.intel.com>
Date: Tue, 2 Dec 2025 13:08:43 +0800
From: Xu Yilun <yilun.xu@...ux.intel.com>
To: x86@...nel.org,
dave.hansen@...ux.intel.com,
kas@...nel.org,
linux-kernel@...r.kernel.org
Cc: chao.gao@...el.com,
rick.p.edgecombe@...el.com,
dan.j.williams@...el.com,
baolu.lu@...ux.intel.com,
yilun.xu@...ux.intel.com,
yilun.xu@...el.com,
zhenzhong.duan@...el.com,
kvm@...r.kernel.org,
adrian.hunter@...el.com
Subject: [PATCH 5/6] x86/virt/tdx: Add generic support for reading array-typed metadata
Rework metadata field reading helper to read array-typed metadata fields
in a unified way. Eliminate the need to read cpuid_config_leaves/values
in special manner.
By adding the array index to the base field_id, the array elements can
be read out. But the actual valid array index boundary should be
retrieved from other metadata fields. Otherwise TDX Module returns error
on an invalid field_id and the whole metadata reading process fails.
That leads to the special handling of these fields.
TDG.SYS.RD provides an output parameter (RDX) for next readable
field_id. Use this return value to validate the next array index and
detect actual array boundary. This makes the array-typed metadata fields
reading self-contained. Remove all special handling for them.
Signed-off-by: Xu Yilun <yilun.xu@...ux.intel.com>
---
arch/x86/virt/vmx/tdx/tdx_global_metadata.c | 99 +++++++++------------
1 file changed, 44 insertions(+), 55 deletions(-)
diff --git a/arch/x86/virt/vmx/tdx/tdx_global_metadata.c b/arch/x86/virt/vmx/tdx/tdx_global_metadata.c
index 836d97166a7a..c366bace454e 100644
--- a/arch/x86/virt/vmx/tdx/tdx_global_metadata.c
+++ b/arch/x86/virt/vmx/tdx/tdx_global_metadata.c
@@ -11,6 +11,7 @@ struct field_mapping {
u64 field_id;
int offset;
int size;
+ int count;
};
/*
@@ -34,11 +35,24 @@ struct field_mapping {
#define TD_SYSINFO_CHECK_SIZE(_field_id, _size) \
__builtin_choose_expr(MD_FIELD_SIZE(_field_id) == (_size), _size, (void)0)
-#define TD_SYSINFO_MAP(_field_id, _member) \
+#define _TD_SYSINFO_MAP(_field_id, _member, _count) \
{ .field_id = _field_id, \
.offset = offsetof(struct tdx_sys_info, _member), \
.size = TD_SYSINFO_CHECK_SIZE(_field_id, \
- sizeof_field(struct tdx_sys_info, _member)) }
+ sizeof_field(struct tdx_sys_info, _member)), \
+ .count = _count }
+
+#define TD_SYSINFO_MAP(_field_id, _member) \
+ _TD_SYSINFO_MAP(_field_id, _member, 1)
+
+#define TD_SYSINFO_MAP_ARR(_field_id, _arr) \
+ _TD_SYSINFO_MAP(_field_id, _arr[0], \
+ ARRAY_SIZE(((struct tdx_sys_info *)0)->_arr))
+
+#define TD_SYSINFO_MAP_2DARR(_field_id, _arr) \
+ _TD_SYSINFO_MAP(_field_id, _arr[0][0], \
+ ARRAY_SIZE(((struct tdx_sys_info *)0)->_arr) * \
+ ARRAY_SIZE(((struct tdx_sys_info *)0)->_arr[0]))
/* Map TD_SYSINFO fields into 'struct tdx_sys_info': */
static const struct field_mapping mappings[] = {
@@ -60,33 +74,37 @@ static const struct field_mapping mappings[] = {
TD_SYSINFO_MAP(0x1900000300000003, td_conf.xfam_fixed1),
TD_SYSINFO_MAP(0x9900000100000004, td_conf.num_cpuid_config),
TD_SYSINFO_MAP(0x9900000100000008, td_conf.max_vcpus_per_td),
+ TD_SYSINFO_MAP_ARR(0x9900000300000400, td_conf.cpuid_config_leaves),
+ TD_SYSINFO_MAP_2DARR(0x9900000300000500, td_conf.cpuid_config_values),
};
-/* Populate the following fields in special manner, separate them out. */
-static const struct field_mapping cpuid_config_leaves =
- TD_SYSINFO_MAP(0x9900000300000400, td_conf.cpuid_config_leaves[0]);
-
-static const struct field_mapping cpuid_config_values =
- TD_SYSINFO_MAP(0x9900000300000500, td_conf.cpuid_config_values[0][0]);
-
-static int read_sys_metadata_field(u64 field_id, int offset, int size,
+static int read_sys_metadata_field(const struct field_mapping *base,
struct tdx_sys_info *ts)
{
- void *field = ((void *)ts) + offset;
- struct tdx_module_args args = {};
- int ret;
-
- /*
- * TDH.SYS.RD -- reads one global metadata field
- * - RDX (in): the field to read
- * - R8 (out): the field data
- */
- args.rdx = field_id;
- ret = seamcall_prerr_ret(TDH_SYS_RD, &args);
- if (ret)
- return ret;
-
- memcpy(field, &args.r8, size);
+ int i, ret;
+
+ for (i = 0; i < base->count; i++) {
+ void *field = ((void *)ts) + base->offset + base->size * i;
+ u64 field_id = base->field_id + i;
+ struct tdx_module_args args = {};
+
+ /*
+ * TDH.SYS.RD -- reads one global metadata field
+ * - RDX (in): the field to read
+ * - RDX (out) : the next valid field ID
+ * - R8 (out): the field data
+ */
+ args.rdx = field_id;
+ ret = seamcall_prerr_ret(TDH_SYS_RD, &args);
+ if (ret)
+ return ret;
+
+ memcpy(field, &args.r8, base->size);
+
+ /* field_id + 1 is invalid, the metadata array ends */
+ if (args.rdx != field_id + 1)
+ break;
+ }
return 0;
}
@@ -98,10 +116,7 @@ static int get_tdx_sys_info(struct tdx_sys_info *sysinfo)
/* Populate 'tdx_sys_info' fields using the mapping structure above: */
for (i = 0; i < ARRAY_SIZE(mappings); i++) {
- ret = read_sys_metadata_field(mappings[i].field_id,
- mappings[i].offset,
- mappings[i].size,
- sysinfo);
+ ret = read_sys_metadata_field(&mappings[i], sysinfo);
if (ret)
return ret;
}
@@ -110,31 +125,5 @@ static int get_tdx_sys_info(struct tdx_sys_info *sysinfo)
td_conf->num_cpuid_config > ARRAY_SIZE(td_conf->cpuid_config_values))
return -EINVAL;
- /*
- * Populate 2 special fields, td_conf.cpuid_config_leaves[] and
- * td_conf.cpuid_config_values[][]
- */
- for (i = 0; i < td_conf->num_cpuid_config; i++) {
- ret = read_sys_metadata_field(cpuid_config_leaves.field_id + i,
- cpuid_config_leaves.offset +
- cpuid_config_leaves.size * i,
- cpuid_config_leaves.size,
- sysinfo);
- if (ret)
- return ret;
- }
-
- for (i = 0;
- i < td_conf->num_cpuid_config * ARRAY_SIZE(td_conf->cpuid_config_values[0]);
- i++) {
- ret = read_sys_metadata_field(cpuid_config_values.field_id + i,
- cpuid_config_values.offset +
- cpuid_config_values.size * i,
- cpuid_config_values.size,
- sysinfo);
- if (ret)
- return ret;
- }
-
return 0;
}
--
2.25.1
Powered by blists - more mailing lists