From: Nikolay Borisov <nik.borisov@suse.com>
To: Xu Yilun <yilun.xu@linux.intel.com>,
x86@kernel.org, kvm@vger.kernel.org, linux-coco@lists.linux.dev,
linux-kernel@vger.kernel.org
Cc: djbw@kernel.org, kas@kernel.org, rick.p.edgecombe@intel.com,
yilun.xu@intel.com, xiaoyao.li@intel.com, sohil.mehta@intel.com,
adrian.hunter@intel.com, kishen.maloor@intel.com,
tony.lindgren@linux.intel.com, peter.fang@intel.com,
baolu.lu@linux.intel.com, zhenzhong.duan@intel.com,
dave.hansen@intel.com, dave.hansen@linux.intel.com,
seanjc@google.com
Subject: Re: [PATCH v2 08/17] x86/virt/tdx: Prepare Quote buffer during extension bringup
Date: Wed, 8 Jul 2026 10:52:07 +0300 [thread overview]
Message-ID: <d13c4073-b248-40ac-aa28-1c0dfc6b9043@suse.com> (raw)
In-Reply-To: <20260618081355.3253581-9-yilun.xu@linux.intel.com>
On 6/18/26 11:13, Xu Yilun wrote:
> From: Peter Fang <peter.fang@intel.com>
>
> During TDX attestation, the TDX guest asks the host to generate a
> signed, verifiable structure (a "Quote"). With the Quoting extension,
> the TDX module returns the Quote in pages that the host shares via an
> Extension-SEAMCALL.
nit: Just say the host provides the pages to the TDX module, no need to
specify if it's via an ext seamcall or some otherway. One can infer this
from the code itself.
>
> The SEAMCALL accepts the host buffer pages as a linked list of 4KB
> "HPA_LINKED_LIST" nodes. Each entry holds the physical address of a 4KB
> data page, except for the last entry, which points to the next node. The
> TDX module reports the required Quote buffer size through a global
> metadata field. See [1] for details.
That HPA_LINKED_LIST is basically a linked list of arrays, each node
into the linked list being the array, and each entry of that array being
the HPA witht he last being a pointer to the next HPA_LINKED_LIST, so in
a way a 2 level data structure. Can you be more explicit and just say
something along the lines of :
"SEAMCALL accepts host buffer pages arranged in a custom data structure,
consisting of nodes containing HPAs, arranged linearly, and each node is
linked to the next one via the last entry"
>
> For simplicity, let all guests share a global buffer. Build the buffer's
> HPA_LINKED_LIST at Quoting extension bringup. This saves a bunch of
> va-to-pa conversions at runtime.
>
> [1] Intel TDX Module ABI specification, Section "Physical Memory
> Management Types"
>
> Signed-off-by: Peter Fang <peter.fang@intel.com>
> Signed-off-by: Xu Yilun <yilun.xu@linux.intel.com>
> ---
> arch/x86/include/asm/tdx_global_metadata.h | 4 +
> arch/x86/virt/vmx/tdx/tdx.c | 115 +++++++++++++++++++-
> arch/x86/virt/vmx/tdx/tdx_global_metadata.c | 14 +++
> 3 files changed, 129 insertions(+), 4 deletions(-)
>
> diff --git a/arch/x86/include/asm/tdx_global_metadata.h b/arch/x86/include/asm/tdx_global_metadata.h
> index b3442b7c88bb..17cb13a1bb40 100644
> --- a/arch/x86/include/asm/tdx_global_metadata.h
> +++ b/arch/x86/include/asm/tdx_global_metadata.h
> @@ -57,4 +57,8 @@ struct tdx_sys_info_ext {
> bool ext_required;
> };
>
> +struct tdx_sys_info_quote {
> + u32 max_quote_size;
> +};
> +
> #endif
> diff --git a/arch/x86/virt/vmx/tdx/tdx.c b/arch/x86/virt/vmx/tdx/tdx.c
> index 06c42b86b05e..9716424a301f 100644
> --- a/arch/x86/virt/vmx/tdx/tdx.c
> +++ b/arch/x86/virt/vmx/tdx/tdx.c
> @@ -32,6 +32,7 @@
> #include <linux/idr.h>
> #include <linux/kvm_types.h>
> #include <linux/bitfield.h>
> +#include <linux/vmalloc.h>
> #include <asm/page.h>
> #include <asm/special_insns.h>
> #include <asm/msr-index.h>
> @@ -71,6 +72,24 @@ static LIST_HEAD(tdx_memlist);
>
> static struct tdx_sys_info tdx_sysinfo;
>
> +/*
> + * Quote buffer shared with the TDX module for quote generation, in HPA linked
> + * list format.
> + *
> + * @buf: Virtual address of the quote buffer.
> + * @buf_len: Size of @buf in bytes.
> + * @hpa_entries: HPA entries, starting at the first list node.
> + * @hpa_entries_pa: Physical address for @hpa_entries.
> + */
> +struct tdx_quote_data {
> + void *buf;
> + u64 buf_len;
> + u64 *hpa_entries;
> + phys_addr_t hpa_entries_pa;
> +};
> +
> +static struct tdx_quote_data tdx_quote;
> +
> static DEFINE_RAW_SPINLOCK(sysinit_lock);
>
> /*
> @@ -1167,6 +1186,81 @@ static __init int init_tdmrs(struct tdmr_info_list *tdmr_list)
> return 0;
> }
>
> +static inline phys_addr_t tdx_vmalloc_to_pa(const void *addr)
> +{
> + unsigned long pfn = vmalloc_to_pfn(addr);
> +
> + return PFN_PHYS(pfn);
> +}
> +
> +#define HPAS_PER_NODE (PAGE_SIZE / sizeof(u64))
> +
> +/*
> + * Pass the quote buffer to the TDX module as an HPA linked list, where each
> + * node holds 4KB page HPAs and the last entry points to the next node.
> + */
> +static __init int tdx_quote_create_buf(unsigned int npages,
> + struct tdx_quote_data *qdata)
> +{
> + unsigned int nnodes;
> + u64 *hpas;
> + void *qbuf;
> + int i, j;
> +
> + if (!npages)
> + return -EINVAL;
> +
> + /*
> + * Each node holds up to (HPAS_PER_NODE - 1) 4KB page HPAs.
> + * The last entry of the node points to the next node.
> + */
> + nnodes = DIV_ROUND_UP(npages, HPAS_PER_NODE - 1);
nit: It's somewhat arbitrary but num_nodes seems more explicit, saving 3
chars is not worth it.
> +
> + hpas = vmalloc_array(nnodes, PAGE_SIZE);
hpas is basically the starting node, so name it "nodes". Also I'm
slightly confused why you use vmalloc to allocate a contiguous address
space when the nodes are linked in a list? I.e you keep referring to
list in the changelog and the code seems to be working in an array chunks?
> + if (!hpas)
> + return -ENOMEM;
> +
> + /*
> + * ~0ULL is the list terminator for HPA_LINKED_LIST.
> + *
> + * Pre-fill the last node with 0xff bytes so that unused entries are
> + * terminators. Overwrite populated entries later.
> + */
> + memset((u8 *)hpas + (nnodes - 1) * PAGE_SIZE, 0xff, PAGE_SIZE);
> +
> + qbuf = vcalloc(npages, PAGE_SIZE);
> + if (!qbuf)
> + goto out_nomem;
'qbuf' is rather arbitrary here. You simply pre-allocate a bunch of
pages which you then initialize into the nodes. Can't this allocation be
moved inside the loop itself, of course it will increase the number of
allocs happening but this is during initialization so it's not
performance critical, yes?
> +
> + /* Populate the linked list */
> + for (i = 0, j = 0; j < npages; i++) {
nit: This feedback was given before, but both variables can be defined
in this loop.
> + if ((i % HPAS_PER_NODE) == HPAS_PER_NODE - 1) {
> + /*
> + * The last node entry always points to the next node.
> + * The address of the following entry must be on next
> + * node's page boundary.
> + */
> + hpas[i] = tdx_vmalloc_to_pa(&hpas[i + 1]);
> + continue;
> + }
> +
> + hpas[i] = tdx_vmalloc_to_pa((u8 *)qbuf + j * PAGE_SIZE);
> + j++;
> + }
> +> + qdata->buf = qbuf;
> + qdata->buf_len = (u64)npages * PAGE_SIZE;
> + qdata->hpa_entries = hpas;
> + qdata->hpa_entries_pa = tdx_vmalloc_to_pa(hpas);
> +
> + return 0;
> +
> +out_nomem:
> + vfree(hpas);
> +
> + return -ENOMEM;
> +}
> +
> /* Initialize quoting extension */
> static __init int tdx_quote_init(void)
> {
> @@ -1185,12 +1279,25 @@ static __init int tdx_quote_init(void)
>
> static __init void init_tdx_quoting_extension(void)
> {
> - int ret;
> + struct tdx_sys_info_quote sysinfo_quote;
> + unsigned int nr_quote_pages;
> +
> + if (!(tdx_addon_feature0 & TDX_FEATURES0_QUOTE))
> + return;
>
> - if (tdx_addon_feature0 & TDX_FEATURES0_QUOTE) {
> - ret = tdx_quote_init();
> - WARN_ON_ONCE(ret);
> + if (tdx_quote_init()) {
> + WARN_ON_ONCE(1);
> + return;
> }
> +
> + /* Quoting metadata is valid only after initialization */
> + if (get_tdx_sys_info_quote(&sysinfo_quote))
> + return;
> +
> + nr_quote_pages = PAGE_ALIGN(sysinfo_quote.max_quote_size) /
> + PAGE_SIZE;
> + if (tdx_quote_create_buf(nr_quote_pages, &tdx_quote))
> + pr_err("Failed to create quote buffer\n");
> }
>
> /* Initialize TDX module extensions for extension SEAMCALLs */
> diff --git a/arch/x86/virt/vmx/tdx/tdx_global_metadata.c b/arch/x86/virt/vmx/tdx/tdx_global_metadata.c
> index 84364da89649..1eb2985307c6 100644
> --- a/arch/x86/virt/vmx/tdx/tdx_global_metadata.c
> +++ b/arch/x86/virt/vmx/tdx/tdx_global_metadata.c
> @@ -151,3 +151,17 @@ static int get_tdx_sys_info_ext(struct tdx_sys_info_ext *sysinfo_ext)
>
> return 0;
> }
> +
> +static __init int get_tdx_sys_info_quote(struct tdx_sys_info_quote *sysinfo_quote)
> +{
> + int ret;
> + u64 val;
> +
> + ret = read_sys_metadata_field(0x2300000200000002, &val);
> + if (ret)
> + return ret;
> +
> + sysinfo_quote->max_quote_size = val;
> +
> + return 0;
> +}
next prev parent reply other threads:[~2026-07-08 7:52 UTC|newest]
Thread overview: 72+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-18 8:13 [PATCH v2 00/17] Enable DICE-based TDX Quoting Extension Xu Yilun
2026-06-18 8:13 ` [PATCH v2 01/17] x86/virt/tdx: Embed version info in SEAMCALL leaf function definitions Xu Yilun
2026-06-18 14:45 ` Dave Hansen
2026-06-22 12:05 ` Xu Yilun
2026-06-18 8:13 ` [PATCH v2 02/17] x86/virt/tdx: Configure add-on features on TDX module init and update Xu Yilun
2026-06-18 15:04 ` Dave Hansen
2026-06-22 13:15 ` Xu Yilun
2026-06-24 12:00 ` Xu Yilun
2026-06-24 22:10 ` Peter Fang
2026-06-25 6:33 ` Xu Yilun
2026-06-23 8:43 ` Chao Gao
2026-06-25 10:50 ` Xu Yilun
2026-06-18 8:13 ` [PATCH v2 03/17] x86/virt/tdx: Detect if the extensions initialization is required Xu Yilun
2026-06-25 5:19 ` Tony Lindgren
2026-06-25 10:57 ` Xu Yilun
2026-06-29 6:33 ` Chao Gao
2026-06-30 11:10 ` Xu Yilun
2026-06-18 8:13 ` [PATCH v2 04/17] x86/virt/tdx: Add extra memory to TDX module for the extensions Xu Yilun
2026-06-29 7:56 ` Chao Gao
2026-06-30 10:27 ` Xu Yilun
2026-06-18 8:13 ` [PATCH v2 05/17] x86/virt/tdx: Make TDX module initialize " Xu Yilun
2026-06-18 8:13 ` [PATCH v2 06/17] x86/virt/tdx: Re-initialize the extensions on runtime TDX module update Xu Yilun
2026-06-29 8:12 ` Chao Gao
2026-06-30 11:14 ` Xu Yilun
2026-06-18 8:13 ` [PATCH v2 07/17] x86/virt/tdx: Initialize Quoting extension Xu Yilun
2026-06-29 8:33 ` Chao Gao
2026-06-30 5:20 ` Peter Fang
2026-06-18 8:13 ` [PATCH v2 08/17] x86/virt/tdx: Prepare Quote buffer during extension bringup Xu Yilun
2026-06-25 6:08 ` Tony Lindgren
2026-06-30 4:12 ` Peter Fang
2026-07-01 19:56 ` Dave Hansen
2026-07-08 9:25 ` Peter Fang
2026-07-08 7:52 ` Nikolay Borisov [this message]
2026-06-18 8:13 ` [PATCH v2 09/17] x86/virt/tdx: Add interface to check Quoting availability Xu Yilun
2026-06-25 6:09 ` Tony Lindgren
2026-06-18 8:13 ` [PATCH v2 10/17] x86/virt/tdx: Move tdx_tdr_pa() up in the file Xu Yilun
2026-06-25 6:10 ` Tony Lindgren
2026-06-18 8:13 ` [PATCH v2 11/17] x86/virt/tdx: Add interface to generate a Quote Xu Yilun
2026-06-25 6:05 ` Tony Lindgren
2026-06-30 4:22 ` Peter Fang
2026-06-18 8:13 ` [PATCH v2 12/17] x86/virt/tdx: Reinitialize the Quoting extension after TDX module update Xu Yilun
2026-06-25 6:12 ` Tony Lindgren
2026-06-18 8:13 ` [PATCH v2 13/17] x86/virt/tdx: Enable Quoting extension Xu Yilun
2026-06-25 6:13 ` Tony Lindgren
2026-06-18 8:13 ` [PATCH v2 14/17] x86/tdx: Move and rename Quote request structure Xu Yilun
2026-06-25 6:15 ` Tony Lindgren
2026-06-18 8:13 ` [PATCH v2 15/17] KVM: TDX: Factor out userspace return path from tdx_get_quote() Xu Yilun
2026-06-25 6:16 ` Tony Lindgren
2026-06-18 8:13 ` [PATCH v2 16/17] KVM: TDX: Add in-kernel Quote generation Xu Yilun
2026-06-25 18:01 ` Sean Christopherson
2026-06-29 10:03 ` Peter Fang
2026-06-30 0:42 ` Sean Christopherson
2026-06-30 23:33 ` Edgecombe, Rick P
2026-07-01 0:24 ` Dan Williams (nvidia)
2026-07-01 17:25 ` Sean Christopherson
2026-07-01 18:45 ` Edgecombe, Rick P
2026-07-04 5:43 ` Peter Fang
2026-07-06 17:57 ` Sean Christopherson
2026-07-08 20:47 ` Dave Hansen
2026-07-08 21:16 ` Sean Christopherson
2026-07-08 22:09 ` Peter Fang
2026-07-08 22:28 ` Sean Christopherson
2026-07-08 23:38 ` Edgecombe, Rick P
2026-07-10 9:01 ` Nikolay Borisov
2026-07-10 9:38 ` Peter Fang
2026-07-08 21:37 ` Sean Christopherson
2026-07-10 12:52 ` Peter Fang
2026-07-10 14:48 ` Sean Christopherson
2026-07-10 22:59 ` Peter Fang
2026-06-18 8:13 ` [PATCH v2 17/17] KVM: TDX: Support event-notify interrupts only with userspace Quoting Xu Yilun
2026-06-25 6:28 ` Tony Lindgren
2026-06-30 6:36 ` Peter Fang
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=d13c4073-b248-40ac-aa28-1c0dfc6b9043@suse.com \
--to=nik.borisov@suse.com \
--cc=adrian.hunter@intel.com \
--cc=baolu.lu@linux.intel.com \
--cc=dave.hansen@intel.com \
--cc=dave.hansen@linux.intel.com \
--cc=djbw@kernel.org \
--cc=kas@kernel.org \
--cc=kishen.maloor@intel.com \
--cc=kvm@vger.kernel.org \
--cc=linux-coco@lists.linux.dev \
--cc=linux-kernel@vger.kernel.org \
--cc=peter.fang@intel.com \
--cc=rick.p.edgecombe@intel.com \
--cc=seanjc@google.com \
--cc=sohil.mehta@intel.com \
--cc=tony.lindgren@linux.intel.com \
--cc=x86@kernel.org \
--cc=xiaoyao.li@intel.com \
--cc=yilun.xu@intel.com \
--cc=yilun.xu@linux.intel.com \
--cc=zhenzhong.duan@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox