mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH 0/2] x86/virt/tdx: Print TDX module version to dmesg
@ 2026-01-08  0:31 Vishal Verma
  2026-01-08  0:31 ` [PATCH 1/2] x86/virt/tdx: Retrieve TDX module version Vishal Verma
  2026-01-08  0:31 ` [PATCH 2/2] x86/virt/tdx: Print TDX module version during init Vishal Verma
  0 siblings, 2 replies; 21+ messages in thread
From: Vishal Verma @ 2026-01-08  0:31 UTC (permalink / raw)
  To: linux-kernel, linux-coco, kvm
  Cc: x86, Chao Gao, Dan Williams, Kai Huang, Thomas Gleixner,
	Ingo Molnar, Borislav Petkov, Dave Hansen, H. Peter Anvin,
	Kiryl Shutsemau, Rick Edgecombe, Vishal Verma

=== Problem & Solution ===

Currently, there is neither an ABI, nor any other way to determine from
the host system, what version of the TDX module is running. A sysfs ABI
for this has been proposed in [1], but it may need additional discussion.

Many/most TDX developers already carry patches like this in their
development branches. It can be tricky to know which TDX module is
actually loaded on a system, and so this functionality has been needed
regularly for development and processing bug reports. Hence, it is
prudent to break out the patches to retrieve and print the TDX module
version, as those parts are very straightforward, and get some level of
debugability and traceability for TDX host systems.

=== Dependencies ===

None. This is based on v6.19-rc4, and applies cleanly to tip.git.

=== Patch details ===

Patch 1 is a prerequisite that adds the infrastructure to retrieve the
TDX module version from its global metadata. This was originally posted in [2].

Patch 2 is based on a patch from Kai Huang [3], and prints the version to
dmesg during init.

=== Testing ===

This has passed the usual suite of tests, including successful 0day
builds, KVM Unit tests, KVM selftests, a TD creation smoke test, and
selected KVM tests from the Avocado test suite.

[1]: https://lore.kernel.org/all/20260105074350.98564-1-chao.gao@intel.com/
[2]: https://lore.kernel.org/all/20260105074350.98564-2-chao.gao@intel.com/
[3]: https://lore.kernel.org/all/57eaa1b17429315f8b5207774307f3c1dd40cf37.1730118186.git.kai.huang@intel.com/

Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
---
Chao Gao (1):
      x86/virt/tdx: Retrieve TDX module version

Vishal Verma (1):
      x86/virt/tdx: Print TDX module version during init

 arch/x86/include/asm/tdx_global_metadata.h  |  7 +++++++
 arch/x86/virt/vmx/tdx/tdx.c                 |  5 +++++
 arch/x86/virt/vmx/tdx/tdx_global_metadata.c | 16 ++++++++++++++++
 3 files changed, 28 insertions(+)
---
base-commit: 9ace4753a5202b02191d54e9fdf7f9e3d02b85eb
change-id: 20260107-tdx_print_module_version-e4ca7edc2022

Best regards,
--  
Vishal Verma <vishal.l.verma@intel.com>


^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH 1/2] x86/virt/tdx: Retrieve TDX module version
  2026-01-08  0:31 [PATCH 0/2] x86/virt/tdx: Print TDX module version to dmesg Vishal Verma
@ 2026-01-08  0:31 ` Vishal Verma
  2026-01-08 10:41   ` Kiryl Shutsemau
  2026-01-08 20:18   ` Edgecombe, Rick P
  2026-01-08  0:31 ` [PATCH 2/2] x86/virt/tdx: Print TDX module version during init Vishal Verma
  1 sibling, 2 replies; 21+ messages in thread
From: Vishal Verma @ 2026-01-08  0:31 UTC (permalink / raw)
  To: linux-kernel, linux-coco, kvm
  Cc: x86, Chao Gao, Dan Williams, Kai Huang, Thomas Gleixner,
	Ingo Molnar, Borislav Petkov, Dave Hansen, H. Peter Anvin,
	Kiryl Shutsemau, Rick Edgecombe, Vishal Verma

From: Chao Gao <chao.gao@intel.com>

Each TDX module has several bits of metadata about which specific TDX
module it is. The primary bit of info is the version, which has an x.y.z
format, where x represents the major version, y the minor version, and z
the update version. Knowing the running TDX Module version is valuable
for bug reporting and debugging. Note that the module does expose other
pieces of version-related metadata, such as build number and date. Those
aren't retrieved for now, that can be added if needed in the future.

Retrieve the TDX Module version using the existing metadata reading
interface. Later changes will expose this information. The metadata
reading interfaces have existed for quite some time, so this will work
with older versions of the TDX module as well - i.e. this isn't a new
interface.

As a side note, the global metadata reading code was originally set up
to be auto-generated from a JSON definition [1]. However, later [2] this
was found to be unsustainable, and the autogeneration approach was
dropped in favor of just manually adding fields as needed (e.g. as in
this patch).

Signed-off-by: Chao Gao <chao.gao@intel.com>
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
Cc: Rick Edgecombe <rick.p.edgecombe@intel.com>
Cc: Kai Huang <kai.huang@intel.com>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Dan Williams <dan.j.williams@intel.com>
Link: https://lore.kernel.org/kvm/CABgObfYXUxqQV_FoxKjC8U3t5DnyM45nz5DpTxYZv2x_uFK_Kw@mail.gmail.com/ # [1]
Link: https://lore.kernel.org/all/1e7bcbad-eb26-44b7-97ca-88ab53467212@intel.com/ # [2]
---
 arch/x86/include/asm/tdx_global_metadata.h  |  7 +++++++
 arch/x86/virt/vmx/tdx/tdx_global_metadata.c | 16 ++++++++++++++++
 2 files changed, 23 insertions(+)

diff --git a/arch/x86/include/asm/tdx_global_metadata.h b/arch/x86/include/asm/tdx_global_metadata.h
index 060a2ad744bff..40689c8dc67eb 100644
--- a/arch/x86/include/asm/tdx_global_metadata.h
+++ b/arch/x86/include/asm/tdx_global_metadata.h
@@ -5,6 +5,12 @@
 
 #include <linux/types.h>
 
+struct tdx_sys_info_version {
+	u16 minor_version;
+	u16 major_version;
+	u16 update_version;
+};
+
 struct tdx_sys_info_features {
 	u64 tdx_features0;
 };
