[PATCH v3 24/26] x86/virt/seamldr: Extend sigstruct to 16KB

Chao Gao posted 26 patches 2 weeks ago
[PATCH v3 24/26] x86/virt/seamldr: Extend sigstruct to 16KB
Posted by Chao Gao 2 weeks ago
Currently, each TDX Module has a 4KB sigstruct that is passed to the
P-SEAMLDR during module updates to authenticate the TDX Module binary.

Future TDX Module versions will pack additional information into the
sigstruct, which will exceed the current 4KB size limit.

To accommodate this, the sigstruct is being extended to support up to
16KB. Update seamldr_params and tdx-blob structures to handle the larger
sigstruct size.

Signed-off-by: Chao Gao <chao.gao@intel.com>
---
 arch/x86/virt/vmx/tdx/seamldr.c | 28 +++++++++++++++++++---------
 1 file changed, 19 insertions(+), 9 deletions(-)

diff --git a/arch/x86/virt/vmx/tdx/seamldr.c b/arch/x86/virt/vmx/tdx/seamldr.c
index d2d85114d6c4..9e77b24f659c 100644
--- a/arch/x86/virt/vmx/tdx/seamldr.c
+++ b/arch/x86/virt/vmx/tdx/seamldr.c
@@ -29,6 +29,8 @@
 /* P-SEAMLDR can accept up to 496 4KB pages for TDX module binary */
 #define SEAMLDR_MAX_NR_MODULE_4KB_PAGES	496
 
+#define SEAMLDR_MAX_NR_SIG_4KB_PAGES	4
+
 /* scenario field in struct seamldr_params */
 #define SEAMLDR_SCENARIO_UPDATE		1
 
@@ -40,8 +42,8 @@
 struct seamldr_params {
 	u32	version;
 	u32	scenario;
-	u64	sigstruct_pa;
-	u8	reserved[104];
+	u64	sigstruct_pa[SEAMLDR_MAX_NR_SIG_4KB_PAGES];
+	u8	reserved[80];
 	u64	num_module_pages;
 	u64	mod_pages_pa_list[SEAMLDR_MAX_NR_MODULE_4KB_PAGES];
 } __packed;
