>+static int init_pamt_metadata(void) >+{ >+ size_t size = max_pfn / PTRS_PER_PTE * sizeof(*pamt_refcounts); >+ struct vm_struct *area; >+ >+ if (!tdx_supports_dynamic_pamt(&tdx_sysinfo)) >+ return 0; >+ >+ /* >+ * Reserve vmalloc range for PAMT reference counters. It covers all >+ * physical address space up to max_pfn. It is going to be populated >+ * from init_tdmr() only for present memory that available for TDX use. >+ */ >+ area = get_vm_area(size, VM_IOREMAP); >+ if (!area) >+ return -ENOMEM; >+ >+ pamt_refcounts = area->addr; >+ return 0; >+} >+ >+static void free_pamt_metadata(void) >+{ >+ size_t size = max_pfn / PTRS_PER_PTE * sizeof(*pamt_refcounts); >+ Shouldn't the free path also be gated by tdx_supports_dynamic_pamt()? There is a possibility that pamt_refcounts could be NULL here, e.g., the TDX module doesn't support dynamic PAMT and init_tdmrs() encountered an error. I am assuming that apply_to_existing_page_range() below will cause issues if pamt_refcounts is NULL, e.g., unmap mappings set up by others. >+ size = round_up(size, PAGE_SIZE); >+ apply_to_existing_page_range(&init_mm, >+ (unsigned long)pamt_refcounts, >+ size, pamt_refcount_depopulate, >+ NULL); >+ vfree(pamt_refcounts); >+ pamt_refcounts = NULL; >+} >+ > static int init_tdmr(struct tdmr_info *tdmr) > { > u64 next; >+ int ret; >+ >+ ret = alloc_tdmr_pamt_refcount(tdmr); >+ if (ret) >+ return ret; > > /* > * Initializing a TDMR can be time consuming. To avoid long >@@ -1048,7 +1150,6 @@ static int init_tdmr(struct tdmr_info *tdmr) > struct tdx_module_args args = { > .rcx = tdmr->base, > }; >- int ret; > > ret = seamcall_prerr_ret(TDH_SYS_TDMR_INIT, &args); > if (ret) >@@ -1134,10 +1235,15 @@ static int init_tdx_module(void) > if (ret) > goto err_reset_pamts; > >+ /* Reserve vmalloc range for PAMT reference counters */ >+ ret = init_pamt_metadata(); >+ if (ret) >+ goto err_reset_pamts; >+ > /* Initialize TDMRs to complete the TDX module initialization */ > ret = init_tdmrs(&tdx_tdmr_list); > if (ret) >- goto err_reset_pamts; >+ goto err_free_pamt_metadata; > > pr_info("%lu KB allocated for PAMT\n", tdmrs_count_pamt_kb(&tdx_tdmr_list)); > >@@ -1149,6 +1255,9 @@ static int init_tdx_module(void) > put_online_mems(); > return ret; > >+err_free_pamt_metadata: >+ free_pamt_metadata(); >+ > err_reset_pamts: > /* > * Part of PAMTs may already have been initialized by the >-- >2.47.2 >