@@ -35,6 +41,7 @@ struct tdx_sys_info_td_conf {
 };
 
 struct tdx_sys_info {
+	struct tdx_sys_info_version version;
 	struct tdx_sys_info_features features;
 	struct tdx_sys_info_tdmr tdmr;
 	struct tdx_sys_info_td_ctrl td_ctrl;
diff --git a/arch/x86/virt/vmx/tdx/tdx_global_metadata.c b/arch/x86/virt/vmx/tdx/tdx_global_metadata.c
index 13ad2663488b1..0454124803f36 100644
--- a/arch/x86/virt/vmx/tdx/tdx_global_metadata.c
+++ b/arch/x86/virt/vmx/tdx/tdx_global_metadata.c
@@ -7,6 +7,21 @@
  * Include this file to other C file instead.
  */
 
+static int get_tdx_sys_info_version(struct tdx_sys_info_version *sysinfo_version)
+{
+	int ret = 0;
+	u64 val;
+
+	if (!ret && !(ret = read_sys_metadata_field(0x0800000100000003, &val)))
+		sysinfo_version->minor_version = val;
+	if (!ret && !(ret = read_sys_metadata_field(0x0800000100000004, &val)))
+		sysinfo_version->major_version = val;
+	if (!ret && !(ret = read_sys_metadata_field(0x0800000100000005, &val)))
+		sysinfo_version->update_version = val;
+
+	return ret;
+}
+
 static int get_tdx_sys_info_features(struct tdx_sys_info_features *sysinfo_features)
 {
 	int ret = 0;
@@ -89,6 +104,7 @@ static int get_tdx_sys_info(struct tdx_sys_info *sysinfo)
 {
 	int ret = 0;
 
+	ret = ret ?: get_tdx_sys_info_version(&sysinfo->version);
 	ret = ret ?: get_tdx_sys_info_features(&sysinfo->features);
 	ret = ret ?: get_tdx_sys_info_tdmr(&sysinfo->tdmr);
 	ret = ret ?: get_tdx_sys_info_td_ctrl(&sysinfo->td_ctrl);

-- 
2.52.0


^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH 2/2] x86/virt/tdx: Print TDX module version during init
  2026-01-08  0:31 [PATCH 0/2] x86/virt/tdx: Print TDX module version to dmesg Vishal Verma
  2026-01-08  0:31 ` [PATCH 1/2] x86/virt/tdx: Retrieve TDX module version Vishal Verma
@ 2026-01-08  0:31 ` Vishal Verma
  2026-01-08 10:50   ` Kiryl Shutsemau
  2026-01-08 20:24   ` Edgecombe, Rick P
  1 sibling, 2 replies; 21+ messages in thread
From: Vishal Verma @ 2026-01-08  0:31 UTC (permalink / raw)
  To: linux-kernel, linux-coco, kvm
  Cc: x86, Chao Gao, Dan Williams, Kai Huang, Thomas Gleixner,
	Ingo Molnar, Borislav Petkov, Dave Hansen, H. Peter Anvin,
	Kiryl Shutsemau, Rick Edgecombe, Vishal Verma

It is useful to print the TDX module version in dmesg logs. This allows
for a quick spot check for whether the correct/expected TDX module is
being loaded, and also creates a record for any future problems being
investigated. This was also requested in [1].

Include the version in the log messages during init, e.g.:

  virt/tdx: TDX module version: 1.5.24
  virt/tdx: 1034220 KB allocated for PAMT
  virt/tdx: module initialized

..followed by remaining TDX initialization messages (or errors).

Print the version early in init_tdx_module(), right after the global
metadata is read, which makes it available even if there are subsequent
initialization failures.

Based on a patch by Kai Huang <kai.huang@intel.com> [2]

Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
Reviewed-by: Chao Gao <chao.gao@intel.com>
Cc: Chao Gao <chao.gao@intel.com>
Cc: Rick Edgecombe <rick.p.edgecombe@intel.com>
Cc: Kai Huang <kai.huang@intel.com>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Dan Williams <dan.j.williams@intel.com>
Link: https://lore.kernel.org/all/CAGtprH8eXwi-TcH2+-Fo5YdbEwGmgLBh9ggcDvd6N=bsKEJ_WQ@mail.gmail.com/ # [1]
Link: https://lore.kernel.org/all/6b5553756f56a8e3222bfc36d0bdb3e5192137b7.1731318868.git.kai.huang@intel.com # [2]
---
 arch/x86/virt/vmx/tdx/tdx.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/x86/virt/vmx/tdx/tdx.c b/arch/x86/virt/vmx/tdx/tdx.c
index 5ce4ebe99774..fba00ddc11f1 100644
--- a/arch/x86/virt/vmx/tdx/tdx.c
+++ b/arch/x86/virt/vmx/tdx/tdx.c
@@ -1084,6 +1084,11 @@ static int init_tdx_module(void)
 	if (ret)
 		return ret;
 
+	pr_info("Module version: %u.%u.%02u\n",
+		tdx_sysinfo.version.major_version,
+		tdx_sysinfo.version.minor_version,
+		tdx_sysinfo.version.update_version);
+
 	/* Check whether the kernel can support this module */
 	ret = check_features(&tdx_sysinfo);
 	if (ret)

-- 
2.52.0


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 1/2] x86/virt/tdx: Retrieve TDX module version
  2026-01-08  0:31 ` [PATCH 1/2] x86/virt/tdx: Retrieve TDX module version Vishal Verma
@ 2026-01-08 10:41   ` Kiryl Shutsemau
  2026-01-08 20:18   ` Edgecombe, Rick P
  1 sibling, 0 replies; 21+ messages in thread
From: Kiryl Shutsemau @ 2026-01-08 10:41 UTC (permalink / raw)
  To: Vishal Verma
  Cc: linux-kernel, linux-coco, kvm, x86, Chao Gao, Dan Williams,
	Kai Huang, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	Dave Hansen, H. Peter Anvin, Rick Edgecombe

On Wed, Jan 07, 2026 at 05:31:28PM -0700, Vishal Verma wrote:
> From: Chao Gao <chao.gao@intel.com>
> 
> Each TDX module has several bits of metadata about which specific TDX
> module it is. The primary bit of info is the version, which has an x.y.z
> format, where x represents the major version, y the minor version, and z
> the update version. Knowing the running TDX Module version is valuable
> for bug reporting and debugging. Note that the module does expose other
> pieces of version-related metadata, such as build number and date. Those
> aren't retrieved for now, that can be added if needed in the future.
> 
> Retrieve the TDX Module version using the existing metadata reading
> interface. Later changes will expose this information. The metadata
> reading interfaces have existed for quite some time, so this will work
> with older versions of the TDX module as well - i.e. this isn't a new
> interface.
> 
> As a side note, the global metadata reading code was originally set up
> to be auto-generated from a JSON definition [1]. However, later [2] this
> was found to be unsustainable, and the autogeneration approach was
> dropped in favor of just manually adding fields as needed (e.g. as in
> this patch).
> 
> Signed-off-by: Chao Gao <chao.gao@intel.com>
> Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
> Cc: Rick Edgecombe <rick.p.edgecombe@intel.com>
> Cc: Kai Huang <kai.huang@intel.com>
> Cc: Dave Hansen <dave.hansen@linux.intel.com>
> Cc: Dan Williams <dan.j.williams@intel.com>
> Link: https://lore.kernel.org/kvm/CABgObfYXUxqQV_FoxKjC8U3t5DnyM45nz5DpTxYZv2x_uFK_Kw@mail.gmail.com/ # [1]
> Link: https://lore.kernel.org/all/1e7bcbad-eb26-44b7-97ca-88ab53467212@intel.com/ # [2]
> ---
>  arch/x86/include/asm/tdx_global_metadata.h  |  7 +++++++
>  arch/x86/virt/vmx/tdx/tdx_global_metadata.c | 16 ++++++++++++++++
>  2 files changed, 23 insertions(+)
> 
> diff --git a/arch/x86/include/asm/tdx_global_metadata.h b/arch/x86/include/asm/tdx_global_metadata.h
> index 060a2ad744bff..40689c8dc67eb 100644
> --- a/arch/x86/include/asm/tdx_global_metadata.h
> +++ b/arch/x86/include/asm/tdx_global_metadata.h
> @@ -5,6 +5,12 @@
>  
>  #include <linux/types.h>
>  
> +struct tdx_sys_info_version {
> +	u16 minor_version;
> +	u16 major_version;
> +	u16 update_version;
> +};
> +
>  struct tdx_sys_info_features {
>  	u64 tdx_features0;
>  };
> @@ -35,6 +41,7 @@ struct tdx_sys_info_td_conf {
>  };
>  
>  struct tdx_sys_info {
> +	struct tdx_sys_info_version version;

Creates a 2 byte hole. Just enough to squeeze INTERNAL_VERSION there.
Just saying :P

But patch looks good to me:

Reviewed-by: Kiryl Shutsemau <kas@kernel.org>

-- 
  Kiryl Shutsemau / Kirill A. Shutemov

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 2/2] x86/virt/tdx: Print TDX module version during init
  2026-01-08  0:31 ` [PATCH 2/2] x86/virt/tdx: Print TDX module version during init Vishal Verma
@ 2026-01-08 10:50   ` Kiryl Shutsemau
  2026-01-08 18:39     ` Verma, Vishal L
  2026-01-08 20:24   ` Edgecombe, Rick P
  1 sibling, 1 reply; 21+ messages in thread
From: Kiryl Shutsemau @ 2026-01-08 10:50 UTC (permalink / raw)
  To: Vishal Verma
  Cc: linux-kernel, linux-coco, kvm, x86, Chao Gao, Dan Williams,
	Kai Huang, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	Dave Hansen, H. Peter Anvin, Rick Edgecombe

On Wed, Jan 07, 2026 at 05:31:29PM -0700, Vishal Verma wrote:
> It is useful to print the TDX module version in dmesg logs. This allows
> for a quick spot check for whether the correct/expected TDX module is
> being loaded, and also creates a record for any future problems being
> investigated. This was also requested in [1].
> 
> Include the version in the log messages during init, e.g.:
> 
>   virt/tdx: TDX module version: 1.5.24
>   virt/tdx: 1034220 KB allocated for PAMT
>   virt/tdx: module initialized
> 
> ..followed by remaining TDX initialization messages (or errors).
> 
> Print the version early in init_tdx_module(), right after the global
> metadata is read, which makes it available even if there are subsequent
> initialization failures.

One thing to note that if metadata read fails, we will not get there.

The daisy chaining we use for metadata read makes it fragile. Some
metadata fields are version/feature dependant, like you can see in DPAMT
case.

It can be useful to dump version information, even if get_tdx_sys_info()
fails. Version info is likely to be valid on failure.

-- 
  Kiryl Shutsemau / Kirill A. Shutemov

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 2/2] x86/virt/tdx: Print TDX module version during init
  2026-01-08 10:50   ` Kiryl Shutsemau
@ 2026-01-08 18:39     ` Verma, Vishal L
  2026-01-08 20:20       ` Edgecombe, Rick P
  2026-01-08 20:49       ` Dave Hansen
  0 siblings, 2 replies; 21+ messages in thread
From: Verma, Vishal L @ 2026-01-08 18:39 UTC (permalink / raw)
  To: kas
  Cc: Gao, Chao, Edgecombe, Rick P, dave.hansen, Huang, Kai, x86, bp,
	linux-kernel, Williams, Dan J, tglx, kvm, linux-coco, hpa, mingo

On Thu, 2026-01-08 at 10:50 +0000, Kiryl Shutsemau wrote:
> On Wed, Jan 07, 2026 at 05:31:29PM -0700, Vishal Verma wrote:
> > It is useful to print the TDX module version in dmesg logs. This allows
> > for a quick spot check for whether the correct/expected TDX module is
> > being loaded, and also creates a record for any future problems being
> > investigated. This was also requested in [1].
> > 
> > Include the version in the log messages during init, e.g.:
> > 
> >   virt/tdx: TDX module version: 1.5.24
> >   virt/tdx: 1034220 KB allocated for PAMT
> >   virt/tdx: module initialized
> > 
> > ..followed by remaining TDX initialization messages (or errors).
> > 
> > Print the version early in init_tdx_module(), right after the global
> > metadata is read, which makes it available even if there are subsequent
> > initialization failures.
> 
> One thing to note that if metadata read fails, we will not get there.
> 
> The daisy chaining we use for metadata read makes it fragile. Some
> metadata fields are version/feature dependant, like you can see in DPAMT
> case.
> 
> It can be useful to dump version information, even if get_tdx_sys_info()
> fails. Version info is likely to be valid on failure.

Good point, maybe something like this to print it as soon as it is
retrieved?

---3<---

diff --git a/arch/x86/virt/vmx/tdx/tdx.c b/arch/x86/virt/vmx/tdx/tdx.c
index fba00ddc11f1..5ce4ebe99774 100644
--- a/arch/x86/virt/vmx/tdx/tdx.c
+++ b/arch/x86/virt/vmx/tdx/tdx.c
@@ -1084,11 +1084,6 @@ static int init_tdx_module(void)
        if (ret)
                return ret;
 
-       pr_info("Module version: %u.%u.%02u\n",
-               tdx_sysinfo.version.major_version,
-               tdx_sysinfo.version.minor_version,
-               tdx_sysinfo.version.update_version);
-
        /* Check whether the kernel can support this module */
        ret = check_features(&tdx_sysinfo);
        if (ret)
diff --git a/arch/x86/virt/vmx/tdx/tdx_global_metadata.c b/arch/x86/virt/vmx/tdx/tdx_global_metadata.c
index 0454124803f3..4c9917a9c2c3 100644
--- a/arch/x86/virt/vmx/tdx/tdx_global_metadata.c
+++ b/arch/x86/virt/vmx/tdx/tdx_global_metadata.c
@@ -105,6 +105,12 @@ static int get_tdx_sys_info(struct tdx_sys_info *sysinfo)
        int ret = 0;
 
        ret = ret ?: get_tdx_sys_info_version(&sysinfo->version);
+
+       pr_info("Module version: %u.%u.%02u\n",
+               sysinfo->version.major_version,
+               sysinfo->version.minor_version,
+               sysinfo->version.update_version);
+
        ret = ret ?: get_tdx_sys_info_features(&sysinfo->features);
        ret = ret ?: get_tdx_sys_info_tdmr(&sysinfo->tdmr);
        ret = ret ?: get_tdx_sys_info_td_ctrl(&sysinfo->td_ctrl);


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 1/2] x86/virt/tdx: Retrieve TDX module version
  2026-01-08  0:31 ` [PATCH 1/2] x86/virt/tdx: Retrieve TDX module version Vishal Verma
  2026-01-08 10:41   ` Kiryl Shutsemau
@ 2026-01-08 20:18   ` Edgecombe, Rick P
  1 sibling, 0 replies; 21+ messages in thread
From: Edgecombe, Rick P @ 2026-01-08 20:18 UTC (permalink / raw)
  To: kvm, linux-coco, Verma, Vishal L, linux-kernel
  Cc: Gao, Chao, bp, Huang, Kai, kas, dave.hansen, mingo, Williams,
	Dan J, tglx, hpa, x86

On Wed, 2026-01-07 at 17:31 -0700, Vishal Verma wrote:
> From: Chao Gao <chao.gao@intel.com>
> 
> Each TDX module has several bits of metadata about which specific TDX
> module it is. 
> 


> The primary bit of info is the version, which has an x.y.z
> format, where x represents the major version, y the minor version, and z
> the update version.
> 

A bit of a run-on sentence.

>  Knowing the running TDX Module version is valuable
> for bug reporting and debugging. Note that the module does expose other
> pieces of version-related metadata, such as build number and date. Those
> aren't retrieved for now, that can be added if needed in the future.
> 
> Retrieve the TDX Module version using the existing metadata reading
> interface. Later changes will expose this information. The metadata
> reading interfaces have existed for quite some time, so this will work
> with older versions of the TDX module as well - i.e. this isn't a new
> interface.
> 
> As a side note, the global metadata reading code was originally set up
> to be auto-generated from a JSON definition [1]. However, later [2] this
> was found to be unsustainable, and the autogeneration approach was
> dropped in favor of just manually adding fields as needed (e.g. as in
> this patch).
> 
> Signed-off-by: Chao Gao <chao.gao@intel.com>
> Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
> Cc: Rick Edgecombe <rick.p.edgecombe@intel.com>
> Cc: Kai Huang <kai.huang@intel.com>
> Cc: Dave Hansen <dave.hansen@linux.intel.com>
> Cc: Dan Williams <dan.j.williams@intel.com>
> Link: https://lore.kernel.org/kvm/CABgObfYXUxqQV_FoxKjC8U3t5DnyM45nz5DpTxYZv2x_uFK_Kw@mail.gmail.com/ # [1]
> Link: https://lore.kernel.org/all/1e7bcbad-eb26-44b7-97ca-88ab53467212@intel.com/ # [2]
> ---
>  arch/x86/include/asm/tdx_global_metadata.h  |  7 +++++++
>  arch/x86/virt/vmx/tdx/tdx_global_metadata.c | 16 ++++++++++++++++
>  2 files changed, 23 insertions(+)
> 
> diff --git a/arch/x86/include/asm/tdx_global_metadata.h b/arch/x86/include/asm/tdx_global_metadata.h
> index 060a2ad744bff..40689c8dc67eb 100644
> --- a/arch/x86/include/asm/tdx_global_metadata.h
> +++ b/arch/x86/include/asm/tdx_global_metadata.h
> @@ -5,6 +5,12 @@
>  
>  #include <linux/types.h>
>  
> +struct tdx_sys_info_version {
> +	u16 minor_version;
> +	u16 major_version;
> +	u16 update_version;
> +};
> +
>  struct tdx_sys_info_features {
>  	u64 tdx_features0;
>  };
> @@ -35,6 +41,7 @@ struct tdx_sys_info_td_conf {
>  };
>  
>  struct tdx_sys_info {
> +	struct tdx_sys_info_version version;
>  	struct tdx_sys_info_features features;
>  	struct tdx_sys_info_tdmr tdmr;
>  	struct tdx_sys_info_td_ctrl td_ctrl;
> diff --git a/arch/x86/virt/vmx/tdx/tdx_global_metadata.c b/arch/x86/virt/vmx/tdx/tdx_global_metadata.c
> index 13ad2663488b1..0454124803f36 100644
> --- a/arch/x86/virt/vmx/tdx/tdx_global_metadata.c
> +++ b/arch/x86/virt/vmx/tdx/tdx_global_metadata.c
> @@ -7,6 +7,21 @@
>   * Include this file to other C file instead.
>   */
>  
> +static int get_tdx_sys_info_version(struct tdx_sys_info_version *sysinfo_version)
> +{
> +	int ret = 0;
> +	u64 val;
> +
> +	if (!ret && !(ret = read_sys_metadata_field(0x0800000100000003, &val)))
> +		sysinfo_version->minor_version = val;
> +	if (!ret && !(ret = read_sys_metadata_field(0x0800000100000004, &val)))
> +		sysinfo_version->major_version = val;
> +	if (!ret && !(ret = read_sys_metadata_field(0x0800000100000005, &val)))
> +		sysinfo_version->update_version = val;
> +
> +	return ret;
> +}
> +
>  static int get_tdx_sys_info_features(struct tdx_sys_info_features *sysinfo_features)
>  {
>  	int ret = 0;
> @@ -89,6 +104,7 @@ static int get_tdx_sys_info(struct tdx_sys_info *sysinfo)
>  {
>  	int ret = 0;
>  
> +	ret = ret ?: get_tdx_sys_info_version(&sysinfo->version);
>  	ret = ret ?: get_tdx_sys_info_features(&sysinfo->features);
>  	ret = ret ?: get_tdx_sys_info_tdmr(&sysinfo->tdmr);
>  	ret = ret ?: get_tdx_sys_info_td_ctrl(&sysinfo->td_ctrl);
> 

Code looks good to me.

Reviewed-by: Rick Edgecombe <rick.p.edgecombe@intel.com>

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 2/2] x86/virt/tdx: Print TDX module version during init
  2026-01-08 18:39     ` Verma, Vishal L
@ 2026-01-08 20:20       ` Edgecombe, Rick P
  2026-01-08 20:30         ` Verma, Vishal L
  2026-01-08 20:49       ` Dave Hansen
  1 sibling, 1 reply; 21+ messages in thread
From: Edgecombe, Rick P @ 2026-01-08 20:20 UTC (permalink / raw)
  To: Verma, Vishal L, kas
  Cc: Gao, Chao, Huang, Kai, bp, hpa, x86, linux-kernel, Williams,
	Dan J, dave.hansen, kvm, tglx, linux-coco, mingo

On Thu, 2026-01-08 at 18:39 +0000, Verma, Vishal L wrote:
> > It can be useful to dump version information, even if get_tdx_sys_info()
> > fails. Version info is likely to be valid on failure.
> 
> Good point, maybe something like this to print it as soon as it is
> retrieved?
> 
> ---3<---
> 
> diff --git a/arch/x86/virt/vmx/tdx/tdx.c b/arch/x86/virt/vmx/tdx/tdx.c
> index fba00ddc11f1..5ce4ebe99774 100644
> --- a/arch/x86/virt/vmx/tdx/tdx.c
> +++ b/arch/x86/virt/vmx/tdx/tdx.c
> @@ -1084,11 +1084,6 @@ static int init_tdx_module(void)
>         if (ret)
>                 return ret;
>  
> -       pr_info("Module version: %u.%u.%02u\n",
> -               tdx_sysinfo.version.major_version,
> -               tdx_sysinfo.version.minor_version,
> -               tdx_sysinfo.version.update_version);
> -
>         /* Check whether the kernel can support this module */
>         ret = check_features(&tdx_sysinfo);
>         if (ret)
> diff --git a/arch/x86/virt/vmx/tdx/tdx_global_metadata.c
> b/arch/x86/virt/vmx/tdx/tdx_global_metadata.c
> index 0454124803f3..4c9917a9c2c3 100644
> --- a/arch/x86/virt/vmx/tdx/tdx_global_metadata.c
> +++ b/arch/x86/virt/vmx/tdx/tdx_global_metadata.c
> @@ -105,6 +105,12 @@ static int get_tdx_sys_info(struct tdx_sys_info *sysinfo)
>         int ret = 0;
>  
>         ret = ret ?: get_tdx_sys_info_version(&sysinfo->version);
> +
> +       pr_info("Module version: %u.%u.%02u\n",
> +               sysinfo->version.major_version,
> +               sysinfo->version.minor_version,
> +               sysinfo->version.update_version);
> +
>         ret = ret ?: get_tdx_sys_info_features(&sysinfo->features);
>         ret = ret ?: get_tdx_sys_info_tdmr(&sysinfo->tdmr);
>         ret = ret ?: get_tdx_sys_info_td_ctrl(&sysinfo->td_ctrl);

It's awkward because it doesn't check if get_tdx_sys_info_version() fails, even
the though the rest of the code handles this case. I'd just leave it. Let's keep
this as simple as possible, because anything here will be a huge upgrade.

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 2/2] x86/virt/tdx: Print TDX module version during init
  2026-01-08  0:31 ` [PATCH 2/2] x86/virt/tdx: Print TDX module version during init Vishal Verma
  2026-01-08 10:50   ` Kiryl Shutsemau
@ 2026-01-08 20:24   ` Edgecombe, Rick P
  2026-01-08 20:38     ` Verma, Vishal L
  1 sibling, 1 reply; 21+ messages in thread
From: Edgecombe, Rick P @ 2026-01-08 20:24 UTC (permalink / raw)
  To: kvm, linux-coco, Verma, Vishal L, linux-kernel
  Cc: Gao, Chao, bp, Huang, Kai, kas, dave.hansen, mingo, Williams,
	Dan J, tglx, hpa, x86

On Wed, 2026-01-07 at 17:31 -0700, Vishal Verma wrote:
> It is useful to print the TDX module version in dmesg logs. This allows
> for a quick spot check for whether the correct/expected TDX module is
> being loaded, and also creates a record for any future problems being
> investigated.
> 

It is more then a spot check, it's the only way to know which version is loaded.

>  This was also requested in [1].
> 
> Include the version in the log messages during init, e.g.:
> 
>   virt/tdx: TDX module version: 1.5.24
>   virt/tdx: 1034220 KB allocated for PAMT
>   virt/tdx: module initialized
> 
> ..followed by remaining TDX initialization messages (or errors).

The TDX initialization errors would be before "module initialized", right?

> 
> Print the version early in init_tdx_module(), right after the global
> metadata is read, which makes it available even if there are subsequent
> initialization failures.
> 
> Based on a patch by Kai Huang <kai.huang@intel.com> [2]
> 
> Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
> Reviewed-by: Chao Gao <chao.gao@intel.com>
> Cc: Chao Gao <chao.gao@intel.com>
> Cc: Rick Edgecombe <rick.p.edgecombe@intel.com>
> Cc: Kai Huang <kai.huang@intel.com>
> Cc: Dave Hansen <dave.hansen@linux.intel.com>
> Cc: Dan Williams <dan.j.williams@intel.com>
> Link: https://lore.kernel.org/all/CAGtprH8eXwi-TcH2+-Fo5YdbEwGmgLBh9ggcDvd6N=bsKEJ_WQ@mail.gmail.com/ # [1]
> Link: https://lore.kernel.org/all/6b5553756f56a8e3222bfc36d0bdb3e5192137b7.1731318868.git.kai.huang@intel.com # [2]
> ---
>  arch/x86/virt/vmx/tdx/tdx.c | 5 +++++
>  1 file changed, 5 insertions(+)
> 
> diff --git a/arch/x86/virt/vmx/tdx/tdx.c b/arch/x86/virt/vmx/tdx/tdx.c
> index 5ce4ebe99774..fba00ddc11f1 100644
> --- a/arch/x86/virt/vmx/tdx/tdx.c
> +++ b/arch/x86/virt/vmx/tdx/tdx.c
> @@ -1084,6 +1084,11 @@ static int init_tdx_module(void)
>  	if (ret)
>  		return ret;
>  
> +	pr_info("Module version: %u.%u.%02u\n",
> +		tdx_sysinfo.version.major_version,
> +		tdx_sysinfo.version.minor_version,
> +		tdx_sysinfo.version.update_version);
> +
>  	/* Check whether the kernel can support this module */
>  	ret = check_features(&tdx_sysinfo);
>  	if (ret)
> 


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 2/2] x86/virt/tdx: Print TDX module version during init
  2026-01-08 20:20       ` Edgecombe, Rick P
@ 2026-01-08 20:30         ` Verma, Vishal L
  0 siblings, 0 replies; 21+ messages in thread
From: Verma, Vishal L @ 2026-01-08 20:30 UTC (permalink / raw)
  To: kas, Edgecombe, Rick P
  Cc: Gao, Chao, mingo, Huang, Kai, x86, hpa, linux-kernel, Williams,
	Dan J, bp, kvm, tglx, linux-coco, dave.hansen

On Thu, 2026-01-08 at 20:20 +0000, Edgecombe, Rick P wrote:
> On Thu, 2026-01-08 at 18:39 +0000, Verma, Vishal L wrote:
> > > It can be useful to dump version information, even if get_tdx_sys_info()
> > > fails. Version info is likely to be valid on failure.
> > 
> > Good point, maybe something like this to print it as soon as it is
> > retrieved?
> > 
> > ---3<---
> > 
> > diff --git a/arch/x86/virt/vmx/tdx/tdx.c b/arch/x86/virt/vmx/tdx/tdx.c
> > index fba00ddc11f1..5ce4ebe99774 100644
> > --- a/arch/x86/virt/vmx/tdx/tdx.c
> > +++ b/arch/x86/virt/vmx/tdx/tdx.c
> > @@ -1084,11 +1084,6 @@ static int init_tdx_module(void)
> >         if (ret)
> >                 return ret;
> >  
> > -       pr_info("Module version: %u.%u.%02u\n",
> > -               tdx_sysinfo.version.major_version,
> > -               tdx_sysinfo.version.minor_version,
> > -               tdx_sysinfo.version.update_version);
> > -
> >         /* Check whether the kernel can support this module */
> >         ret = check_features(&tdx_sysinfo);
> >         if (ret)
> > diff --git a/arch/x86/virt/vmx/tdx/tdx_global_metadata.c
> > b/arch/x86/virt/vmx/tdx/tdx_global_metadata.c
> > index 0454124803f3..4c9917a9c2c3 100644
> > --- a/arch/x86/virt/vmx/tdx/tdx_global_metadata.c
> > +++ b/arch/x86/virt/vmx/tdx/tdx_global_metadata.c
> > @@ -105,6 +105,12 @@ static int get_tdx_sys_info(struct tdx_sys_info *sysinfo)
> >         int ret = 0;
> >  
> >         ret = ret ?: get_tdx_sys_info_version(&sysinfo->version);
> > +
> > +       pr_info("Module version: %u.%u.%02u\n",
> > +               sysinfo->version.major_version,
> > +               sysinfo->version.minor_version,
> > +               sysinfo->version.update_version);
> > +
> >         ret = ret ?: get_tdx_sys_info_features(&sysinfo->features);
> >         ret = ret ?: get_tdx_sys_info_tdmr(&sysinfo->tdmr);
> >         ret = ret ?: get_tdx_sys_info_td_ctrl(&sysinfo->td_ctrl);
> 
> It's awkward because it doesn't check if get_tdx_sys_info_version() fails, even
> the though the rest of the code handles this case. I'd just leave it. Let's keep
> this as simple as possible, because anything here will be a huge upgrade.


I considered gating it on 'ret', but making it unconditional also
provides us an indirect hint as to which field failed to retrieve.

Do you mean leave it as in stick to printing only after
get_tdx_sys_info()?

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 2/2] x86/virt/tdx: Print TDX module version during init
  2026-01-08 20:24   ` Edgecombe, Rick P
@ 2026-01-08 20:38     ` Verma, Vishal L
  0 siblings, 0 replies; 21+ messages in thread
