Re: [RFC PATCH 09/15] x86/virt/tdx: Add interface to generate a Quote
From: Peter Fang
Date: Mon Jul 06 2026 - 23:46:02 EST
On Wed, Jul 01, 2026 at 02:46:16PM +0300, Nikolay Borisov wrote:
>
>
> > @@ -1228,6 +1230,86 @@ bool tdx_quote_enabled(void)
> > }
> > EXPORT_SYMBOL_FOR_KVM(tdx_quote_enabled);
> > +#define QUOTE_ID_MASK GENMASK_U64(47, 32)
> > +
> > +static u64 tdx_quote_get(struct tdx_td *td, u64 in_data_pa, u64 in_data_len,
> > + u64 hpa_list_pa, u64 total_len, u64 *quote_len)
> > +{
> > + struct tdx_module_args args = {
> > + .rcx = tdx_tdr_pa(td),
> > + /* Don't bother specifying the quote id */
> > + .rdx = QUOTE_ID_MASK & (u64)-1,
>
> This is simply equal to QUOTE_ID_MASK, so why not create a special value
> meaning "ANY QUOTE" i.e
>
> #define QUOTE_ID_MASK ....
> #define ANY_QUOTE QUOTE_ID_MASK
>
> or some such .
I replaced it with just GENMASK_U64(47, 32) in the v2 series and added a
comment explaining it. QUOTE_ID_MASK isn't really needed since we don't
use any other Quote ID for this SEAMCALL. Hope this is clearer:
struct tdx_module_args args = {
.rcx = tdx_tdr_pa(td),
/* [47:32] QUOTE_ID: All-1s selects the default quote format */
.rdx = GENMASK_U64(47, 32),
.r8 = in_data_pa,
.r9 = in_data_len,
.r10 = hpa_entries_pa,
.r11 = total_len,
};
>
> > + .r8 = in_data_pa,
> > + .r9 = in_data_len,
> > + .r10 = hpa_list_pa,
> > + .r11 = total_len,
> > + };
> > + u64 r;
> > +
> > + do {
> > + r = seamcall_ret(TDH_QUOTE_GET, &args);
> > + } while (r == TDX_INTERRUPTED_RESUMABLE);
>
>
> nit: This pattern seems to repeat a lot, might be worth it to consider
> introducing a wrapper similar to existing sc_retry?
I think Yilun gave some reasoning behind this in a separate reply:
https://lore.kernel.org/linux-coco/akaKmEZnTY4FO2gY@yilunxu-OptiPlex-7050/
> > +void *tdx_quote_generate(struct tdx_td *td, void *in_data, u32 in_data_len,
> > + u32 *quote_len)
> > +{
> > + void *quote_dup = NULL;
> > + u64 r, out_len;
> > +
> > + if (!tdx_quote_enabled())
> > + return NULL;
> > +
> > + /* TDH.QUOTE.GET expects the input data to fit in a page */
> > + if (in_data_len > PAGE_SIZE)
> > + return NULL;
> > +
> > + mutex_lock(&tdx_quote_lock);
> > +
> > + /*
> > + * Use the first page of the quote buffer for input data. The buffer
> > + * must be at least one page in size. @in_data may not be page-aligned,
> > + * but TDH.QUOTE.GET expects page-aligned addresses.
> > + */
> > + memcpy(quote_data.buf, in_data, (size_t)in_data_len);
>
> Perhaps you can use min(PAGE_SIZE, in_data_len) and that way you can
> eliminate the in_data_len check above and copy up-to PAGE_SIZE data, if the
> data is longer - you will copy PAGE_SIZE which will likely result in error
> on generating the quote?
Oh that's an interesting idea. I'm going to change the implementation in
the upcoming v3 series and I'll see if using min() works. Thanks for the
suggestion.
>