Re: [PATCH v4 02/17] x86/virt/tdx: Add a SEAMCALL wrapper to demote a 2MB huge page

From: Edgecombe, Rick P

Date: Thu Oct 22 2026 - 11:54:33 EST


On Thu, 2026-10-22 at 16:46 +0800, Yan Zhao wrote:
> u64 tdh_mem_page_demote_2mb(struct tdx_td *td, u64 gpa, kvm_pfn_t pfn, struct
> page *new_sept_pt,
>                             struct tdx_pamt_cache *pamt_cache, u64 *ext_err1,
> u64 *ext_err2)
> {
>         struct tdx_module_args args = {
>                 .rcx = gpa | pg_level_to_tdx_sept_level(PG_LEVEL_2M),
>                 .rdx = tdx_tdr_pa(td),
>                 .r8 = page_to_phys(new_sept_pt),
>         };
>         struct page *dpamt_pages[TDX_DPAMT_ENTRY_PAGE_CNT];
>         atomic_t *dpamt_refcount;
>         u64 ret;
>
>         /*
>          * For implementation simplicity, only support demotion when
>          * DPAMT is enabled.
>          */
>         WARN_ON_ONCE(!tdx_supports_dynamic_pamt(&tdx_sysinfo));
>
>         /* A NULL pamt_cache is unexpected, so failure indicates a software
> error */

On the edge of unnecessary to me, but ok.

>         ret = alloc_pamt_array(dpamt_pages, pamt_cache);
>         if (ret) {
>                 *ext_err1 = 0;
>                 *ext_err2 = 0;
>                 return TDX_SW_ERROR;
>         }
>
>         dpamt_refcount = tdx_find_dpamt_refcount(pfn);
>
>         args.r12 = page_to_phys(dpamt_pages[0]);
>         args.r13 = page_to_phys(dpamt_pages[1]);
>
>         /*
>          * The dpamt_lock is used to avoid contention between the
>          * TDH_MEM_PAGE_DEMOTE and TDH_PHYMEM_PAMT_{ADD/REMOVE} SEAMCALLs.
>          */
>         spin_lock(&dpamt_lock);
>
>         ret = seamcall_saved_ret(TDH_MEM_PAGE_DEMOTE, &args);
>         *ext_err1 = args.rcx;
>         *ext_err2 = args.rdx;
>
>         if (WARN_ON_ONCE(ret != TDX_SUCCESS))
>                 goto out_free;
>
>         atomic_set(dpamt_refcount, PTRS_PER_PMD);
>         spin_unlock(&dpamt_lock);
>
>         return TDX_SUCCESS;
>
> out_free:
>         spin_unlock(&dpamt_lock);
>         free_pamt_array(pamt_cache, dpamt_pages);
>
>         return ret;
> }

LGTM