@@ -121,7 +123,10 @@ static struct seamldr_params *alloc_seamldr_params(const void *module, unsigned
 	if (module_size > SEAMLDR_MAX_NR_MODULE_4KB_PAGES * SZ_4K)
 		return ERR_PTR(-EINVAL);
 
-	if (!IS_ALIGNED(module_size, SZ_4K) || sig_size != SZ_4K ||
+	if (sig_size > SEAMLDR_MAX_NR_SIG_4KB_PAGES * SZ_4K)
+		return ERR_PTR(-EINVAL);
+
+	if (!IS_ALIGNED(module_size, SZ_4K) || !IS_ALIGNED(sig_size, SZ_4K) ||
 	    !IS_ALIGNED((unsigned long)module, SZ_4K) ||
 	    !IS_ALIGNED((unsigned long)sig, SZ_4K))
 		return ERR_PTR(-EINVAL);
@@ -132,12 +137,17 @@ static struct seamldr_params *alloc_seamldr_params(const void *module, unsigned
 
 	params->scenario = SEAMLDR_SCENARIO_UPDATE;
 
-	/*
-	 * Don't assume @sig is page-aligned although it is 4KB-aligned.
-	 * Always add the in-page offset to get the physical address.
-	 */
-	params->sigstruct_pa = (vmalloc_to_pfn(sig) << PAGE_SHIFT) +
-			       ((unsigned long)sig & ~PAGE_MASK);
+	ptr = sig;
+	for (i = 0; i < sig_size / SZ_4K; i++) {
+		/*
+		 * Don't assume @sig is page-aligned although it is 4KB-aligned.
+		 * Always add the in-page offset to get the physical address.
+		 */
+		params->sigstruct_pa[i] = (vmalloc_to_pfn(ptr) << PAGE_SHIFT) +
+					  ((unsigned long)ptr & ~PAGE_MASK);
+		ptr += SZ_4K;
+	}
+
 	params->num_module_pages = module_size / SZ_4K;
 
 	ptr = module;
-- 
2.47.3
Re: [PATCH v3 24/26] x86/virt/seamldr: Extend sigstruct to 16KB
Posted by Huang, Kai 1 week, 2 days ago
On Fri, 2026-01-23 at 06:55 -0800, Chao Gao wrote:
> Currently, each TDX Module has a 4KB sigstruct that is passed to the
> P-SEAMLDR during module updates to authenticate the TDX Module binary.
> 
> Future TDX Module versions will pack additional information into the
> sigstruct, which will exceed the current 4KB size limit.
> 
> To accommodate this, the sigstruct is being extended to support up to
> 16KB. Update seamldr_params and tdx-blob structures to handle the larger
> sigstruct size.
> 
> Signed-off-by: Chao Gao <chao.gao@intel.com>
> ---
>  arch/x86/virt/vmx/tdx/seamldr.c | 28 +++++++++++++++++++---------
>  1 file changed, 19 insertions(+), 9 deletions(-)
> 
> diff --git a/arch/x86/virt/vmx/tdx/seamldr.c b/arch/x86/virt/vmx/tdx/seamldr.c
> index d2d85114d6c4..9e77b24f659c 100644
> --- a/arch/x86/virt/vmx/tdx/seamldr.c
> +++ b/arch/x86/virt/vmx/tdx/seamldr.c
> @@ -29,6 +29,8 @@
>  /* P-SEAMLDR can accept up to 496 4KB pages for TDX module binary */
>  #define SEAMLDR_MAX_NR_MODULE_4KB_PAGES	496
>  
> +#define SEAMLDR_MAX_NR_SIG_4KB_PAGES	4
> +
>  /* scenario field in struct seamldr_params */
>  #define SEAMLDR_SCENARIO_UPDATE		1
>  
> @@ -40,8 +42,8 @@
>  struct seamldr_params {
>  	u32	version;
>  	u32	scenario;
> -	u64	sigstruct_pa;
> -	u8	reserved[104];
> +	u64	sigstruct_pa[SEAMLDR_MAX_NR_SIG_4KB_PAGES];
> +	u8	reserved[80];
>  	u64	num_module_pages;
>  	u64	mod_pages_pa_list[SEAMLDR_MAX_NR_MODULE_4KB_PAGES];
>  } __packed;
> @@ -121,7 +123,10 @@ static struct seamldr_params *alloc_seamldr_params(const void *module, unsigned
>  	if (module_size > SEAMLDR_MAX_NR_MODULE_4KB_PAGES * SZ_4K)
>  		return ERR_PTR(-EINVAL);
>  
> -	if (!IS_ALIGNED(module_size, SZ_4K) || sig_size != SZ_4K ||
> +	if (sig_size > SEAMLDR_MAX_NR_SIG_4KB_PAGES * SZ_4K)
> +		return ERR_PTR(-EINVAL);
> +
> +	if (!IS_ALIGNED(module_size, SZ_4K) || !IS_ALIGNED(sig_size, SZ_4K) ||
>  	    !IS_ALIGNED((unsigned long)module, SZ_4K) ||
>  	    !IS_ALIGNED((unsigned long)sig, SZ_4K))
>  		return ERR_PTR(-EINVAL);
> @@ -132,12 +137,17 @@ static struct seamldr_params *alloc_seamldr_params(const void *module, unsigned
>  
>  	params->scenario = SEAMLDR_SCENARIO_UPDATE;
>  
> -	/*
> -	 * Don't assume @sig is page-aligned although it is 4KB-aligned.
> -	 * Always add the in-page offset to get the physical address.
> -	 */
> -	params->sigstruct_pa = (vmalloc_to_pfn(sig) << PAGE_SHIFT) +
> -			       ((unsigned long)sig & ~PAGE_MASK);
> +	ptr = sig;
> +	for (i = 0; i < sig_size / SZ_4K; i++) {
> +		/*
> +		 * Don't assume @sig is page-aligned although it is 4KB-aligned.
> +		 * Always add the in-page offset to get the physical address.
> +		 */
> +		params->sigstruct_pa[i] = (vmalloc_to_pfn(ptr) << PAGE_SHIFT) +
> +					  ((unsigned long)ptr & ~PAGE_MASK);
> +		ptr += SZ_4K;
> +	}
> +
>  	params->num_module_pages = module_size / SZ_4K;
>  
>  	ptr = module;

Let's move the discussion here (from patch 13 -- sorry about that):

IIRC this patch just simply re-purposes couple of reserved space in
SEAMLDR_PARAMS (which is part of P-SEAMLDR ABI) w/o enumeration, explicit
opt-in whatever.  The code change here doesn't even bump up its version.

IIUC, if this code run on an old platform where SEAMLDR.INSTALL still only
works with 4K SIGSTRUCT, the SEAMLDR.INSTALL will only see part of the
SIGSTRUCT thus will likely fail.

How can we know whether a given 'struct tdx_blob' can work on an platform or
not?  Or am I missing anything?
Re: [PATCH v3 24/26] x86/virt/seamldr: Extend sigstruct to 16KB
Posted by Chao Gao 1 week ago
>Let's move the discussion here (from patch 13 -- sorry about that):
>
>IIRC this patch just simply re-purposes couple of reserved space in
>SEAMLDR_PARAMS (which is part of P-SEAMLDR ABI) w/o enumeration, explicit
>opt-in whatever.  The code change here doesn't even bump up its version.
>
>IIUC, if this code run on an old platform where SEAMLDR.INSTALL still only
>works with 4K SIGSTRUCT, the SEAMLDR.INSTALL will only see part of the
>SIGSTRUCT thus will likely fail.
>
>How can we know whether a given 'struct tdx_blob' can work on an platform or
>not?  Or am I missing anything?

Good question.

This is actually userspace's responsibility. The kernel exposes P-SEAMLDR
version to userspace, and for each module, the mapping file [*] lists the
module's minimum P-SEAMLDR version requirements. This allows userspace to
determine whether the existing P-SEAMLDR can load a specific TDX blob.

If the kernel cannot load a module using the current P-SEAMLDR, that's
userspace's fault.

*: https://github.com/intel/confidential-computing.tdx.tdx-module.binaries/blob/main/mapping_file.json
Re: [PATCH v3 24/26] x86/virt/seamldr: Extend sigstruct to 16KB
Posted by Huang, Kai 4 days, 17 hours ago
On Fri, 2026-01-30 at 22:25 +0800, Gao, Chao wrote:
> > Let's move the discussion here (from patch 13 -- sorry about that):
> > 
> > IIRC this patch just simply re-purposes couple of reserved space in
> > SEAMLDR_PARAMS (which is part of P-SEAMLDR ABI) w/o enumeration, explicit
> > opt-in whatever.  The code change here doesn't even bump up its version.
> > 
> > IIUC, if this code run on an old platform where SEAMLDR.INSTALL still only
> > works with 4K SIGSTRUCT, the SEAMLDR.INSTALL will only see part of the
> > SIGSTRUCT thus will likely fail.
> > 
> > How can we know whether a given 'struct tdx_blob' can work on an platform or
> > not?  Or am I missing anything?
> 
> Good question.
> 
> This is actually userspace's responsibility. The kernel exposes P-SEAMLDR
> version to userspace, and for each module, the mapping file [*] lists the
> module's minimum P-SEAMLDR version requirements. This allows userspace to
> determine whether the existing P-SEAMLDR can load a specific TDX blob.
> 
> If the kernel cannot load a module using the current P-SEAMLDR, that's
> userspace's fault.
> 
> *: https://github.com/intel/confidential-computing.tdx.tdx-module.binaries/blob/main/mapping_file.json

Thanks for the info.

In this case, I am not sure why do you need to implement code (patch 13) to
firstly support 4K less SIGSTRUCT (with a confusing doc of 'tdx_blob' layout
definition), but here extend it to 16K in a second patch?

How about just merge this one to patch 13 and point out this fact in
changelog if needed?

E.g.,:

  For a given TDX blob, not all SEAMLDR and TDX module versions support 
  runtime update for it.  Intel publishes the requirement of the minimal
  SEAMLDR and TDX module versions for it.

  There's no hardware/firmware interface that the kernel could use to
  detect and bail out early if such requirement is not met.  It's
  userspace's responsibility to make sure such requirement is met before
	 	
  performing runtime update.

Actually, assuming the new spec which reflects 16KB SIGSTRUCT in
SEAMLDR_PARAMS will be published, I _think_ the fact that "some old SEMALDR
versions only support upto 4K SIGSTRUCT" probably doesn't matter anymore,
especially if we add the above to the changelog.

So I don't quite see why we need to keep this "extend SIGSTRUCT to 16KB" as
a separate patch?

Btw, we also need the updated doc of TDX blob layout too, to reflect what
your code is doing (regarding to how to calculate SIGSTRUCT base/size).

And we need to make sure the TDX blob layout is architectural.
Re: [PATCH v3 24/26] x86/virt/seamldr: Extend sigstruct to 16KB
Posted by Huang, Kai 1 week, 4 days ago
On Fri, 2026-01-23 at 06:55 -0800, Gao, Chao wrote:
> Currently, each TDX Module has a 4KB sigstruct that is passed to the
> P-SEAMLDR during module updates to authenticate the TDX Module binary.
> 
> Future TDX Module versions will pack additional information into the
> sigstruct, which will exceed the current 4KB size limit.
> 
> To accommodate this, the sigstruct is being extended to support up to
> 16KB. 
> 

[...]

> Update seamldr_params and tdx-blob structures to handle the larger
> sigstruct size.

Nit: there's no update to 'struct tdx_blob' in this patch.

Btw, is there any spec/doc that mentions this publicly?

E.g., we do need some update to the TDX module blob doc, right?
Re: [PATCH v3 24/26] x86/virt/seamldr: Extend sigstruct to 16KB
Posted by Tony Lindgren 1 week, 4 days ago
On Fri, Jan 23, 2026 at 06:55:32AM -0800, Chao Gao wrote:
> Currently, each TDX Module has a 4KB sigstruct that is passed to the
> P-SEAMLDR during module updates to authenticate the TDX Module binary.
> 
> Future TDX Module versions will pack additional information into the
> sigstruct, which will exceed the current 4KB size limit.
> 
> To accommodate this, the sigstruct is being extended to support up to
> 16KB. Update seamldr_params and tdx-blob structures to handle the larger
> sigstruct size.

Reviewed-by: Tony Lindgren <tony.lindgren@linux.intel.com>