lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<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

Powered by Openwall GNU/*/Linux Powered by OpenVZ