From: Verma, Vishal L @ 2026-01-08 20:38 UTC (permalink / raw)
  To: kvm, linux-coco, linux-kernel, Edgecombe, Rick P
  Cc: Gao, Chao, x86, Huang, Kai, kas, dave.hansen, mingo, tglx,
	Williams, Dan J, hpa, bp

On Thu, 2026-01-08 at 20:24 +0000, Edgecombe, Rick P wrote:
> On Wed, 2026-01-07 at 17:31 -0700, Vishal Verma wrote:
> > It is useful to print the TDX module version in dmesg logs. This allows
> > for a quick spot check for whether the correct/expected TDX module is
> > being loaded, and also creates a record for any future problems being
> > investigated.
> > 
> 
> It is more then a spot check, it's the only way to know which version is loaded.

I'll update to:

   It is useful to print the TDX module version in dmesg logs. This is
   currently the only way to determine the module version from the host. It
   also creates a record for...

> 
> >  This was also requested in [1].
> > 
> > Include the version in the log messages during init, e.g.:
> > 
> >   virt/tdx: TDX module version: 1.5.24
> >   virt/tdx: 1034220 KB allocated for PAMT
> >   virt/tdx: module initialized
> > 
> > ..followed by remaining TDX initialization messages (or errors).
> 
> The TDX initialization errors would be before "module initialized", right?

