Re: [PATCH v3 22/24] x86/tdx: Add/Remove DPAMT pages for guest private memory to demote

From: Huang, Kai

Date: Mon Jan 19 2026 - 05:52:52 EST


On Tue, 2026-01-06 at 18:24 +0800, Yan Zhao wrote:
>  u64 tdh_mem_page_demote(struct tdx_td *td, u64 gpa, int level, struct page *new_sept_page,
> + struct tdx_prealloc *prealloc,
>   u64 *ext_err1, u64 *ext_err2)
>  {
> - struct tdx_module_args args = {
> - .rcx = gpa | level,
> - .rdx = tdx_tdr_pa(td),
> - .r8 = page_to_phys(new_sept_page),
> + bool dpamt = tdx_supports_dynamic_pamt(&tdx_sysinfo) && level == TDX_PS_2M;

The spec of TDH.MEM.PAGE.DEMOTE says:

If the TDX Module is configured to use Dynamic PAMT and the large page
level is 1 (2MB), R12 contains the host physical address of a new 
PAMT page (HKID bits must be 0).

It says "... is configured to use Dynamic PAMT ...", but not ".. Dynamic
PAMT is supported ..".

tdx_supports_dynamic_pamt() only reports whether the module "supports"
DPAMT. Although in the DPAMT series the kernel always enables DPAMT when
it is supported, I think it's better to have a comment point out this fact
so we don't need to go to that series to figure out.

> + u64 guest_memory_pamt_page[MAX_TDX_ARG_SIZE(r12)];
> + struct tdx_module_array_args args = {
> + .args.rcx = gpa | level,
> + .args.rdx = tdx_tdr_pa(td),
> + .args.r8 = page_to_phys(new_sept_page),
>   };
>   u64 ret;
>  
>   if (!tdx_supports_demote_nointerrupt(&tdx_sysinfo))
>   return TDX_SW_ERROR;
>  
> + if (dpamt) {
> + u64 *args_array = dpamt_args_array_ptr_r12(&args);
> +
> + if (alloc_pamt_array(guest_memory_pamt_page, prealloc))
> + return TDX_SW_ERROR;
> +
> + /*
> + * Copy PAMT page PAs of the guest memory into the struct per the
> + * TDX ABI
> + */
> + memcpy(args_array, guest_memory_pamt_page,
> +        tdx_dpamt_entry_pages() * sizeof(*args_array));
> + }