* [PATCH v5 1/6] x86/tdx: Take the Quote buffer as a generic pointer
2026-09-28 10:08 [PATCH v5 0/6] tdx-guest: Make Quote buffer size dynamic Peter Fang
@ 2026-09-28 10:08 ` Peter Fang
2026-09-28 19:04 ` Edgecombe, Rick P
2026-09-28 10:08 ` [PATCH v5 2/6] virt: tdx-guest: Give the Quote buffer an explicit type Peter Fang
` (4 subsequent siblings)
5 siblings, 1 reply; 13+ messages in thread
From: Peter Fang @ 2026-09-28 10:08 UTC (permalink / raw)
To: Dave Hansen, Kiryl Shutsemau, Rick Edgecombe, Kuppuswamy Sathyanarayanan
Cc: Thomas Gleixner, Ingo Molnar, Borislav Petkov, x86,
H. Peter Anvin, linux-kernel, linux-coco, kvm, Xiaoyao Li,
Binbin Wu, Tony Lindgren, Sean Christopherson, Artem Bityutskiy,
Peter Fang
tdx_hcall_get_quote() takes a "u8 *" buffer unnecessarily. It is never
used as such, since only the buffer's memory address matters. Let the
guest driver give the buffer a type internally and just accept it as a
"void *" instead.
AI was used under supervision to collect/apply feedback, review code and
workshop logs.
Signed-off-by: Peter Fang <peter.fang@intel.com>
---
v5:
- New patch. Prepare for a typed Quote buffer. [Dave]
---
arch/x86/coco/tdx/tdx.c | 2 +-
arch/x86/include/asm/tdx.h | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/x86/coco/tdx/tdx.c b/arch/x86/coco/tdx/tdx.c
index f904a636d449..bcaf4180a8db 100644
--- a/arch/x86/coco/tdx/tdx.c
+++ b/arch/x86/coco/tdx/tdx.c
@@ -191,7 +191,7 @@ EXPORT_SYMBOL_GPL(tdx_mcall_extend_rtmr);
*
* Return 0 on success or error code on failure.
*/
-u64 tdx_hcall_get_quote(u8 *buf, size_t size)
+u64 tdx_hcall_get_quote(void *buf, size_t size)
{
/* Since buf is a shared memory, set the shared (decrypted) bits */
return _tdx_hypercall(TDVMCALL_GET_QUOTE, cc_mkdec(virt_to_phys(buf)), size, 0, 0);
diff --git a/arch/x86/include/asm/tdx.h b/arch/x86/include/asm/tdx.h
index 89e97d5761d8..a3c37d61e676 100644
--- a/arch/x86/include/asm/tdx.h
+++ b/arch/x86/include/asm/tdx.h
@@ -81,7 +81,7 @@ int tdx_mcall_get_report0(u8 *reportdata, u8 *tdreport);
int tdx_mcall_extend_rtmr(u8 index, u8 *data);
-u64 tdx_hcall_get_quote(u8 *buf, size_t size);
+u64 tdx_hcall_get_quote(void *buf, size_t size);
void __init tdx_dump_attributes(u64 td_attr);
void __init tdx_dump_td_ctls(u64 td_ctls);
--
2.53.0
^ permalink raw reply [flat|nested] 13+ messages in thread* Re: [PATCH v5 1/6] x86/tdx: Take the Quote buffer as a generic pointer
2026-09-28 10:08 ` [PATCH v5 1/6] x86/tdx: Take the Quote buffer as a generic pointer Peter Fang
@ 2026-09-28 19:04 ` Edgecombe, Rick P
0 siblings, 0 replies; 13+ messages in thread
From: Edgecombe, Rick P @ 2026-09-28 19:04 UTC (permalink / raw)
To: sathyanarayanan.kuppuswamy, kas, Fang, Peter, dave.hansen
Cc: seanjc, bp, x86, binbin.wu, hpa, mingo, linux-kernel, Li,
Xiaoyao, tglx, kvm, linux-coco, Bityutskiy, Artem, tony.lindgren
On Mon, 2026-09-28 at 03:08 -0700, Peter Fang wrote:
> tdx_hcall_get_quote() takes a "u8 *" buffer unnecessarily. It is never
> used as such, since only the buffer's memory address matters. Let the
> guest driver give the buffer a type internally and just accept it as a
> "void *" instead.
>
> AI was used under supervision to collect/apply feedback, review code and
> workshop logs.
>
> Signed-off-by: Peter Fang <peter.fang@intel.com>
> ---
> v5:
> - New patch. Prepare for a typed Quote buffer. [Dave]
I guess this traces back to a comment by Binbin. Which had a specific reason.
Changing the global from a void * means a cast would be needed to pass it to
tdx_hcall_get_quote(). I had to go hunting back multiple versions to learn this
because the log didn't mention it. Otherwise it looks like misc cleanup. Can you
explain the connection to future changes in the log?
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v5 2/6] virt: tdx-guest: Give the Quote buffer an explicit type
2026-09-28 10:08 [PATCH v5 0/6] tdx-guest: Make Quote buffer size dynamic Peter Fang
2026-09-28 10:08 ` [PATCH v5 1/6] x86/tdx: Take the Quote buffer as a generic pointer Peter Fang
@ 2026-09-28 10:08 ` Peter Fang
2026-09-28 10:08 ` [PATCH v5 3/6] virt: tdx-guest: Calculate the Quote buffer size safely Peter Fang
` (3 subsequent siblings)
5 siblings, 0 replies; 13+ messages in thread
From: Peter Fang @ 2026-09-28 10:08 UTC (permalink / raw)
To: Dave Hansen, Kiryl Shutsemau, Rick Edgecombe, Kuppuswamy Sathyanarayanan
Cc: Thomas Gleixner, Ingo Molnar, Borislav Petkov, x86,
H. Peter Anvin, linux-kernel, linux-coco, kvm, Xiaoyao Li,
Binbin Wu, Tony Lindgren, Sean Christopherson, Artem Bityutskiy,
Peter Fang
The Quote buffer is always a "struct tdx_quote_buf", but its global
pointer is a "void *". A function would have to convert it back to make
sense of it.
Declare the global with its actual type, and give it a better name.
This creates variable shadowing in wait_for_quote_completion(), so
rename its parameter for clarity.
AI was used under supervision to collect/apply feedback, review code and
workshop logs.
Signed-off-by: Peter Fang <peter.fang@intel.com>
---
v5:
- New patch. [Dave]
---
drivers/virt/coco/tdx-guest/tdx-guest.c | 35 ++++++++++++-------------
1 file changed, 17 insertions(+), 18 deletions(-)
diff --git a/drivers/virt/coco/tdx-guest/tdx-guest.c b/drivers/virt/coco/tdx-guest/tdx-guest.c
index d0303e31e816..896eb0a09c4a 100644
--- a/drivers/virt/coco/tdx-guest/tdx-guest.c
+++ b/drivers/virt/coco/tdx-guest/tdx-guest.c
@@ -192,7 +192,7 @@ struct tdx_quote_buf {
};
/* Quote data buffer */
-static void *quote_data;
+static struct tdx_quote_buf *quote_buf;
/* Lock to streamline quote requests */
static DEFINE_MUTEX(quote_lock);
@@ -209,7 +209,7 @@ static long tdx_get_report0(struct tdx_report_req __user *req)
USER_SOCKPTR(req->tdreport));
}
-static void free_quote_buf(void *buf)
+static void free_quote_buf(struct tdx_quote_buf *buf)
{
size_t len = PAGE_ALIGN(GET_QUOTE_BUF_SIZE);
unsigned int count = len >> PAGE_SHIFT;
@@ -222,25 +222,25 @@ static void free_quote_buf(void *buf)
free_pages_exact(buf, len);
}
-static void *alloc_quote_buf(void)
+static struct tdx_quote_buf *alloc_quote_buf(void)
{
size_t len = PAGE_ALIGN(GET_QUOTE_BUF_SIZE);
unsigned int count = len >> PAGE_SHIFT;
- void *addr;
+ struct tdx_quote_buf *buf;
- addr = alloc_pages_exact(len, GFP_KERNEL | __GFP_ZERO);
- if (!addr)
+ buf = alloc_pages_exact(len, GFP_KERNEL | __GFP_ZERO);
+ if (!buf)
return NULL;
- if (set_memory_decrypted((unsigned long)addr, count))
+ if (set_memory_decrypted((unsigned long)buf, count))
return NULL;
- return addr;
+ return buf;
}
/*
* wait_for_quote_completion() - Wait for Quote request completion
- * @quote_buf: Address of Quote buffer.
+ * @buf: Address of Quote buffer.
* @timeout: Timeout in seconds to wait for the Quote generation.
*
* As per TDX GHCI v1.0 specification, sec titled "TDG.VP.VMCALL<GetQuote>",
@@ -249,7 +249,7 @@ static void *alloc_quote_buf(void)
* or error code after processing is complete. So wait till the status
* changes from GET_QUOTE_IN_FLIGHT or the request being timed out.
*/
-static int wait_for_quote_completion(struct tdx_quote_buf *quote_buf, u32 timeout)
+static int wait_for_quote_completion(struct tdx_quote_buf *buf, u32 timeout)
{
int i = 0;
@@ -257,7 +257,7 @@ static int wait_for_quote_completion(struct tdx_quote_buf *quote_buf, u32 timeou
* Quote requests usually take a few seconds to complete, so waking up
* once per second to recheck the status is fine for this use case.
*/
- while (quote_buf->status == GET_QUOTE_IN_FLIGHT && i++ < timeout) {
+ while (buf->status == GET_QUOTE_IN_FLIGHT && i++ < timeout) {
if (msleep_interruptible(MSEC_PER_SEC))
return -EINTR;
}
@@ -268,7 +268,6 @@ static int wait_for_quote_completion(struct tdx_quote_buf *quote_buf, u32 timeou
static int tdx_report_new_locked(struct tsm_report *report, void *data)
{
u8 *buf;
- struct tdx_quote_buf *quote_buf = quote_data;
struct tsm_report_desc *desc = &report->desc;
u32 out_len;
int ret;
@@ -285,7 +284,7 @@ static int tdx_report_new_locked(struct tsm_report *report, void *data)
if (desc->inblob_len != TDX_REPORTDATA_LEN)
return -EINVAL;
- memset(quote_data, 0, GET_QUOTE_BUF_SIZE);
+ memset(quote_buf, 0, GET_QUOTE_BUF_SIZE);
/* Update Quote buffer header */
quote_buf->version = GET_QUOTE_CMD_VER;
@@ -296,7 +295,7 @@ static int tdx_report_new_locked(struct tsm_report *report, void *data)
if (ret)
return ret;
- err = tdx_hcall_get_quote(quote_data, GET_QUOTE_BUF_SIZE);
+ err = tdx_hcall_get_quote(quote_buf, GET_QUOTE_BUF_SIZE);
if (err) {
pr_err("GetQuote hypercall failed, status:%llx\n", err);
return -EIO;
@@ -417,8 +416,8 @@ static int __init tdx_guest_init(void)
if (ret)
goto deinit_mr;
- quote_data = alloc_quote_buf();
- if (!quote_data) {
+ quote_buf = alloc_quote_buf();
+ if (!quote_buf) {
pr_err("Failed to allocate Quote buffer\n");
ret = -ENOMEM;
goto free_misc;
@@ -431,7 +430,7 @@ static int __init tdx_guest_init(void)
return 0;
free_quote:
- free_quote_buf(quote_data);
+ free_quote_buf(quote_buf);
free_misc:
misc_deregister(&tdx_misc_dev);
deinit_mr:
@@ -444,7 +443,7 @@ module_init(tdx_guest_init);
static void __exit tdx_guest_exit(void)
{
tsm_report_unregister(&tdx_tsm_ops);
- free_quote_buf(quote_data);
+ free_quote_buf(quote_buf);
misc_deregister(&tdx_misc_dev);
tdx_mr_deinit(tdx_attr_groups[0]);
}
--
2.53.0
^ permalink raw reply [flat|nested] 13+ messages in thread* [PATCH v5 3/6] virt: tdx-guest: Calculate the Quote buffer size safely
2026-09-28 10:08 [PATCH v5 0/6] tdx-guest: Make Quote buffer size dynamic Peter Fang
2026-09-28 10:08 ` [PATCH v5 1/6] x86/tdx: Take the Quote buffer as a generic pointer Peter Fang
2026-09-28 10:08 ` [PATCH v5 2/6] virt: tdx-guest: Give the Quote buffer an explicit type Peter Fang
@ 2026-09-28 10:08 ` Peter Fang
2026-09-28 15:50 ` Dave Hansen
2026-09-28 10:08 ` [PATCH v5 4/6] virt: tdx-guest: Add a helper for the Quote buffer size Peter Fang
` (2 subsequent siblings)
5 siblings, 1 reply; 13+ messages in thread
From: Peter Fang @ 2026-09-28 10:08 UTC (permalink / raw)
To: Dave Hansen, Kiryl Shutsemau, Rick Edgecombe, Kuppuswamy Sathyanarayanan
Cc: Thomas Gleixner, Ingo Molnar, Borislav Petkov, x86,
H. Peter Anvin, linux-kernel, linux-coco, kvm, Xiaoyao Li,
Binbin Wu, Tony Lindgren, Sean Christopherson, Artem Bityutskiy,
Peter Fang
struct tdx_quote_buf has a trailing flexible array member.
struct_size_t() calculates the size of this kind of struct safely. It
handles overflow, which helps since the Quote size comes from the host.
Use it to rewrite the bounds check logic, since
"header_size + data_size > buf_size"
... is more readable than "data_size > buf_size - header_size".
This also prepares for a later change that needs the same
"header_size + data_size" calculation for the Quote buffer size.
AI was used to review code.
Signed-off-by: Peter Fang <peter.fang@intel.com>
Reviewed-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
Reviewed-by: Tony Lindgren <tony.lindgren@linux.intel.com>
Reviewed-by: Xiaoyao Li <xiaoyao.li@intel.com>
Reviewed-by: Binbin Wu <binbin.wu@linux.intel.com>
Reviewed-by: Kiryl Shutsemau (Meta) <kas@kernel.org>
---
v5:
- Rename TDX_QUOTE_BUF_LEN() to TDX_QUOTE_TOTAL_SIZE(). [Dave]
- Add Kiryl's Reviewed-by.
v4:
- No code changes.
- Add Reviewed-by tags. [Sathya, Tony, Xiaoyao, Binbin]
v3:
- Split out the use of struct_size_t() for buffer length from the v2
"Allocate Quote buffer dynamically" patch to refactor first. [Dave]
- Drop the Reviewed-by tags from v2 (Kiryl, Binbin) as the patch was
reworked.
---
drivers/virt/coco/tdx-guest/tdx-guest.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/virt/coco/tdx-guest/tdx-guest.c b/drivers/virt/coco/tdx-guest/tdx-guest.c
index 896eb0a09c4a..b30439584886 100644
--- a/drivers/virt/coco/tdx-guest/tdx-guest.c
+++ b/drivers/virt/coco/tdx-guest/tdx-guest.c
@@ -170,7 +170,7 @@ static void tdx_mr_deinit(const struct attribute_group *mr_grp)
#define GET_QUOTE_SUCCESS 0
#define GET_QUOTE_IN_FLIGHT 0xffffffffffffffff
-#define TDX_QUOTE_MAX_LEN (GET_QUOTE_BUF_SIZE - sizeof(struct tdx_quote_buf))
+#define TDX_QUOTE_TOTAL_SIZE(n) struct_size_t(struct tdx_quote_buf, data, n)
/* struct tdx_quote_buf: Format of Quote request buffer.
* @version: Quote format version, filled by TD.
@@ -314,7 +314,7 @@ static int tdx_report_new_locked(struct tsm_report *report, void *data)
out_len = READ_ONCE(quote_buf->out_len);
- if (out_len > TDX_QUOTE_MAX_LEN)
+ if (TDX_QUOTE_TOTAL_SIZE(out_len) > GET_QUOTE_BUF_SIZE)
return -EFBIG;
buf = kvmemdup(quote_buf->data, out_len, GFP_KERNEL);
--
2.53.0
^ permalink raw reply [flat|nested] 13+ messages in thread* Re: [PATCH v5 3/6] virt: tdx-guest: Calculate the Quote buffer size safely
2026-09-28 10:08 ` [PATCH v5 3/6] virt: tdx-guest: Calculate the Quote buffer size safely Peter Fang
@ 2026-09-28 15:50 ` Dave Hansen
0 siblings, 0 replies; 13+ messages in thread
From: Dave Hansen @ 2026-09-28 15:50 UTC (permalink / raw)
To: Peter Fang, Dave Hansen, Kiryl Shutsemau, Rick Edgecombe,
Kuppuswamy Sathyanarayanan
Cc: Thomas Gleixner, Ingo Molnar, Borislav Petkov, x86,
H. Peter Anvin, linux-kernel, linux-coco, kvm, Xiaoyao Li,
Binbin Wu, Tony Lindgren, Sean Christopherson, Artem Bityutskiy
On 9/28/26 03:08, Peter Fang wrote:
> -#define TDX_QUOTE_MAX_LEN (GET_QUOTE_BUF_SIZE - sizeof(struct tdx_quote_buf))
> +#define TDX_QUOTE_TOTAL_SIZE(n) struct_size_t(struct tdx_quote_buf, data, n)
>
> /* struct tdx_quote_buf: Format of Quote request buffer.
> * @version: Quote format version, filled by TD.
> @@ -314,7 +314,7 @@ static int tdx_report_new_locked(struct tsm_report *report, void *data)
>
> out_len = READ_ONCE(quote_buf->out_len);
>
> - if (out_len > TDX_QUOTE_MAX_LEN)
> + if (TDX_QUOTE_TOTAL_SIZE(out_len) > GET_QUOTE_BUF_SIZE)
> return -EFBIG;
Gah, this is awful. There are two different literal "data" things:
1. The function argument: void *data
2. The flexible array member: tdx_quote_buf->data[]
Worse, I think the function argument isn't even used, despite being
passed through at least one level of static, file-local TDX calls.
It becomes a *total* liability since there are so many "data" names
being tossed around.
I just committed this:
> https://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git/commit/?h=x86/tdx&id=d48b2d347105436365280a3697a265aa4d37e96c
Any reason not to keep it?
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v5 4/6] virt: tdx-guest: Add a helper for the Quote buffer size
2026-09-28 10:08 [PATCH v5 0/6] tdx-guest: Make Quote buffer size dynamic Peter Fang
` (2 preceding siblings ...)
2026-09-28 10:08 ` [PATCH v5 3/6] virt: tdx-guest: Calculate the Quote buffer size safely Peter Fang
@ 2026-09-28 10:08 ` Peter Fang
2026-09-28 16:13 ` Dave Hansen
2026-09-28 18:23 ` Edgecombe, Rick P
2026-09-28 10:08 ` [PATCH v5 5/6] x86/tdx: Add a helper to query maximum Quote size Peter Fang
2026-09-28 10:08 ` [PATCH v5 6/6] virt: tdx-guest: Make the Quote buffer size dynamic Peter Fang
5 siblings, 2 replies; 13+ messages in thread
From: Peter Fang @ 2026-09-28 10:08 UTC (permalink / raw)
To: Dave Hansen, Kiryl Shutsemau, Rick Edgecombe, Kuppuswamy Sathyanarayanan
Cc: Thomas Gleixner, Ingo Molnar, Borislav Petkov, x86,
H. Peter Anvin, linux-kernel, linux-coco, kvm, Xiaoyao Li,
Binbin Wu, Tony Lindgren, Sean Christopherson, Artem Bityutskiy,
Peter Fang
The Quote buffer size is a constant sprinkled across several places.
Read it from a helper instead. And rename the constant to avoid using a
verb.
Cache the answer in the helper, so a later change can make the size
dynamic without new plumbing.
AI was used under supervision to collect/apply feedback, review code and
workshop logs.
Signed-off-by: Peter Fang <peter.fang@intel.com>
---
v5:
- Reworked v4 3/4 to use a helper instead of a global. [Dave, Xiaoyao]
- Use TDX_DEFAULT_QUOTE_SIZE instead of GET_QUOTE_DEFAULT_BUF_SIZE.
[Dave]
- Use "size" instead of "len" for buffer size variables. [Dave]
- Drop the RB tags, as the code changed substantially.
---
drivers/virt/coco/tdx-guest/tdx-guest.c | 37 ++++++++++++++++++-------
1 file changed, 27 insertions(+), 10 deletions(-)
diff --git a/drivers/virt/coco/tdx-guest/tdx-guest.c b/drivers/virt/coco/tdx-guest/tdx-guest.c
index b30439584886..b79b4325da3a 100644
--- a/drivers/virt/coco/tdx-guest/tdx-guest.c
+++ b/drivers/virt/coco/tdx-guest/tdx-guest.c
@@ -162,7 +162,7 @@ static void tdx_mr_deinit(const struct attribute_group *mr_grp)
* DICE-based attestation uses layered evidence that requires
* larger Quote size (~100K).
*/
-#define GET_QUOTE_BUF_SIZE SZ_128K
+#define TDX_DEFAULT_QUOTE_SIZE SZ_128K
#define GET_QUOTE_CMD_VER 1
@@ -209,26 +209,42 @@ static long tdx_get_report0(struct tdx_report_req __user *req)
USER_SOCKPTR(req->tdreport));
}
+static size_t get_quote_buf_size(void)
+{
+ static size_t quote_buf_size;
+
+ if (quote_buf_size)
+ return quote_buf_size;
+
+ quote_buf_size = PAGE_ALIGN(TDX_DEFAULT_QUOTE_SIZE);
+
+ return quote_buf_size;
+}
+
static void free_quote_buf(struct tdx_quote_buf *buf)
{
- size_t len = PAGE_ALIGN(GET_QUOTE_BUF_SIZE);
- unsigned int count = len >> PAGE_SHIFT;
+ size_t buf_size = get_quote_buf_size();
+ unsigned int count;
+
+ count = buf_size >> PAGE_SHIFT;
if (set_memory_encrypted((unsigned long)buf, count)) {
pr_err("Failed to restore encryption mask for Quote buffer, leak it\n");
return;
}
- free_pages_exact(buf, len);
+ free_pages_exact(buf, buf_size);
}
static struct tdx_quote_buf *alloc_quote_buf(void)
{
- size_t len = PAGE_ALIGN(GET_QUOTE_BUF_SIZE);
- unsigned int count = len >> PAGE_SHIFT;
+ size_t buf_size = get_quote_buf_size();
struct tdx_quote_buf *buf;
+ unsigned int count;
- buf = alloc_pages_exact(len, GFP_KERNEL | __GFP_ZERO);
+ count = buf_size >> PAGE_SHIFT;
+
+ buf = alloc_pages_exact(buf_size, GFP_KERNEL | __GFP_ZERO);
if (!buf)
return NULL;
@@ -269,6 +285,7 @@ static int tdx_report_new_locked(struct tsm_report *report, void *data)
{
u8 *buf;
struct tsm_report_desc *desc = &report->desc;
+ size_t quote_buf_size = get_quote_buf_size();
u32 out_len;
int ret;
u64 err;
@@ -284,7 +301,7 @@ static int tdx_report_new_locked(struct tsm_report *report, void *data)
if (desc->inblob_len != TDX_REPORTDATA_LEN)
return -EINVAL;
- memset(quote_buf, 0, GET_QUOTE_BUF_SIZE);
+ memset(quote_buf, 0, quote_buf_size);
/* Update Quote buffer header */
quote_buf->version = GET_QUOTE_CMD_VER;
@@ -295,7 +312,7 @@ static int tdx_report_new_locked(struct tsm_report *report, void *data)
if (ret)
return ret;
- err = tdx_hcall_get_quote(quote_buf, GET_QUOTE_BUF_SIZE);
+ err = tdx_hcall_get_quote(quote_buf, quote_buf_size);
if (err) {
pr_err("GetQuote hypercall failed, status:%llx\n", err);
return -EIO;
@@ -314,7 +331,7 @@ static int tdx_report_new_locked(struct tsm_report *report, void *data)
out_len = READ_ONCE(quote_buf->out_len);
- if (TDX_QUOTE_TOTAL_SIZE(out_len) > GET_QUOTE_BUF_SIZE)
+ if (TDX_QUOTE_TOTAL_SIZE(out_len) > quote_buf_size)
return -EFBIG;
buf = kvmemdup(quote_buf->data, out_len, GFP_KERNEL);
--
2.53.0
^ permalink raw reply [flat|nested] 13+ messages in thread* Re: [PATCH v5 4/6] virt: tdx-guest: Add a helper for the Quote buffer size
2026-09-28 10:08 ` [PATCH v5 4/6] virt: tdx-guest: Add a helper for the Quote buffer size Peter Fang
@ 2026-09-28 16:13 ` Dave Hansen
2026-09-28 18:23 ` Edgecombe, Rick P
1 sibling, 0 replies; 13+ messages in thread
From: Dave Hansen @ 2026-09-28 16:13 UTC (permalink / raw)
To: Peter Fang, Dave Hansen, Kiryl Shutsemau, Rick Edgecombe,
Kuppuswamy Sathyanarayanan
Cc: Thomas Gleixner, Ingo Molnar, Borislav Petkov, x86,
H. Peter Anvin, linux-kernel, linux-coco, kvm, Xiaoyao Li,
Binbin Wu, Tony Lindgren, Sean Christopherson, Artem Bityutskiy
On 9/28/26 03:08, Peter Fang wrote:
> +static size_t get_quote_buf_size(void)
> +{
> + static size_t quote_buf_size;
> +
> + if (quote_buf_size)
> + return quote_buf_size;
> +
> + quote_buf_size = PAGE_ALIGN(TDX_DEFAULT_QUOTE_SIZE);
> +
> + return quote_buf_size;
> +}
<sarcasm>
This is gloriously unencumbered by unwieldy comments!
</sarcasm>
Please explain the goal of this function. Why is it doing what it is
doing? This should also explain why it is page-aligning and caching things.
Which also reminds me, it really isn't calculating the size of the quote
"buf". It's calculating the size of the allocation required to transport
it around, no?
Because, there are three sizes here:
1. The actual data of the quote
2. The size of #1 with the metadata added in
3. The size of #2 with page padding
Which one of those three is "buf_size", eh?
^ permalink raw reply [flat|nested] 13+ messages in thread* Re: [PATCH v5 4/6] virt: tdx-guest: Add a helper for the Quote buffer size
2026-09-28 10:08 ` [PATCH v5 4/6] virt: tdx-guest: Add a helper for the Quote buffer size Peter Fang
2026-09-28 16:13 ` Dave Hansen
@ 2026-09-28 18:23 ` Edgecombe, Rick P
1 sibling, 0 replies; 13+ messages in thread
From: Edgecombe, Rick P @ 2026-09-28 18:23 UTC (permalink / raw)
To: sathyanarayanan.kuppuswamy, kas, Fang, Peter, dave.hansen
Cc: seanjc, bp, x86, binbin.wu, hpa, mingo, linux-kernel, Li,
Xiaoyao, tglx, kvm, linux-coco, Bityutskiy, Artem, tony.lindgren
On Mon, 2026-09-28 at 03:08 -0700, Peter Fang wrote:
> +static size_t get_quote_buf_size(void)
> +{
> + static size_t quote_buf_size;
> +
> + if (quote_buf_size)
> + return quote_buf_size;
> +
> + quote_buf_size = PAGE_ALIGN(TDX_DEFAULT_QUOTE_SIZE);
> +
> + return quote_buf_size;
> +}
> +
This makes no sense, at the point of this patch. It lazily sets a global to a
constant value. Function scoped static is also weird.
I think you are doing it this way so that later you can plug in the dynamic
read. But later it still doesn't make sense why to lazily fetch it. Why not just
read it in the tdx_guest_init() to a global? If the read fails, set to
TDX_DEFAULT_QUOTE_SIZE. Then you are done. All callers of tdx_guest_init() just
refer to the global. Why not?
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v5 5/6] x86/tdx: Add a helper to query maximum Quote size
2026-09-28 10:08 [PATCH v5 0/6] tdx-guest: Make Quote buffer size dynamic Peter Fang
` (3 preceding siblings ...)
2026-09-28 10:08 ` [PATCH v5 4/6] virt: tdx-guest: Add a helper for the Quote buffer size Peter Fang
@ 2026-09-28 10:08 ` Peter Fang
2026-09-28 18:35 ` Edgecombe, Rick P
2026-09-28 18:50 ` Edgecombe, Rick P
2026-09-28 10:08 ` [PATCH v5 6/6] virt: tdx-guest: Make the Quote buffer size dynamic Peter Fang
5 siblings, 2 replies; 13+ messages in thread
From: Peter Fang @ 2026-09-28 10:08 UTC (permalink / raw)
To: Dave Hansen, Kiryl Shutsemau, Rick Edgecombe, Kuppuswamy Sathyanarayanan
Cc: Thomas Gleixner, Ingo Molnar, Borislav Petkov, x86,
H. Peter Anvin, linux-kernel, linux-coco, kvm, Xiaoyao Li,
Binbin Wu, Tony Lindgren, Sean Christopherson, Artem Bityutskiy,
Peter Fang
TDX attestation report ("Quote") sizes can grow with newer crypto
algorithms, so guests can no longer rely on a fixed-size buffer for the
Quote.
The TDX module added a new ABI that reports the largest possible Quote
size via a metadata field [1]. Add a helper to query the size instead of
exposing tdg_vm_rd() directly, as it can read arbitrary metadata fields.
The reported size covers every Quote type the platform can produce,
including SGX-based Quotes.
Thanks to Xu Yilun for suggesting this in an off-list discussion.
AI was used under supervision to collect/apply feedback, review code and
workshop logs.
[1] Intel TDX Module ABI Definitions, August 2026, TD-scope metadata
field "TD_QUOTE_MAX_SIZE"
Signed-off-by: Peter Fang <peter.fang@intel.com>
---
v5:
- Drop unused EXPORT_SYMBOL_GPL(). [Dave]
- Use an error code to report failure. [Dave]
- Drop the u32 cast. [Dave]
- Replace the kernel-doc comment with a one-liner. [Dave]
- Drop the RB tags, as the code changed substantially.
v4:
- Update the TDCS_QUOTE_MAX_SIZE encoding to 0x9010000200000007. [1]
- Provide documentation for the metadata field. [Rick, Kiryl]
- Document that the reported size covers every Quote type. [Xiaoyao]
- Document that a module update does not change the reported size.
[Tony]
- Add Tony's Reviewed-by.
v3:
- No code changes. Add Binbin's Reviewed-by.
v2:
- Keep the explicit (u32) cast to document the metadata field width.
[Binbin]
- Note that Xu Yilun's suggestion was made in an off-list discussion.
[Sathya]
- Drop the Assisted-by tags, as the code was not written by AI.
---
arch/x86/coco/tdx/tdx.c | 16 ++++++++++++++++
arch/x86/include/asm/shared/tdx.h | 1 +
arch/x86/include/asm/tdx.h | 2 ++
3 files changed, 19 insertions(+)
diff --git a/arch/x86/coco/tdx/tdx.c b/arch/x86/coco/tdx/tdx.c
index bcaf4180a8db..323e1efc78ea 100644
--- a/arch/x86/coco/tdx/tdx.c
+++ b/arch/x86/coco/tdx/tdx.c
@@ -198,6 +198,22 @@ u64 tdx_hcall_get_quote(void *buf, size_t size)
}
EXPORT_SYMBOL_GPL(tdx_hcall_get_quote);
+/*
+ * Ask the TDX module what the largest possible Quote might be.
+ */
+int tdx_get_max_quote_size(u64 *max_quote_size)
+{
+ u64 err;
+
+ err = tdg_vm_rd(TDCS_QUOTE_MAX_SIZE, max_quote_size);
+
+ /* Old modules do not support this. Tell the caller. */
+ if (err)
+ return -EINVAL;
+
+ return 0;
+}
+
static void __noreturn tdx_panic(const char *msg)
{
struct tdx_module_args args = {
diff --git a/arch/x86/include/asm/shared/tdx.h b/arch/x86/include/asm/shared/tdx.h
index f20e91d7ac35..6f106d4b1a58 100644
--- a/arch/x86/include/asm/shared/tdx.h
+++ b/arch/x86/include/asm/shared/tdx.h
@@ -50,6 +50,7 @@
/* TDX TD-Scope Metadata. To be used by TDG.VM.WR and TDG.VM.RD */
#define TDCS_CONFIG_FLAGS 0x1110000300000016
#define TDCS_TD_CTLS 0x1110000300000017
+#define TDCS_QUOTE_MAX_SIZE 0x9010000200000007
#define TDCS_NOTIFY_ENABLES 0x9100000000000010
#define TDCS_TOPOLOGY_ENUM_CONFIGURED 0x9100000000000019
diff --git a/arch/x86/include/asm/tdx.h b/arch/x86/include/asm/tdx.h
index a3c37d61e676..6a465827d8f9 100644
--- a/arch/x86/include/asm/tdx.h
+++ b/arch/x86/include/asm/tdx.h
@@ -83,6 +83,8 @@ int tdx_mcall_extend_rtmr(u8 index, u8 *data);
u64 tdx_hcall_get_quote(void *buf, size_t size);
+int tdx_get_max_quote_size(u64 *max_quote_size);
+
void __init tdx_dump_attributes(u64 td_attr);
void __init tdx_dump_td_ctls(u64 td_ctls);
--
2.53.0
^ permalink raw reply [flat|nested] 13+ messages in thread* Re: [PATCH v5 5/6] x86/tdx: Add a helper to query maximum Quote size
2026-09-28 10:08 ` [PATCH v5 5/6] x86/tdx: Add a helper to query maximum Quote size Peter Fang
@ 2026-09-28 18:35 ` Edgecombe, Rick P
2026-09-28 18:50 ` Edgecombe, Rick P
1 sibling, 0 replies; 13+ messages in thread
From: Edgecombe, Rick P @ 2026-09-28 18:35 UTC (permalink / raw)
To: sathyanarayanan.kuppuswamy, kas, Fang, Peter, dave.hansen
Cc: seanjc, bp, x86, binbin.wu, hpa, mingo, linux-kernel, Li,
Xiaoyao, tglx, kvm, linux-coco, Bityutskiy, Artem, tony.lindgren
On Mon, 2026-09-28 at 03:08 -0700, Peter Fang wrote:
> TDX attestation report ("Quote") sizes can grow with newer crypto
> algorithms, so guests can no longer rely on a fixed-size buffer for the
> Quote.
>
> The TDX module added a new ABI that reports the largest possible Quote
> size via a metadata field [1]. Add a helper to query the size instead of
> exposing tdg_vm_rd() directly, as it can read arbitrary metadata fields.
>
> The reported size covers every Quote type the platform can produce,
> including SGX-based Quotes.
>
> Thanks to Xu Yilun for suggesting this in an off-list discussion.
Suggesting what?
>
> AI was used under supervision to collect/apply feedback, review code and
> workshop logs.
>
> [1] Intel TDX Module ABI Definitions, August 2026, TD-scope metadata
> field "TD_QUOTE_MAX_SIZE"
>
> Signed-off-by: Peter Fang <peter.fang@intel.com>
> ---
> v5:
> - Drop unused EXPORT_SYMBOL_GPL(). [Dave]
> - Use an error code to report failure. [Dave]
> - Drop the u32 cast. [Dave]
> - Replace the kernel-doc comment with a one-liner. [Dave]
> - Drop the RB tags, as the code changed substantially.
> v4:
> - Update the TDCS_QUOTE_MAX_SIZE encoding to 0x9010000200000007. [1]
> - Provide documentation for the metadata field. [Rick, Kiryl]
> - Document that the reported size covers every Quote type. [Xiaoyao]
> - Document that a module update does not change the reported size.
> [Tony]
> - Add Tony's Reviewed-by.
> v3:
> - No code changes. Add Binbin's Reviewed-by.
> v2:
> - Keep the explicit (u32) cast to document the metadata field width.
> [Binbin]
> - Note that Xu Yilun's suggestion was made in an off-list discussion.
> [Sathya]
> - Drop the Assisted-by tags, as the code was not written by AI.
> ---
> arch/x86/coco/tdx/tdx.c | 16 ++++++++++++++++
> arch/x86/include/asm/shared/tdx.h | 1 +
> arch/x86/include/asm/tdx.h | 2 ++
> 3 files changed, 19 insertions(+)
>
> diff --git a/arch/x86/coco/tdx/tdx.c b/arch/x86/coco/tdx/tdx.c
> index bcaf4180a8db..323e1efc78ea 100644
> --- a/arch/x86/coco/tdx/tdx.c
> +++ b/arch/x86/coco/tdx/tdx.c
> @@ -198,6 +198,22 @@ u64 tdx_hcall_get_quote(void *buf, size_t size)
> }
> EXPORT_SYMBOL_GPL(tdx_hcall_get_quote);
>
> +/*
> + * Ask the TDX module what the largest possible Quote might be.
How about adding the "largest on the host platform" detail to this comment.
> + */
> +int tdx_get_max_quote_size(u64 *max_quote_size)
> +{
> + u64 err;
> +
> + err = tdg_vm_rd(TDCS_QUOTE_MAX_SIZE, max_quote_size);
> +
> + /* Old modules do not support this. Tell the caller. */
> + if (err)
> + return -EINVAL;
> +
> + return 0;
> +}
> +
> static void __noreturn tdx_panic(const char *msg)
> {
> struct tdx_module_args args = {
> diff --git a/arch/x86/include/asm/shared/tdx.h b/arch/x86/include/asm/shared/tdx.h
> index f20e91d7ac35..6f106d4b1a58 100644
> --- a/arch/x86/include/asm/shared/tdx.h
> +++ b/arch/x86/include/asm/shared/tdx.h
> @@ -50,6 +50,7 @@
> /* TDX TD-Scope Metadata. To be used by TDG.VM.WR and TDG.VM.RD */
> #define TDCS_CONFIG_FLAGS 0x1110000300000016
> #define TDCS_TD_CTLS 0x1110000300000017
> +#define TDCS_QUOTE_MAX_SIZE 0x9010000200000007
> #define TDCS_NOTIFY_ENABLES 0x9100000000000010
> #define TDCS_TOPOLOGY_ENUM_CONFIGURED 0x9100000000000019
>
> diff --git a/arch/x86/include/asm/tdx.h b/arch/x86/include/asm/tdx.h
> index a3c37d61e676..6a465827d8f9 100644
> --- a/arch/x86/include/asm/tdx.h
> +++ b/arch/x86/include/asm/tdx.h
> @@ -83,6 +83,8 @@ int tdx_mcall_extend_rtmr(u8 index, u8 *data);
>
> u64 tdx_hcall_get_quote(void *buf, size_t size);
>
> +int tdx_get_max_quote_size(u64 *max_quote_size);
> +
> void __init tdx_dump_attributes(u64 td_attr);
> void __init tdx_dump_td_ctls(u64 td_ctls);
>
^ permalink raw reply [flat|nested] 13+ messages in thread* Re: [PATCH v5 5/6] x86/tdx: Add a helper to query maximum Quote size
2026-09-28 10:08 ` [PATCH v5 5/6] x86/tdx: Add a helper to query maximum Quote size Peter Fang
2026-09-28 18:35 ` Edgecombe, Rick P
@ 2026-09-28 18:50 ` Edgecombe, Rick P
1 sibling, 0 replies; 13+ messages in thread
From: Edgecombe, Rick P @ 2026-09-28 18:50 UTC (permalink / raw)
To: sathyanarayanan.kuppuswamy, kas, Fang, Peter, dave.hansen
Cc: seanjc, bp, x86, binbin.wu, hpa, mingo, linux-kernel, Li,
Xiaoyao, tglx, kvm, linux-coco, Bityutskiy, Artem, tony.lindgren
On Mon, 2026-09-28 at 03:08 -0700, Peter Fang wrote:
> [1] Intel TDX Module ABI Definitions, August 2026, TD-scope metadata
> field "TD_QUOTE_MAX_SIZE"
The latest seems to be June 2026:
https://www.intel.com/content/www/us/en/developer/tools/trust-domain-extensions/documentation.html
So where is this? Does it say anything about being page aligned already?
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v5 6/6] virt: tdx-guest: Make the Quote buffer size dynamic
2026-09-28 10:08 [PATCH v5 0/6] tdx-guest: Make Quote buffer size dynamic Peter Fang
` (4 preceding siblings ...)
2026-09-28 10:08 ` [PATCH v5 5/6] x86/tdx: Add a helper to query maximum Quote size Peter Fang
@ 2026-09-28 10:08 ` Peter Fang
5 siblings, 0 replies; 13+ messages in thread
From: Peter Fang @ 2026-09-28 10:08 UTC (permalink / raw)
To: Dave Hansen, Kiryl Shutsemau, Rick Edgecombe, Kuppuswamy Sathyanarayanan
Cc: Thomas Gleixner, Ingo Molnar, Borislav Petkov, x86,
H. Peter Anvin, linux-kernel, linux-coco, kvm, Xiaoyao Li,
Binbin Wu, Tony Lindgren, Sean Christopherson, Artem Bityutskiy,
Peter Fang
Support a new TDX module ABI that reports the Quote size limit in a
metadata field. The fixed 128KB buffer in the driver may be too small
for Quotes that use new algorithms like post-quantum cryptography (PQC),
which can produce much larger certificates. With this ABI, the guest
sizes the buffer to the platform's needs and no longer has to rely on
some empirical number.
The shared buffer comes from the buddy allocator, as the host expects it
to be physically contiguous. The allocator's page order limit should be
sufficient for current attestation needs. Platforms that don't report
the limit fall back to the default 128KB buffer.
AI was used under supervision to collect/apply feedback, review code and
workshop logs.
Based on a patch originally by Kuppuswamy Sathyanarayanan.
Signed-off-by: Peter Fang <peter.fang@intel.com>
---
v5:
- Do the export here, and use EXPORT_SYMBOL_FOR_MODULES() instead.
[Xiaoyao, Dave]
- Drop the comment about the buddy allocator. [Dave]
- Drop the RB tags, as the code changed substantially.
v4:
- Move the PAGE_ALIGN() out of get_quote_buf_size(). [Xiaoyao]
- Improve the get_quote_buf_size() pattern again.
- Document that the reported size covers every Quote type. [Xiaoyao]
- Document that a module update does not change the reported size.
[Tony]
- Add Tony's Reviewed-by.
v3:
- Split out from the v2 "Allocate Quote buffer dynamically" patch. Add
the dynamic buffer feature on top of the refactoring. [Dave]
- Improve the get_quote_buf_size() pattern for better readability.
[Dave]
- Drop __GFP_NOWARN so an allocation failure warns. [Dave, Rick, Kiryl]
- Drop the Reviewed-by tags from v2 (Kiryl, Binbin) as the patch was
reworked.
---
arch/x86/coco/tdx/tdx.c | 1 +
drivers/virt/coco/tdx-guest/tdx-guest.c | 13 ++++++++++++-
2 files changed, 13 insertions(+), 1 deletion(-)
diff --git a/arch/x86/coco/tdx/tdx.c b/arch/x86/coco/tdx/tdx.c
index 323e1efc78ea..847430fc639f 100644
--- a/arch/x86/coco/tdx/tdx.c
+++ b/arch/x86/coco/tdx/tdx.c
@@ -213,6 +213,7 @@ int tdx_get_max_quote_size(u64 *max_quote_size)
return 0;
}
+EXPORT_SYMBOL_FOR_MODULES(tdx_get_max_quote_size, "tdx-guest");
static void __noreturn tdx_panic(const char *msg)
{
diff --git a/drivers/virt/coco/tdx-guest/tdx-guest.c b/drivers/virt/coco/tdx-guest/tdx-guest.c
index b79b4325da3a..ad2cb4740898 100644
--- a/drivers/virt/coco/tdx-guest/tdx-guest.c
+++ b/drivers/virt/coco/tdx-guest/tdx-guest.c
@@ -212,11 +212,22 @@ static long tdx_get_report0(struct tdx_report_req __user *req)
static size_t get_quote_buf_size(void)
{
static size_t quote_buf_size;
+ u64 max_quote_size;
if (quote_buf_size)
return quote_buf_size;
- quote_buf_size = PAGE_ALIGN(TDX_DEFAULT_QUOTE_SIZE);
+ /* Start with the default buffer size */
+ quote_buf_size = TDX_DEFAULT_QUOTE_SIZE;
+
+ /*
+ * Override the default when the TDX module reports a size. Add room
+ * for the header metadata.
+ */
+ if (!tdx_get_max_quote_size(&max_quote_size))
+ quote_buf_size = TDX_QUOTE_TOTAL_SIZE(max_quote_size);
+
+ quote_buf_size = PAGE_ALIGN(quote_buf_size);
return quote_buf_size;
}
--
2.53.0
^ permalink raw reply [flat|nested] 13+ messages in thread