Yep, I think this whole line can just be removed to avoid confusion.


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 2/2] x86/virt/tdx: Print TDX module version during init
  2026-01-08 18:39     ` Verma, Vishal L
  2026-01-08 20:20       ` Edgecombe, Rick P
@ 2026-01-08 20:49       ` Dave Hansen
  1 sibling, 0 replies; 21+ messages in thread
From: Dave Hansen @ 2026-01-08 20:49 UTC (permalink / raw)
  To: Verma, Vishal L, kas
  Cc: Gao, Chao, Edgecombe, Rick P, dave.hansen, Huang, Kai, x86, bp,
	linux-kernel, Williams, Dan J, tglx, kvm, linux-coco, hpa, mingo

On 1/8/26 10:39, Verma, Vishal L wrote:
>         ret = ret ?: get_tdx_sys_info_version(&sysinfo->version);
> +
> +       pr_info("Module version: %u.%u.%02u\n",
> +               sysinfo->version.major_version,
> +               sysinfo->version.minor_version,
> +               sysinfo->version.update_version);

This is wonky, but it's also fine.

If we can't even get the module version, we have pretty big problems on
our hands Seeing "Module version: 0.0.00" is a nice indication. It'll
almost certainly be followed by a bunch of other nasty messages, so one
wonky message before them will be a drop in the bucket.

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 1/2] x86/virt/tdx: Retrieve TDX module version
  2025-10-22  7:54     ` Chao Gao
  2025-10-22 10:26       ` Kiryl Shutsemau
@ 2025-11-13  1:24       ` Chao Gao
  1 sibling, 0 replies; 21+ messages in thread
From: Chao Gao @ 2025-11-13  1:24 UTC (permalink / raw)
  To: Dave Hansen
  Cc: linux-coco, linux-kernel, x86, Thomas Gleixner, Ingo Molnar,
	Borislav Petkov, Dave Hansen, H. Peter Anvin, Kirill A. Shutemov,
	Kai Huang, Paolo Bonzini, Dan Williams

On Wed, Oct 22, 2025 at 03:55:01PM +0800, Chao Gao wrote:
>On Wed, Oct 01, 2025 at 08:15:46AM -0700, Dave Hansen wrote:
>>On 9/30/25 19:22, Chao Gao wrote:
>>> +	if (!ret && !(ret = read_sys_metadata_field(0x0800000100000003, &val)))
>>> +		sysinfo_version->minor_version = val;
>>> +	if (!ret && !(ret = read_sys_metadata_field(0x0800000100000004, &val)))
>>> +		sysinfo_version->major_version = val;
>>> +	if (!ret && !(ret = read_sys_metadata_field(0x0800000100000005, &val)))
>>> +		sysinfo_version->update_version = val;
>>
>>Heh, how long does this take in practice to get 6 bytes of data out of
>>the module?
>
>~8us. And the whole metadata reading process (i.e., get_tdx_sys_info()) takes
>~113us.
>
>>When is the point that we move  over to TDH.SYS.RDALL?
>
>TDH.SYS.RDALL takes ~16us.
>
>I'm uncertain whether the saved CPU time of ~100us justifies implementing
>TDH.SYS.RDALL.

I chatted with Dave and Yilun offline. We think that saving 100us for this
one-off operation isn't worth the code churn.

For the record, the idea of moving over to TDH.SYS.RDALL is:

1. Call TDH.SYS.RDALL to dump all metadata into a data structure
2. Add a tdx_get_one() helper to look up the data structure and get the
   metadata for a given field ID
3. Replace read_sys_metadata_field() with tdx_get_one()

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 1/2] x86/virt/tdx: Retrieve TDX module version
  2025-10-01  2:22 ` [PATCH 1/2] x86/virt/tdx: Retrieve TDX module version Chao Gao
  2025-10-01 15:15   ` Dave Hansen
@ 2025-10-24 14:20   ` Vishal Annapurve
  1 sibling, 0 replies; 21+ messages in thread
From: Vishal Annapurve @ 2025-10-24 14:20 UTC (permalink / raw)
  To: Chao Gao
  Cc: linux-coco, linux-kernel, x86, Thomas Gleixner, Ingo Molnar,
	Borislav Petkov, Dave Hansen, H. Peter Anvin, Kirill A. Shutemov,
	Kai Huang, Paolo Bonzini, Dan Williams

On Tue, Sep 30, 2025 at 7:24 PM Chao Gao <chao.gao@intel.com> wrote:
>
> Each TDX module is associated with a version in the x.y.z format, where x
> represents the major version, y the minor version, and z the update
> version. Knowing the running TDX module version is valuable for bug
> reporting and debugging.
>
> Retrieve the TDX module version using the existing metadata reading
> interface, in preparation for exposing it to userspace via sysfs.
>

In addition to exposing the TDX module version via sysfs, it would be
helpful to have the TDX module version captured in dmesg logs/console.

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 1/2] x86/virt/tdx: Retrieve TDX module version
  2025-10-24  9:35           ` Kiryl Shutsemau
@ 2025-10-24 10:04             ` Chao Gao
  0 siblings, 0 replies; 21+ messages in thread
From: Chao Gao @ 2025-10-24 10:04 UTC (permalink / raw)
  To: Kiryl Shutsemau
  Cc: Dave Hansen, linux-coco, linux-kernel, x86, Thomas Gleixner,
	Ingo Molnar, Borislav Petkov, Dave Hansen, H. Peter Anvin,
	Kai Huang, Paolo Bonzini, Dan Williams

>> >Hm. Isn't it buggy?
>> >
>> >Caller expects to see field_id == -1 to exit loop, but you never set it
>> >in case of an error. It will result in endless loop if error happens not on
>> >the first iteration.
>> 
>> The caller checks the return value and bails out if there was an error.
>
>I misread it. Missed the break.
>
>> >
>> >Drop the branch and always return ret.
>> 
>> Setting field_id to -1 on error appears unnecessary since callers must check
>> the return value anyway. And, even if args.r8 were copied to field_id
>> on error, this wouldn't guarantee that field_id would be set to -1, as
>> SEAMCALLs may encounter #GP/#UD exceptions where r8 remains unchanged.
>> 
>> Given this, I prefer to leave field_id as an undefined value on error, and
>> callers should not read/use it when an error occurs.
>
>It is not undefined. TDX module sets R8 to -1 in case of error.

Yes, I saw it. That's TDX module ABI. It doesn't necessarily have to be the
semantics of this kernel API. So, we have two choices:

1. Follow the TDX module, i.e., set field_id to -1 on error. Then we should do:

	if (ret)
		*field_id = -1;
	else
		*field_id = args.r8;

 to cover #GP/#UD cases.

2. Leave field_id undefined on error, as in this patch.

I don't see the value of setting field_id to -1 on error if callers are
expected to check the return value.

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 1/2] x86/virt/tdx: Retrieve TDX module version
  2025-10-24  6:33         ` Chao Gao
@ 2025-10-24  9:35           ` Kiryl Shutsemau
  2025-10-24 10:04             ` Chao Gao
  0 siblings, 1 reply; 21+ messages in thread
From: Kiryl Shutsemau @ 2025-10-24  9:35 UTC (permalink / raw)
  To: Chao Gao
  Cc: Dave Hansen, linux-coco, linux-kernel, x86, Thomas Gleixner,
	Ingo Molnar, Borislav Petkov, Dave Hansen, H. Peter Anvin,
	Kai Huang, Paolo Bonzini, Dan Williams

On Fri, Oct 24, 2025 at 02:33:23PM +0800, Chao Gao wrote:
> >I don't hate it. Seems more scalable than current approach.
> >
> >See some comments below.
> >
> >> diff --git a/arch/x86/virt/vmx/tdx/tdx.c b/arch/x86/virt/vmx/tdx/tdx.c
> >> index 128e6ffba736..fa9bb6d47a87 100644
> >> --- a/arch/x86/virt/vmx/tdx/tdx.c
> >> +++ b/arch/x86/virt/vmx/tdx/tdx.c
> >> @@ -226,22 +226,23 @@ static int build_tdx_memlist(struct list_head *tmb_list)
> >> 	return ret;
> >>  }
> >>  
> >> -static int read_sys_metadata_field(u64 field_id, u64 *data)
> >> +static int read_sys_metadata_field(u64 *field_id, void *ptr)
> >
> >Keeping the same name for completely different functionality?
> 
> how about read_sys_metadata_fields() or read_sys_metadata_all()?

Looks good.

> 
> >
> >>  {
> >> 	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
> >> +	 * TDH.SYS.RDALL -- reads all global metadata fields
> >> +	 *  - RDX (in): the physical address of the buffer to store
> >> +	 *  - R8 (in/out): the initial field ID to read (in) and
> >> +	 *		   the next field ID to read (out).
> >> 	 */
> >> -	args.rdx = field_id;
> >> -	ret = seamcall_prerr_ret(TDH_SYS_RD, &args);
> >> +	args.rdx = __pa(ptr);
> >
> >Maybe take virtual address (unsigned long) of the buffer as an argument
> >to the function. And use virt_to_phys() here.
> >
> >This way there's no need in cast on caller side.
> 
> Sure. Will do.
> 
> >
> >> +	args.r8  = *field_id;
> >> +	ret = seamcall_prerr_ret(TDH_SYS_RDALL, &args);
> >> 	if (ret)
> >> 		return ret;
> >> -
> >> -	*data = args.r8;
> >> +	*field_id = args.r8;
> >>  
> >> 	return 0;
> >
> >Hm. Isn't it buggy?
> >
> >Caller expects to see field_id == -1 to exit loop, but you never set it
> >in case of an error. It will result in endless loop if error happens not on
> >the first iteration.
> 
> The caller checks the return value and bails out if there was an error.

I misread it. Missed the break.

> >
> >Drop the branch and always return ret.
> 
> Setting field_id to -1 on error appears unnecessary since callers must check
> the return value anyway. And, even if args.r8 were copied to field_id
> on error, this wouldn't guarantee that field_id would be set to -1, as
> SEAMCALLs may encounter #GP/#UD exceptions where r8 remains unchanged.
> 
> Given this, I prefer to leave field_id as an undefined value on error, and
> callers should not read/use it when an error occurs.

It is not undefined. TDX module sets R8 to -1 in case of error.

> 
> What do you think?

-- 
  Kiryl Shutsemau / Kirill A. Shutemov

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 1/2] x86/virt/tdx: Retrieve TDX module version
  2025-10-22 10:26       ` Kiryl Shutsemau
@ 2025-10-24  6:33         ` Chao Gao
  2025-10-24  9:35           ` Kiryl Shutsemau
  0 siblings, 1 reply; 21+ messages in thread
From: Chao Gao @ 2025-10-24  6:33 UTC (permalink / raw)
  To: Kiryl Shutsemau
  Cc: Dave Hansen, linux-coco, linux-kernel, x86, Thomas Gleixner,
	Ingo Molnar, Borislav Petkov, Dave Hansen, H. Peter Anvin,
	Kai Huang, Paolo Bonzini, Dan Williams

>I don't hate it. Seems more scalable than current approach.
>
>See some comments below.
>
>> diff --git a/arch/x86/virt/vmx/tdx/tdx.c b/arch/x86/virt/vmx/tdx/tdx.c
>> index 128e6ffba736..fa9bb6d47a87 100644
>> --- a/arch/x86/virt/vmx/tdx/tdx.c
>> +++ b/arch/x86/virt/vmx/tdx/tdx.c
>> @@ -226,22 +226,23 @@ static int build_tdx_memlist(struct list_head *tmb_list)
>> 	return ret;
>>  }
>>  
>> -static int read_sys_metadata_field(u64 field_id, u64 *data)
>> +static int read_sys_metadata_field(u64 *field_id, void *ptr)
>
>Keeping the same name for completely different functionality?

how about read_sys_metadata_fields() or read_sys_metadata_all()?

>
>>  {
>> 	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
>> +	 * TDH.SYS.RDALL -- reads all global metadata fields
>> +	 *  - RDX (in): the physical address of the buffer to store
>> +	 *  - R8 (in/out): the initial field ID to read (in) and
>> +	 *		   the next field ID to read (out).
>> 	 */
>> -	args.rdx = field_id;
>> -	ret = seamcall_prerr_ret(TDH_SYS_RD, &args);
>> +	args.rdx = __pa(ptr);
>
>Maybe take virtual address (unsigned long) of the buffer as an argument
>to the function. And use virt_to_phys() here.
>
>This way there's no need in cast on caller side.

Sure. Will do.

>
>> +	args.r8  = *field_id;
>> +	ret = seamcall_prerr_ret(TDH_SYS_RDALL, &args);
>> 	if (ret)
>> 		return ret;
>> -
>> -	*data = args.r8;
>> +	*field_id = args.r8;
>>  
>> 	return 0;
>
>Hm. Isn't it buggy?
>
>Caller expects to see field_id == -1 to exit loop, but you never set it
>in case of an error. It will result in endless loop if error happens not on
>the first iteration.

The caller checks the return value and bails out if there was an error.

>
>Drop the branch and always return ret.

Setting field_id to -1 on error appears unnecessary since callers must check
the return value anyway. And, even if args.r8 were copied to field_id
on error, this wouldn't guarantee that field_id would be set to -1, as
SEAMCALLs may encounter #GP/#UD exceptions where r8 remains unchanged.

Given this, I prefer to leave field_id as an undefined value on error, and
callers should not read/use it when an error occurs.

What do you think?

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 1/2] x86/virt/tdx: Retrieve TDX module version
  2025-10-22  7:54     ` Chao Gao
@ 2025-10-22 10:26       ` Kiryl Shutsemau
  2025-10-24  6:33         ` Chao Gao
  2025-11-13  1:24       ` Chao Gao
  1 sibling, 1 reply; 21+ messages in thread
From: Kiryl Shutsemau @ 2025-10-22 10:26 UTC (permalink / raw)
  To: Chao Gao
  Cc: Dave Hansen, linux-coco, linux-kernel, x86, Thomas Gleixner,
	Ingo Molnar, Borislav Petkov, Dave Hansen, H. Peter Anvin,
	Kai Huang, Paolo Bonzini, Dan Williams

On Wed, Oct 22, 2025 at 03:54:51PM +0800, Chao Gao wrote:
> On Wed, Oct 01, 2025 at 08:15:46AM -0700, Dave Hansen wrote:
> >On 9/30/25 19:22, Chao Gao wrote:
> >> +	if (!ret && !(ret = read_sys_metadata_field(0x0800000100000003, &val)))
> >> +		sysinfo_version->minor_version = val;
> >> +	if (!ret && !(ret = read_sys_metadata_field(0x0800000100000004, &val)))
> >> +		sysinfo_version->major_version = val;
> >> +	if (!ret && !(ret = read_sys_metadata_field(0x0800000100000005, &val)))
> >> +		sysinfo_version->update_version = val;
> >
> >Heh, how long does this take in practice to get 6 bytes of data out of
> >the module?
> 
> ~8us. And the whole metadata reading process (i.e., get_tdx_sys_info()) takes
> ~113us.
> 
> >When is the point that we move  over to TDH.SYS.RDALL?
> 
> TDH.SYS.RDALL takes ~16us.
> 
> I'm uncertain whether the saved CPU time of ~100us justifies implementing
> TDH.SYS.RDALL.
> 
> TDH.SYS.RDALL returns all metadata as a list of arrays, requiring the kernel to
> parse this structure and iterate through all fields.
> 
> One advantage of TDH.SYS.RDALL is that it eliminates the need to check field
> existence before reading, since it simply dumps all available fields rather
> than targeting specific ones. For example, TDH.SYS.RDALL removes the need for
> the tdx_supports_ABC() check:
> 
> 	in the DPAMT series:
> 
> 	+	if (!ret && tdx_supports_dynamic_pamt(&tdx_sysinfo) &&
> 	+	    !(ret = read_sys_metadata_field(0x9100000100000013, &val)))
> 	+		sysinfo_tdmr->pamt_page_bitmap_entry_bits = val;
> 
> 	in the TDX Module update series:
> 
> 	+	if (tdx_supports_runtime_update(&tdx_sysinfo) &&
> 	+	    !(ret = read_sys_metadata_field(0x8900000100000000, &val)))
> 	+		sysinfo_handoff->module_hv = val;
> 
> While iterating through the array list adds some complexity, this is a one-time
> cost. Once the loop structure is in place, adding new fields only requires
> inserting a "switch-case" clause within the loop.
> 
> Please see the draft code below. If TDH.SYS.RDALL is the right direction, I can
> refine the code and submit a formal patch series.

I don't hate it. Seems more scalable than current approach.

See some comments below.

> diff --git a/arch/x86/virt/vmx/tdx/tdx.c b/arch/x86/virt/vmx/tdx/tdx.c
> index 128e6ffba736..fa9bb6d47a87 100644
> --- a/arch/x86/virt/vmx/tdx/tdx.c
> +++ b/arch/x86/virt/vmx/tdx/tdx.c
> @@ -226,22 +226,23 @@ static int build_tdx_memlist(struct list_head *tmb_list)
> 	return ret;
>  }
>  
> -static int read_sys_metadata_field(u64 field_id, u64 *data)
> +static int read_sys_metadata_field(u64 *field_id, void *ptr)

Keeping the same name for completely different functionality?

>  {
> 	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
> +	 * TDH.SYS.RDALL -- reads all global metadata fields
> +	 *  - RDX (in): the physical address of the buffer to store
> +	 *  - R8 (in/out): the initial field ID to read (in) and
> +	 *		   the next field ID to read (out).
> 	 */
> -	args.rdx = field_id;
> -	ret = seamcall_prerr_ret(TDH_SYS_RD, &args);
> +	args.rdx = __pa(ptr);

Maybe take virtual address (unsigned long) of the buffer as an argument
to the function. And use virt_to_phys() here.

This way there's no need in cast on caller side.

> +	args.r8  = *field_id;
> +	ret = seamcall_prerr_ret(TDH_SYS_RDALL, &args);
> 	if (ret)
> 		return ret;
> -
> -	*data = args.r8;
> +	*field_id = args.r8;
>  
> 	return 0;

Hm. Isn't it buggy?

Caller expects to see field_id == -1 to exit loop, but you never set it
in case of an error. It will result in endless loop if error happens not on
the first iteration.

Drop the branch and always return ret.

>  }
> diff --git a/arch/x86/virt/vmx/tdx/tdx.h b/arch/x86/virt/vmx/tdx/tdx.h
> index 1965adb63f1f..44d92047073e 100644
> --- a/arch/x86/virt/vmx/tdx/tdx.h
> +++ b/arch/x86/virt/vmx/tdx/tdx.h
> @@ -42,6 +42,7 @@
>  #define TDH_SYS_RD			34
>  #define TDH_SYS_LP_INIT			35
>  #define TDH_SYS_TDMR_INIT		36
> +#define TDH_SYS_RDALL			37
>  #define TDH_MEM_TRACK			38
>  #define TDH_PHYMEM_CACHE_WB		40
>  #define TDH_PHYMEM_PAGE_WBINVD		41
> diff --git a/arch/x86/virt/vmx/tdx/tdx_global_metadata.c b/arch/x86/virt/vmx/tdx/tdx_global_metadata.c
> index 3fdd5cbc21d8..f4b16367ef2f 100644
> --- a/arch/x86/virt/vmx/tdx/tdx_global_metadata.c
> +++ b/arch/x86/virt/vmx/tdx/tdx_global_metadata.c
> @@ -7,121 +7,177 @@
>   * Include this file to other C file instead.
>   */
>  
> -static int get_tdx_sys_info_version(struct tdx_sys_info_version *sysinfo_version)
> +struct md_field_id
>  {
> -	int ret = 0;
> -	u64 val;
> -
> -	if (!ret && !(ret = read_sys_metadata_field(0x0800000100000003, &val)))
> -		sysinfo_version->minor_version = val;
> -	if (!ret && !(ret = read_sys_metadata_field(0x0800000100000004, &val)))
> -		sysinfo_version->major_version = val;
> -	if (!ret && !(ret = read_sys_metadata_field(0x0800000100000005, &val)))
> -		sysinfo_version->update_version = val;
> -
> -	return ret;
> -}
> -
> -static int get_tdx_sys_info_features(struct tdx_sys_info_features *sysinfo_features)
> -{
> -	int ret = 0;
> -	u64 val;
> -
> -	if (!ret && !(ret = read_sys_metadata_field(0x0A00000300000008, &val)))
> -		sysinfo_features->tdx_features0 = val;
> -
> -	return ret;
> -}
> -
> -static int get_tdx_sys_info_tdmr(struct tdx_sys_info_tdmr *sysinfo_tdmr)
> +	union {
> +		struct {
> +			u32 field_code;				// Bits 31:0
> +			u32 element_size_code		: 2;	// Bits 33:32
> +			u32 last_element_in_field	: 4;	// Bits 37:34
> +			u32 last_field_in_sequence	: 9;	// Bits 46:38
> +			u32 reserved_1			: 3;	// Bits 49:47
> +			u32 inc_size			: 1;	// Bit 50
> +			u32 write_mask_valid		: 1;	// Bit 51
> +			u32 context_code		: 3;	// Bits 54:52
> +			u32 reserved_2			: 1;	// Bit 55
> +			u32 class_code			: 6;	// Bits 61:56
> +			u32 reserved_3			: 1;	// Bit 62
> +			u32 non_arch			: 1;	// Bit 63
> +		};
> +		u64 raw;
> +	};
> +};
> +struct md_list_header
>  {
> -	int ret = 0;
> -	u64 val;
> -
> -	if (!ret && !(ret = read_sys_metadata_field(0x9100000100000008, &val)))
> -		sysinfo_tdmr->max_tdmrs = val;
> -	if (!ret && !(ret = read_sys_metadata_field(0x9100000100000009, &val)))
> -		sysinfo_tdmr->max_reserved_per_tdmr = val;
> -	if (!ret && !(ret = read_sys_metadata_field(0x9100000100000010, &val)))
> -		sysinfo_tdmr->pamt_4k_entry_size = val;
> -	if (!ret && !(ret = read_sys_metadata_field(0x9100000100000011, &val)))
> -		sysinfo_tdmr->pamt_2m_entry_size = val;
> -	if (!ret && !(ret = read_sys_metadata_field(0x9100000100000012, &val)))
> -		sysinfo_tdmr->pamt_1g_entry_size = val;
> -
> -	return ret;
> -}
> +	u16 list_buff_size;
> +	u16 num_sequences;
> +	u32 reserved;
> +};
>  
> -static int get_tdx_sys_info_td_ctrl(struct tdx_sys_info_td_ctrl *sysinfo_td_ctrl)
> +struct md_sequence
>  {
> -	int ret = 0;
> -	u64 val;
> +	struct md_field_id sequence_header;
> +	u64 element[0];
> +};
> +
> +#define TDX_MD_ID_MINOR_VERSION			0x0800000100000003
> +#define TDX_MD_ID_MAJOR_VERSION			0x0800000100000004
> +#define TDX_MD_ID_UPDATE_VERSION		0x0800000100000005
> +#define TDX_MD_ID_MODULE_HV			0x8900000100000000
> +#define TDX_MD_ID_TDX_FEATURES0			0x0A00000300000008
> +#define TDX_MD_ID_MAX_TDMRS			0x9100000100000008
> +#define TDX_MD_ID_MAX_RESERVED_PER_TDMR		0x9100000100000009
> +#define TDX_MD_ID_PAMT_4K_ENTRY_SIZE		0x9100000100000010
> +#define TDX_MD_ID_PAMT_2M_ENTRY_SIZE		0x9100000100000011
> +#define TDX_MD_ID_PAMT_1G_ENTRY_SIZE		0x9100000100000012
> +#define TDX_MD_ID_TDR_BASE_SIZE			0x9800000100000000
> +#define TDX_MD_ID_TDCS_BASE_SIZE		0x9800000100000100
> +#define TDX_MD_ID_TDVPS_BASE_SIZE		0x9800000100000200
> +#define TDX_MD_ID_ATTRIBUTES_FIXED0		0x1900000300000000
> +#define TDX_MD_ID_ATTRIBUTES_FIXED1		0x1900000300000001
> +#define TDX_MD_ID_XFAM_FIXED0			0x1900000300000002
> +#define TDX_MD_ID_XFAM_FIXED1			0x1900000300000003
> +#define TDX_MD_ID_NUM_CPUID_CONFIG		0x9900000100000004
> +#define TDX_MD_ID_MAX_VCPUS_PER_TD		0x9900000100000008
> +#define TDX_MD_ID_CPUID_CONFIG_LEAVES		0x9900000300000400
> +#define TDX_MD_ID_CPUID_CONFIG_VALUES		0x9900000300000500
>  
> -	if (!ret && !(ret = read_sys_metadata_field(0x9800000100000000, &val)))
> -		sysinfo_td_ctrl->tdr_base_size = val;
> -	if (!ret && !(ret = read_sys_metadata_field(0x9800000100000100, &val)))
> -		sysinfo_td_ctrl->tdcs_base_size = val;
> -	if (!ret && !(ret = read_sys_metadata_field(0x9800000100000200, &val)))
> -		sysinfo_td_ctrl->tdvps_base_size = val;
> -
> -	return ret;
> -}
> +/*
> + * Extract CLASS_CODE (bits 61:56), CONTEXT_CODE(bits 54:52),
> + * FIELD_CODE(bits 23:0) from metadata IDs. Other bits in metadata IDs
> + * cannot be used for comparison.
> + */
> +#define TDX_MD_ID_MASK				0x3f70000000ffffff
>  
> -static int get_tdx_sys_info_td_conf(struct tdx_sys_info_td_conf *sysinfo_td_conf)
> +static void parse_md_sequence(struct md_sequence *sequence, struct tdx_sys_info *sysinfo)
>  {
> -	int ret = 0;
> -	u64 val;
> +	u32 num_elements = (sequence->sequence_header.last_element_in_field + 1) *
> +			   (sequence->sequence_header.last_field_in_sequence + 1);
> +	u64 base_id = sequence->sequence_header.raw & TDX_MD_ID_MASK;
> +	u64 field_id;
> +	u64 *data;
> 	int i, j;
>  
> -	if (!ret && !(ret = read_sys_metadata_field(0x1900000300000000, &val)))
> -		sysinfo_td_conf->attributes_fixed0 = val;
> -	if (!ret && !(ret = read_sys_metadata_field(0x1900000300000001, &val)))
> -		sysinfo_td_conf->attributes_fixed1 = val;
> -	if (!ret && !(ret = read_sys_metadata_field(0x1900000300000002, &val)))
> -		sysinfo_td_conf->xfam_fixed0 = val;
> -	if (!ret && !(ret = read_sys_metadata_field(0x1900000300000003, &val)))
> -		sysinfo_td_conf->xfam_fixed1 = val;
> -	if (!ret && !(ret = read_sys_metadata_field(0x9900000100000004, &val)))
> -		sysinfo_td_conf->num_cpuid_config = val;
> -	if (!ret && !(ret = read_sys_metadata_field(0x9900000100000008, &val)))
> -		sysinfo_td_conf->max_vcpus_per_td = val;
> -	if (sysinfo_td_conf->num_cpuid_config > ARRAY_SIZE(sysinfo_td_conf->cpuid_config_leaves))
> -		return -EINVAL;
> -	for (i = 0; i < sysinfo_td_conf->num_cpuid_config; i++)
> -		if (!ret && !(ret = read_sys_metadata_field(0x9900000300000400 + i, &val)))
> -			sysinfo_td_conf->cpuid_config_leaves[i] = val;
> -	if (sysinfo_td_conf->num_cpuid_config > ARRAY_SIZE(sysinfo_td_conf->cpuid_config_values))
> -		return -EINVAL;
> -	for (i = 0; i < sysinfo_td_conf->num_cpuid_config; i++)
> -		for (j = 0; j < 2; j++)
> -			if (!ret && !(ret = read_sys_metadata_field(0x9900000300000500 + i * 2 + j, &val)))
> -				sysinfo_td_conf->cpuid_config_values[i][j] = val;
> -
> -	return ret;
> +	pr_info("header 0x%016llx id 0x%016llx elements_in_field %d field %d\n", sequence->sequence_header.raw, base_id,
> +		sequence->sequence_header.last_element_in_field + 1,
> +		sequence->sequence_header.last_field_in_sequence + 1);
> +
> +	/* Iterate over all elements in the sequence */
> +	for (i = 0; i < num_elements; i++) {
> +		field_id = base_id + i;
> +		data = sequence->element + i;
> +
> +		switch (field_id) {
> +		#define READ_TDX_MD(name, field)			\
> +			case (TDX_MD_ID_##name & TDX_MD_ID_MASK):	\
> +				field = *data;				\
> +				break;
> +
> +		READ_TDX_MD(MINOR_VERSION, sysinfo->version.minor_version);
> +		READ_TDX_MD(MAJOR_VERSION, sysinfo->version.major_version);
> +		READ_TDX_MD(UPDATE_VERSION, sysinfo->version.update_version);
> +
> +		READ_TDX_MD(MODULE_HV, sysinfo->handoff.module_hv);
> +
> +		READ_TDX_MD(TDX_FEATURES0, sysinfo->features.tdx_features0);
> +
> +		READ_TDX_MD(MAX_TDMRS, sysinfo->tdmr.max_tdmrs);
> +		READ_TDX_MD(MAX_RESERVED_PER_TDMR, sysinfo->tdmr.max_reserved_per_tdmr);
> +		READ_TDX_MD(PAMT_4K_ENTRY_SIZE, sysinfo->tdmr.pamt_4k_entry_size);
> +		READ_TDX_MD(PAMT_2M_ENTRY_SIZE, sysinfo->tdmr.pamt_2m_entry_size);
> +		READ_TDX_MD(PAMT_1G_ENTRY_SIZE, sysinfo->tdmr.pamt_1g_entry_size);
> +
> +		READ_TDX_MD(TDR_BASE_SIZE, sysinfo->td_ctrl.tdr_base_size);
> +		READ_TDX_MD(TDCS_BASE_SIZE, sysinfo->td_ctrl.tdcs_base_size);
> +		READ_TDX_MD(TDVPS_BASE_SIZE, sysinfo->td_ctrl.tdvps_base_size);
> +
> +		READ_TDX_MD(ATTRIBUTES_FIXED0, sysinfo->td_conf.attributes_fixed0);
> +		READ_TDX_MD(ATTRIBUTES_FIXED1, sysinfo->td_conf.attributes_fixed1);
> +		READ_TDX_MD(XFAM_FIXED0, sysinfo->td_conf.xfam_fixed0);
> +		READ_TDX_MD(XFAM_FIXED1, sysinfo->td_conf.xfam_fixed1);
> +		READ_TDX_MD(NUM_CPUID_CONFIG, sysinfo->td_conf.num_cpuid_config);
> +		READ_TDX_MD(MAX_VCPUS_PER_TD, sysinfo->td_conf.max_vcpus_per_td);
> +		#undef READ_TDX_MD
> +
> +		case TDX_MD_ID_CPUID_CONFIG_LEAVES & TDX_MD_ID_MASK:
> +			for (j = 0; j < sysinfo->td_conf.num_cpuid_config; j++)
> +				sysinfo->td_conf.cpuid_config_leaves[j] = data[j];
> +			/* return as all elements in this sequence are handled */
> +			return;
> +		case TDX_MD_ID_CPUID_CONFIG_VALUES & TDX_MD_ID_MASK:
> +			for (j = 0; j < sysinfo->td_conf.num_cpuid_config; j++) {
> +				sysinfo->td_conf.cpuid_config_values[j][0] = data[2*j];
> +				sysinfo->td_conf.cpuid_config_values[j][1] = data[2*j+1];
> +			}
> +			/* return as all elements in this sequence are handled */
> +			return;
> +		default:
> +			break;
> +		}
> +	}
>  }
>  
> -static int get_tdx_sys_info_handoff(struct tdx_sys_info_handoff *sysinfo_handoff)
> +static void parse_md_list(struct md_list_header *list_header, struct tdx_sys_info *sysinfo)
>  {
> -	int ret = 0;
> -	u64 val;
> -
> -	if (tdx_supports_runtime_update(&tdx_sysinfo) &&
> -	    !(ret = read_sys_metadata_field(0x8900000100000000, &val)))
> -		sysinfo_handoff->module_hv = val;
> -
> -	return ret;
> +	struct md_sequence *sequence;
> +	u32 num_elements;
> +	int i = 0;
> +
> +	pr_info("header: buff_size %u, num_sequences %u\n",
> +		list_header->list_buff_size,
> +		list_header->num_sequences);
> +
> +	sequence = (struct md_sequence *)(list_header + 1);
> +
> +	while (i < list_header->num_sequences) {
> +		num_elements = (sequence->sequence_header.last_element_in_field + 1) *
> +			       (sequence->sequence_header.last_field_in_sequence + 1);
> +		parse_md_sequence(sequence, sysinfo);
> +		sequence = (struct md_sequence *)(&sequence->element[num_elements]);
> +		i++;
> +	}
>  }
>  
>  static int get_tdx_sys_info(struct tdx_sys_info *sysinfo)
>  {
> +	unsigned long buffer;
> +	u64 field_id = -1;
> 	int ret = 0;
>  
> -	ret = ret ?: get_tdx_sys_info_version(&sysinfo->version);
> -	ret = ret ?: get_tdx_sys_info_features(&sysinfo->features);
> -	ret = ret ?: get_tdx_sys_info_tdmr(&sysinfo->tdmr);
> -	ret = ret ?: get_tdx_sys_info_td_ctrl(&sysinfo->td_ctrl);
> -	ret = ret ?: get_tdx_sys_info_td_conf(&sysinfo->td_conf);
> -	ret = ret ?: get_tdx_sys_info_handoff(&sysinfo->handoff);
> +	buffer = __get_free_page(GFP_KERNEL);
> +	if (!buffer)
> +		return -ENOMEM;
> +
> +	do {
> +		ret = read_sys_metadata_field(&field_id, (void *)buffer);
> +		if (ret)
> +			break;
> +		parse_md_list((void *)buffer, sysinfo);
> +	} while (field_id != -1);
> +
> +	free_page(buffer);
> +	if (ret)
> +		pr_info("TDX sysinfo version read all failed: %d\n", ret);
>  
> 	return ret;
>  }
> 

-- 
  Kiryl Shutsemau / Kirill A. Shutemov

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 1/2] x86/virt/tdx: Retrieve TDX module version
  2025-10-01 15:15   ` Dave Hansen
@ 2025-10-22  7:54     ` Chao Gao
  2025-10-22 10:26       ` Kiryl Shutsemau
  2025-11-13  1:24       ` Chao Gao
  0 siblings, 2 replies; 21+ messages in thread
From: Chao Gao @ 2025-10-22  7:54 UTC (permalink / raw)
  To: Dave Hansen
  Cc: linux-coco, linux-kernel, x86, Thomas Gleixner, Ingo Molnar,
	Borislav Petkov, Dave Hansen, H. Peter Anvin, Kirill A. Shutemov,
	Kai Huang, Paolo Bonzini, Dan Williams

On Wed, Oct 01, 2025 at 08:15:46AM -0700, Dave Hansen wrote:
>On 9/30/25 19:22, Chao Gao wrote:
>> +	if (!ret && !(ret = read_sys_metadata_field(0x0800000100000003, &val)))
>> +		sysinfo_version->minor_version = val;
>> +	if (!ret && !(ret = read_sys_metadata_field(0x0800000100000004, &val)))
>> +		sysinfo_version->major_version = val;
>> +	if (!ret && !(ret = read_sys_metadata_field(0x0800000100000005, &val)))
>> +		sysinfo_version->update_version = val;
>
>Heh, how long does this take in practice to get 6 bytes of data out of
>the module?

~8us. And the whole metadata reading process (i.e., get_tdx_sys_info()) takes
~113us.

>When is the point that we move  over to TDH.SYS.RDALL?

TDH.SYS.RDALL takes ~16us.

I'm uncertain whether the saved CPU time of ~100us justifies implementing
TDH.SYS.RDALL.

TDH.SYS.RDALL returns all metadata as a list of arrays, requiring the kernel to
parse this structure and iterate through all fields.

One advantage of TDH.SYS.RDALL is that it eliminates the need to check field
existence before reading, since it simply dumps all available fields rather
than targeting specific ones. For example, TDH.SYS.RDALL removes the need for
the tdx_supports_ABC() check:

	in the DPAMT series:

	+	if (!ret && tdx_supports_dynamic_pamt(&tdx_sysinfo) &&
	+	    !(ret = read_sys_metadata_field(0x9100000100000013, &val)))
	+		sysinfo_tdmr->pamt_page_bitmap_entry_bits = val;

	in the TDX Module update series:

	+	if (tdx_supports_runtime_update(&tdx_sysinfo) &&
	+	    !(ret = read_sys_metadata_field(0x8900000100000000, &val)))
	+		sysinfo_handoff->module_hv = val;

While iterating through the array list adds some complexity, this is a one-time
cost. Once the loop structure is in place, adding new fields only requires
inserting a "switch-case" clause within the loop.

Please see the draft code below. If TDH.SYS.RDALL is the right direction, I can
refine the code and submit a formal patch series.

diff --git a/arch/x86/virt/vmx/tdx/tdx.c b/arch/x86/virt/vmx/tdx/tdx.c
index 128e6ffba736..fa9bb6d47a87 100644
--- a/arch/x86/virt/vmx/tdx/tdx.c
+++ b/arch/x86/virt/vmx/tdx/tdx.c
@@ -226,22 +226,23 @@ static int build_tdx_memlist(struct list_head *tmb_list)
	return ret;
 }
 
-static int read_sys_metadata_field(u64 field_id, u64 *data)
+static int read_sys_metadata_field(u64 *field_id, void *ptr)
 {
	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
+	 * TDH.SYS.RDALL -- reads all global metadata fields
+	 *  - RDX (in): the physical address of the buffer to store
+	 *  - R8 (in/out): the initial field ID to read (in) and
+	 *		   the next field ID to read (out).
	 */
-	args.rdx = field_id;
-	ret = seamcall_prerr_ret(TDH_SYS_RD, &args);
+	args.rdx = __pa(ptr);
+	args.r8  = *field_id;
+	ret = seamcall_prerr_ret(TDH_SYS_RDALL, &args);
	if (ret)
		return ret;
-
-	*data = args.r8;
+	*field_id = args.r8;
 
	return 0;
 }
diff --git a/arch/x86/virt/vmx/tdx/tdx.h b/arch/x86/virt/vmx/tdx/tdx.h
index 1965adb63f1f..44d92047073e 100644
--- a/arch/x86/virt/vmx/tdx/tdx.h
+++ b/arch/x86/virt/vmx/tdx/tdx.h
@@ -42,6 +42,7 @@
 #define TDH_SYS_RD			34
 #define TDH_SYS_LP_INIT			35
 #define TDH_SYS_TDMR_INIT		36
+#define TDH_SYS_RDALL			37
 #define TDH_MEM_TRACK			38
 #define TDH_PHYMEM_CACHE_WB		40
 #define TDH_PHYMEM_PAGE_WBINVD		41
diff --git a/arch/x86/virt/vmx/tdx/tdx_global_metadata.c b/arch/x86/virt/vmx/tdx/tdx_global_metadata.c
index 3fdd5cbc21d8..f4b16367ef2f 100644
--- a/arch/x86/virt/vmx/tdx/tdx_global_metadata.c
+++ b/arch/x86/virt/vmx/tdx/tdx_global_metadata.c
@@ -7,121 +7,177 @@
  * Include this file to other C file instead.
  */
 
-static int get_tdx_sys_info_version(struct tdx_sys_info_version *sysinfo_version)
+struct md_field_id
 {
-	int ret = 0;
-	u64 val;
-
-	if (!ret && !(ret = read_sys_metadata_field(0x0800000100000003, &val)))
-		sysinfo_version->minor_version = val;
-	if (!ret && !(ret = read_sys_metadata_field(0x0800000100000004, &val)))
-		sysinfo_version->major_version = val;
-	if (!ret && !(ret = read_sys_metadata_field(0x0800000100000005, &val)))
-		sysinfo_version->update_version = val;
-
-	return ret;
-}
-
-static int get_tdx_sys_info_features(struct tdx_sys_info_features *sysinfo_features)
-{
-	int ret = 0;
-	u64 val;
-
-	if (!ret && !(ret = read_sys_metadata_field(0x0A00000300000008, &val)))
-		sysinfo_features->tdx_features0 = val;
-
-	return ret;
-}
-
-static int get_tdx_sys_info_tdmr(struct tdx_sys_info_tdmr *sysinfo_tdmr)
+	union {
+		struct {
+			u32 field_code;				// Bits 31:0
+			u32 element_size_code		: 2;	// Bits 33:32
+			u32 last_element_in_field	: 4;	// Bits 37:34
+			u32 last_field_in_sequence	: 9;	// Bits 46:38
+			u32 reserved_1			: 3;	// Bits 49:47
+			u32 inc_size			: 1;	// Bit 50
+			u32 write_mask_valid		: 1;	// Bit 51
+			u32 context_code		: 3;	// Bits 54:52
+			u32 reserved_2			: 1;	// Bit 55
+			u32 class_code			: 6;	// Bits 61:56
+			u32 reserved_3			: 1;	// Bit 62
+			u32 non_arch			: 1;	// Bit 63
+		};
+		u64 raw;
+	};
+};
+struct md_list_header
 {
-	int ret = 0;
-	u64 val;
-
-	if (!ret && !(ret = read_sys_metadata_field(0x9100000100000008, &val)))
-		sysinfo_tdmr->max_tdmrs = val;
-	if (!ret && !(ret = read_sys_metadata_field(0x9100000100000009, &val)))
-		sysinfo_tdmr->max_reserved_per_tdmr = val;
-	if (!ret && !(ret = read_sys_metadata_field(0x9100000100000010, &val)))
-		sysinfo_tdmr->pamt_4k_entry_size = val;
-	if (!ret && !(ret = read_sys_metadata_field(0x9100000100000011, &val)))
-		sysinfo_tdmr->pamt_2m_entry_size = val;
-	if (!ret && !(ret = read_sys_metadata_field(0x9100000100000012, &val)))
-		sysinfo_tdmr->pamt_1g_entry_size = val;
-
-	return ret;
-}
+	u16 list_buff_size;
+	u16 num_sequences;
+	u32 reserved;
+};
 
-static int get_tdx_sys_info_td_ctrl(struct tdx_sys_info_td_ctrl *sysinfo_td_ctrl)
+struct md_sequence
 {
-	int ret = 0;
-	u64 val;
+	struct md_field_id sequence_header;
+	u64 element[0];
+};
+
+#define TDX_MD_ID_MINOR_VERSION			0x0800000100000003
+#define TDX_MD_ID_MAJOR_VERSION			0x0800000100000004
+#define TDX_MD_ID_UPDATE_VERSION		0x0800000100000005
+#define TDX_MD_ID_MODULE_HV			0x8900000100000000
+#define TDX_MD_ID_TDX_FEATURES0			0x0A00000300000008
+#define TDX_MD_ID_MAX_TDMRS			0x9100000100000008
+#define TDX_MD_ID_MAX_RESERVED_PER_TDMR		0x9100000100000009
+#define TDX_MD_ID_PAMT_4K_ENTRY_SIZE		0x9100000100000010
+#define TDX_MD_ID_PAMT_2M_ENTRY_SIZE		0x9100000100000011
+#define TDX_MD_ID_PAMT_1G_ENTRY_SIZE		0x9100000100000012
+#define TDX_MD_ID_TDR_BASE_SIZE			0x9800000100000000
+#define TDX_MD_ID_TDCS_BASE_SIZE		0x9800000100000100
+#define TDX_MD_ID_TDVPS_BASE_SIZE		0x9800000100000200
+#define TDX_MD_ID_ATTRIBUTES_FIXED0		0x1900000300000000
+#define TDX_MD_ID_ATTRIBUTES_FIXED1		0x1900000300000001
+#define TDX_MD_ID_XFAM_FIXED0			0x1900000300000002
+#define TDX_MD_ID_XFAM_FIXED1			0x1900000300000003
+#define TDX_MD_ID_NUM_CPUID_CONFIG		0x9900000100000004
+#define TDX_MD_ID_MAX_VCPUS_PER_TD		0x9900000100000008
+#define TDX_MD_ID_CPUID_CONFIG_LEAVES		0x9900000300000400
+#define TDX_MD_ID_CPUID_CONFIG_VALUES		0x9900000300000500
 
-	if (!ret && !(ret = read_sys_metadata_field(0x9800000100000000, &val)))
-		sysinfo_td_ctrl->tdr_base_size = val;
-	if (!ret && !(ret = read_sys_metadata_field(0x9800000100000100, &val)))
-		sysinfo_td_ctrl->tdcs_base_size = val;
-	if (!ret && !(ret = read_sys_metadata_field(0x9800000100000200, &val)))
-		sysinfo_td_ctrl->tdvps_base_size = val;
-
-	return ret;
-}
+/*
+ * Extract CLASS_CODE (bits 61:56), CONTEXT_CODE(bits 54:52),
+ * FIELD_CODE(bits 23:0) from metadata IDs. Other bits in metadata IDs
+ * cannot be used for comparison.
+ */
+#define TDX_MD_ID_MASK				0x3f70000000ffffff
 
-static int get_tdx_sys_info_td_conf(struct tdx_sys_info_td_conf *sysinfo_td_conf)
+static void parse_md_sequence(struct md_sequence *sequence, struct tdx_sys_info *sysinfo)
 {
-	int ret = 0;
-	u64 val;
+	u32 num_elements = (sequence->sequence_header.last_element_in_field + 1) *
+			   (sequence->sequence_header.last_field_in_sequence + 1);
+	u64 base_id = sequence->sequence_header.raw & TDX_MD_ID_MASK;
+	u64 field_id;
+	u64 *data;
	int i, j;
 
-	if (!ret && !(ret = read_sys_metadata_field(0x1900000300000000, &val)))
-		sysinfo_td_conf->attributes_fixed0 = val;
-	if (!ret && !(ret = read_sys_metadata_field(0x1900000300000001, &val)))
-		sysinfo_td_conf->attributes_fixed1 = val;
-	if (!ret && !(ret = read_sys_metadata_field(0x1900000300000002, &val)))
-		sysinfo_td_conf->xfam_fixed0 = val;
-	if (!ret && !(ret = read_sys_metadata_field(0x1900000300000003, &val)))
-		sysinfo_td_conf->xfam_fixed1 = val;
-	if (!ret && !(ret = read_sys_metadata_field(0x9900000100000004, &val)))
-		sysinfo_td_conf->num_cpuid_config = val;
-	if (!ret && !(ret = read_sys_metadata_field(0x9900000100000008, &val)))
-		sysinfo_td_conf->max_vcpus_per_td = val;
-	if (sysinfo_td_conf->num_cpuid_config > ARRAY_SIZE(sysinfo_td_conf->cpuid_config_leaves))
-		return -EINVAL;
-	for (i = 0; i < sysinfo_td_conf->num_cpuid_config; i++)
-		if (!ret && !(ret = read_sys_metadata_field(0x9900000300000400 + i, &val)))
-			sysinfo_td_conf->cpuid_config_leaves[i] = val;
-	if (sysinfo_td_conf->num_cpuid_config > ARRAY_SIZE(sysinfo_td_conf->cpuid_config_values))
-		return -EINVAL;
-	for (i = 0; i < sysinfo_td_conf->num_cpuid_config; i++)
-		for (j = 0; j < 2; j++)
-			if (!ret && !(ret = read_sys_metadata_field(0x9900000300000500 + i * 2 + j, &val)))
-				sysinfo_td_conf->cpuid_config_values[i][j] = val;
-
-	return ret;
+	pr_info("header 0x%016llx id 0x%016llx elements_in_field %d field %d\n", sequence->sequence_header.raw, base_id,
+		sequence->sequence_header.last_element_in_field + 1,
+		sequence->sequence_header.last_field_in_sequence + 1);
+
+	/* Iterate over all elements in the sequence */
+	for (i = 0; i < num_elements; i++) {
+		field_id = base_id + i;
+		data = sequence->element + i;
+
+		switch (field_id) {
+		#define READ_TDX_MD(name, field)			\
+			case (TDX_MD_ID_##name & TDX_MD_ID_MASK):	\
+				field = *data;				\
+				break;
+
+		READ_TDX_MD(MINOR_VERSION, sysinfo->version.minor_version);
+		READ_TDX_MD(MAJOR_VERSION, sysinfo->version.major_version);
+		READ_TDX_MD(UPDATE_VERSION, sysinfo->version.update_version);
+
+		READ_TDX_MD(MODULE_HV, sysinfo->handoff.module_hv);
+
+		READ_TDX_MD(TDX_FEATURES0, sysinfo->features.tdx_features0);
+
+		READ_TDX_MD(MAX_TDMRS, sysinfo->tdmr.max_tdmrs);
+		READ_TDX_MD(MAX_RESERVED_PER_TDMR, sysinfo->tdmr.max_reserved_per_tdmr);
+		READ_TDX_MD(PAMT_4K_ENTRY_SIZE, sysinfo->tdmr.pamt_4k_entry_size);
+		READ_TDX_MD(PAMT_2M_ENTRY_SIZE, sysinfo->tdmr.pamt_2m_entry_size);
+		READ_TDX_MD(PAMT_1G_ENTRY_SIZE, sysinfo->tdmr.pamt_1g_entry_size);
+
+		READ_TDX_MD(TDR_BASE_SIZE, sysinfo->td_ctrl.tdr_base_size);
+		READ_TDX_MD(TDCS_BASE_SIZE, sysinfo->td_ctrl.tdcs_base_size);
+		READ_TDX_MD(TDVPS_BASE_SIZE, sysinfo->td_ctrl.tdvps_base_size);
+
+		READ_TDX_MD(ATTRIBUTES_FIXED0, sysinfo->td_conf.attributes_fixed0);
+		READ_TDX_MD(ATTRIBUTES_FIXED1, sysinfo->td_conf.attributes_fixed1);
+		READ_TDX_MD(XFAM_FIXED0, sysinfo->td_conf.xfam_fixed0);
+		READ_TDX_MD(XFAM_FIXED1, sysinfo->td_conf.xfam_fixed1);
+		READ_TDX_MD(NUM_CPUID_CONFIG, sysinfo->td_conf.num_cpuid_config);
+		READ_TDX_MD(MAX_VCPUS_PER_TD, sysinfo->td_conf.max_vcpus_per_td);
+		#undef READ_TDX_MD
+
+		case TDX_MD_ID_CPUID_CONFIG_LEAVES & TDX_MD_ID_MASK:
+			for (j = 0; j < sysinfo->td_conf.num_cpuid_config; j++)
+				sysinfo->td_conf.cpuid_config_leaves[j] = data[j];
+			/* return as all elements in this sequence are handled */
+			return;
+		case TDX_MD_ID_CPUID_CONFIG_VALUES & TDX_MD_ID_MASK:
+			for (j = 0; j < sysinfo->td_conf.num_cpuid_config; j++) {
+				sysinfo->td_conf.cpuid_config_values[j][0] = data[2*j];
+				sysinfo->td_conf.cpuid_config_values[j][1] = data[2*j+1];
+			}
+			/* return as all elements in this sequence are handled */
+			return;
+		default:
+			break;
+		}
+	}
 }
 
-static int get_tdx_sys_info_handoff(struct tdx_sys_info_handoff *sysinfo_handoff)
+static void parse_md_list(struct md_list_header *list_header, struct tdx_sys_info *sysinfo)
 {
-	int ret = 0;
-	u64 val;
-
-	if (tdx_supports_runtime_update(&tdx_sysinfo) &&
-	    !(ret = read_sys_metadata_field(0x8900000100000000, &val)))
-		sysinfo_handoff->module_hv = val;
-
-	return ret;
+	struct md_sequence *sequence;
+	u32 num_elements;
+	int i = 0;
+
+	pr_info("header: buff_size %u, num_sequences %u\n",
+		list_header->list_buff_size,
+		list_header->num_sequences);
+
+	sequence = (struct md_sequence *)(list_header + 1);
+
+	while (i < list_header->num_sequences) {
+		num_elements = (sequence->sequence_header.last_element_in_field + 1) *
+			       (sequence->sequence_header.last_field_in_sequence + 1);
+		parse_md_sequence(sequence, sysinfo);
+		sequence = (struct md_sequence *)(&sequence->element[num_elements]);
+		i++;
+	}
 }
 
 static int get_tdx_sys_info(struct tdx_sys_info *sysinfo)
 {
+	unsigned long buffer;
+	u64 field_id = -1;
	int ret = 0;
 
-	ret = ret ?: get_tdx_sys_info_version(&sysinfo->version);
-	ret = ret ?: get_tdx_sys_info_features(&sysinfo->features);
-	ret = ret ?: get_tdx_sys_info_tdmr(&sysinfo->tdmr);
-	ret = ret ?: get_tdx_sys_info_td_ctrl(&sysinfo->td_ctrl);
-	ret = ret ?: get_tdx_sys_info_td_conf(&sysinfo->td_conf);
-	ret = ret ?: get_tdx_sys_info_handoff(&sysinfo->handoff);
+	buffer = __get_free_page(GFP_KERNEL);
+	if (!buffer)
+		return -ENOMEM;
+
+	do {
+		ret = read_sys_metadata_field(&field_id, (void *)buffer);
+		if (ret)
+			break;
+		parse_md_list((void *)buffer, sysinfo);
+	} while (field_id != -1);
+
+	free_page(buffer);
+	if (ret)
+		pr_info("TDX sysinfo version read all failed: %d\n", ret);
 
	return ret;
 }


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 1/2] x86/virt/tdx: Retrieve TDX module version
  2025-10-01  2:22 ` [PATCH 1/2] x86/virt/tdx: Retrieve TDX module version Chao Gao
