Re: [PATCH v1 06/26] x86/virt/tdx: Add tdx_page_array helpers for new TDX Module objects

Xu Yilun
2025-11-18T13:02:44Z

On Mon, Nov 17, 2025 at 08:41:37AM -0800, Dave Hansen wrote:
> On 11/16/25 18:22, Xu Yilun wrote:
> > + struct page *root __free(__free_page) = alloc_page(GFP_KERNEL |
> > + __GFP_ZERO);
> > + if (!root)
> > + return NULL;
>
> Why don't you just kcalloc() this like the rest of them?

It's feasible for this patch, see the code below.

But when I'm trying to address the copy-and-paste concern in Patch #15,
I realize the common part is the allocation of the supporting structures
(struct tdx_page_array *, struct page **, the root page), and the
different part is the allocation of data pages that TDX module requires.
So I don't think I should allocate root page along with the data pages
here.

>
> Then you won't need "mm: Add __free() support for __free_page()" either,
> right?

mm.. But I still need this scope-based cleanup in later patch:

[PATCH v1 22/26] coco/tdx-host: Implement SPDM session setup

--------------8<------
diff --git a/arch/x86/include/asm/tdx.h b/arch/x86/include/asm/tdx.h
index b5ad3818f222..bb62f8639040 100644
--- a/arch/x86/include/asm/tdx.h
+++ b/arch/x86/include/asm/tdx.h
@@ -148,6 +148,7 @@ struct tdx_page_array {
unsigned int offset;
unsigned int nents;
struct page *root;
+ struct page **raw;
};

void tdx_page_array_free(struct tdx_page_array *array);
diff --git a/arch/x86/virt/vmx/tdx/tdx.c b/arch/x86/virt/vmx/tdx/tdx.c
index fd622445d3d6..c41af2260475 100644
--- a/arch/x86/virt/vmx/tdx/tdx.c
+++ b/arch/x86/virt/vmx/tdx/tdx.c
@@ -360,15 +360,16 @@ void tdx_page_array_free(struct tdx_page_array *array)
if (!array)
return;

- __free_page(array->root);
- tdx_free_pages_bulk(array->nr_pages, array->pages);
- kfree(array->pages);
+ tdx_free_pages_bulk(array->nr_pages + 1, array->raw);
+ kfree(array->raw);
kfree(array);
}
EXPORT_SYMBOL_GPL(tdx_page_array_free);

static struct tdx_page_array *tdx_page_array_alloc(unsigned int nr_pages)
{
+ /* Need an extra root page to hold the page array HPA list */
+ unsigned int nr_pages_alloc = nr_pages + 1;
int ret;

if (!nr_pages)
@@ -379,23 +380,19 @@ static struct tdx_page_array *tdx_page_array_alloc(unsigned int nr_pages)
if (!array)
return NULL;

- struct page *root __free(__free_page) = alloc_page(GFP_KERNEL |
- __GFP_ZERO);
- if (!root)
- return NULL;
-
- struct page **pages __free(kfree) = kcalloc(nr_pages, sizeof(*pages),
- GFP_KERNEL);
- if (!pages)
+ struct page **raw __free(kfree) = kcalloc(nr_pages_alloc, sizeof(*raw),
+ GFP_KERNEL);
+ if (!raw)
return NULL;

- ret = tdx_alloc_pages_bulk(nr_pages, pages);
+ ret = tdx_alloc_pages_bulk(nr_pages_alloc, raw);
if (ret)
return NULL;

+ array->root = raw[0];
+ array->pages = raw + 1;
array->nr_pages = nr_pages;
- array->pages = no_free_ptr(pages);
- array->root = no_free_ptr(root);
+ array->raw = no_free_ptr(raw);

return no_free_ptr(array);
}