@ 2025-10-01 15:15   ` Dave Hansen
  2025-10-22  7:54     ` Chao Gao
  2025-10-24 14:20   ` Vishal Annapurve
  1 sibling, 1 reply; 21+ messages in thread
From: Dave Hansen @ 2025-10-01 15:15 UTC (permalink / raw)
  To: Chao Gao, linux-coco, linux-kernel, x86
  Cc: Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen,
	H. Peter Anvin, Kirill A. Shutemov, Kai Huang, Paolo Bonzini,
	Dan Williams

On 9/30/25 19:22, Chao Gao wrote:
> +	if (!ret && !(ret = read_sys_metadata_field(0x0800000100000003, &val)))
> +		sysinfo_version->minor_version = val;
> +	if (!ret && !(ret = read_sys_metadata_field(0x0800000100000004, &val)))
> +		sysinfo_version->major_version = val;
> +	if (!ret && !(ret = read_sys_metadata_field(0x0800000100000005, &val)))
> +		sysinfo_version->update_version = val;

Heh, how long does this take in practice to get 6 bytes of data out of
the module? When is the point that we move  over to TDH.SYS.RDALL?

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH 1/2] x86/virt/tdx: Retrieve TDX module version
  2025-10-01  2:22 [PATCH 0/2] Expose TDX Module version Chao Gao
@ 2025-10-01  2:22 ` Chao Gao
  2025-10-01 15:15   ` Dave Hansen
  2025-10-24 14:20   ` Vishal Annapurve
  0 siblings, 2 replies; 21+ messages in thread
From: Chao Gao @ 2025-10-01  2:22 UTC (permalink / raw)
  To: linux-coco, linux-kernel, x86
  Cc: Chao Gao, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	Dave Hansen, H. Peter Anvin, Kirill A. Shutemov, Kai Huang,
	Paolo Bonzini, Dan Williams

Each TDX module is associated with a version in the x.y.z format, where x
represents the major version, y the minor version, and z the update
version. Knowing the running TDX module version is valuable for bug
reporting and debugging.

Retrieve the TDX module version using the existing metadata reading
interface, in preparation for exposing it to userspace via sysfs.

Note changes to tdx_global_metadata.{hc} are auto-generated by the
following command.

 $ python tdx.py global_metadata.json tdx_global_metadata.h \
        tdx_global_metadata.c

The 'tdx.py' can be fetched from [1]. The 'global_metadata.json' can be
fetched from [2]. And 'tdx.py' has "BUILD_DATE", "BUILD_NUM" and
"INTERNAL_VERSION" in TDX_STRUCTS; they are removed before running
the above command as they are not needed for now.

Signed-off-by: Chao Gao <chao.gao@intel.com>
Link: https://lore.kernel.org/kvm/0853b155ec9aac09c594caa60914ed6ea4dc0a71.camel@intel.com/ # [1]
Link: https://cdrdv2.intel.com/v1/dl/getContent/795381 # [2]
---
 arch/x86/include/asm/tdx_global_metadata.h  |  7 +++++++
 arch/x86/virt/vmx/tdx/tdx_global_metadata.c | 16 ++++++++++++++++
 2 files changed, 23 insertions(+)

diff --git a/arch/x86/include/asm/tdx_global_metadata.h b/arch/x86/include/asm/tdx_global_metadata.h
index 060a2ad744bf..40689c8dc67e 100644
--- a/arch/x86/include/asm/tdx_global_metadata.h
+++ b/arch/x86/include/asm/tdx_global_metadata.h
@@ -5,6 +5,12 @@
 
 #include <linux/types.h>
 
+struct tdx_sys_info_version {
+	u16 minor_version;
+	u16 major_version;
+	u16 update_version;
+};
+
 struct tdx_sys_info_features {
 	u64 tdx_features0;
 };
@@ -35,6 +41,7 @@ struct tdx_sys_info_td_conf {
 };
 
 struct tdx_sys_info {
+	struct tdx_sys_info_version version;
 	struct tdx_sys_info_features features;
 	struct tdx_sys_info_tdmr tdmr;
 	struct tdx_sys_info_td_ctrl td_ctrl;
diff --git a/arch/x86/virt/vmx/tdx/tdx_global_metadata.c b/arch/x86/virt/vmx/tdx/tdx_global_metadata.c
index 13ad2663488b..0454124803f3 100644
--- a/arch/x86/virt/vmx/tdx/tdx_global_metadata.c
+++ b/arch/x86/virt/vmx/tdx/tdx_global_metadata.c
@@ -7,6 +7,21 @@
  * Include this file to other C file instead.
  */
 
+static int get_tdx_sys_info_version(struct tdx_sys_info_version *sysinfo_version)
+{
+	int ret = 0;
+	u64 val;
+
+	if (!ret && !(ret = read_sys_metadata_field(0x0800000100000003, &val)))
+		sysinfo_version->minor_version = val;
+	if (!ret && !(ret = read_sys_metadata_field(0x0800000100000004, &val)))
+		sysinfo_version->major_version = val;
+	if (!ret && !(ret = read_sys_metadata_field(0x0800000100000005, &val)))
+		sysinfo_version->update_version = val;
+
+	return ret;
+}
+
 static int get_tdx_sys_info_features(struct tdx_sys_info_features *sysinfo_features)
 {
 	int ret = 0;
@@ -89,6 +104,7 @@ static int get_tdx_sys_info(struct tdx_sys_info *sysinfo)
 {
 	int ret = 0;
 
+	ret = ret ?: get_tdx_sys_info_version(&sysinfo->version);
 	ret = ret ?: get_tdx_sys_info_features(&sysinfo->features);
 	ret = ret ?: get_tdx_sys_info_tdmr(&sysinfo->tdmr);
 	ret = ret ?: get_tdx_sys_info_td_ctrl(&sysinfo->td_ctrl);
-- 
2.47.3


^ permalink raw reply	[flat|nested] 21+ messages in thread

end of thread, other threads:[~2026-01-08 20:49 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-01-08  0:31 [PATCH 0/2] x86/virt/tdx: Print TDX module version to dmesg Vishal Verma
2026-01-08  0:31 ` [PATCH 1/2] x86/virt/tdx: Retrieve TDX module version Vishal Verma
2026-01-08 10:41   ` Kiryl Shutsemau
2026-01-08 20:18   ` Edgecombe, Rick P
2026-01-08  0:31 ` [PATCH 2/2] x86/virt/tdx: Print TDX module version during init Vishal Verma
2026-01-08 10:50   ` Kiryl Shutsemau
2026-01-08 18:39     ` Verma, Vishal L
2026-01-08 20:20       ` Edgecombe, Rick P
2026-01-08 20:30         ` Verma, Vishal L
2026-01-08 20:49       ` Dave Hansen
2026-01-08 20:24   ` Edgecombe, Rick P
2026-01-08 20:38     ` Verma, Vishal L
  -- strict thread matches above, loose matches on Subject: below --
2025-10-01  2:22 [PATCH 0/2] Expose TDX Module version Chao Gao
2025-10-01  2:22 ` [PATCH 1/2] x86/virt/tdx: Retrieve TDX module version Chao Gao
2025-10-01 15:15   ` Dave Hansen
2025-10-22  7:54     ` Chao Gao
2025-10-22 10:26       ` Kiryl Shutsemau
2025-10-24  6:33         ` Chao Gao
2025-10-24  9:35           ` Kiryl Shutsemau
2025-10-24 10:04             ` Chao Gao
2025-11-13  1:24       ` Chao Gao
2025-10-24 14:20   ` Vishal Annapurve

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®