return memblock_alloc(size, size);
 }
 
-static void vmem_free_pages(unsigned long addr, int order)
+static void vmem_free_pages(unsigned long addr, int order, struct vmem_altmap *altmap)
 {
+       if (altmap) {
+               vmem_altmap_free(altmap, 1 << order);
+               return;
+       }
        /* We don't expect boot memory to be removed ever. */
        if (!slab_is_available() ||
            WARN_ON_ONCE(PageReserved(virt_to_page((void *)addr))))
 
 /* __ref: we'll only call vmemmap_alloc_block() via vmemmap_populate() */
 static int __ref modify_pte_table(pmd_t *pmd, unsigned long addr,
-                                 unsigned long end, bool add, bool direct)
+                                 unsigned long end, bool add, bool direct,
+                                 struct vmem_altmap *altmap)
 {
        unsigned long prot, pages = 0;
        int ret = -ENOMEM;
                        if (pte_none(*pte))
                                continue;
                        if (!direct)
-                               vmem_free_pages((unsigned long) pfn_to_virt(pte_pfn(*pte)), 0);
+                               vmem_free_pages((unsigned long)pfn_to_virt(pte_pfn(*pte)), get_order(PAGE_SIZE), altmap);
                        pte_clear(&init_mm, addr, pte);
                } else if (pte_none(*pte)) {
                        if (!direct) {
-                               void *new_page = vmemmap_alloc_block(PAGE_SIZE, NUMA_NO_NODE);
+                               void *new_page = vmemmap_alloc_block_buf(PAGE_SIZE, NUMA_NO_NODE, altmap);
 
                                if (!new_page)
                                        goto out;
 
 /* __ref: we'll only call vmemmap_alloc_block() via vmemmap_populate() */
 static int __ref modify_pmd_table(pud_t *pud, unsigned long addr,
-                                 unsigned long end, bool add, bool direct)
+                                 unsigned long end, bool add, bool direct,
+                                 struct vmem_altmap *altmap)
 {
        unsigned long next, prot, pages = 0;
        int ret = -ENOMEM;
                                if (IS_ALIGNED(addr, PMD_SIZE) &&
                                    IS_ALIGNED(next, PMD_SIZE)) {
                                        if (!direct)
-                                               vmem_free_pages(pmd_deref(*pmd), get_order(PMD_SIZE));
+                                               vmem_free_pages(pmd_deref(*pmd), get_order(PMD_SIZE), altmap);
                                        pmd_clear(pmd);
                                        pages++;
                                } else if (!direct && vmemmap_unuse_sub_pmd(addr, next)) {
-                                       vmem_free_pages(pmd_deref(*pmd), get_order(PMD_SIZE));
+                                       vmem_free_pages(pmd_deref(*pmd), get_order(PMD_SIZE), altmap);
                                        pmd_clear(pmd);
                                }
                                continue;
                                 * page tables since vmemmap_populate gets
                                 * called for each section separately.
                                 */
-                               new_page = vmemmap_alloc_block(PMD_SIZE, NUMA_NO_NODE);
+                               new_page = vmemmap_alloc_block_buf(PMD_SIZE, NUMA_NO_NODE, altmap);
                                if (new_page) {
                                        set_pmd(pmd, __pmd(__pa(new_page) | prot));
                                        if (!IS_ALIGNED(addr, PMD_SIZE) ||
                                vmemmap_use_sub_pmd(addr, next);
                        continue;
                }
-               ret = modify_pte_table(pmd, addr, next, add, direct);
+               ret = modify_pte_table(pmd, addr, next, add, direct, altmap);
                if (ret)
                        goto out;
                if (!add)
        for (i = 0; i < PTRS_PER_PMD; i++, pmd++)
                if (!pmd_none(*pmd))
                        return;
-       vmem_free_pages(pud_deref(*pud), CRST_ALLOC_ORDER);
+       vmem_free_pages(pud_deref(*pud), CRST_ALLOC_ORDER, NULL);
        pud_clear(pud);
 }
 
 static int modify_pud_table(p4d_t *p4d, unsigned long addr, unsigned long end,
-                           bool add, bool direct)
+                           bool add, bool direct, struct vmem_altmap *altmap)
 {
        unsigned long next, prot, pages = 0;
        int ret = -ENOMEM;
                } else if (pud_large(*pud)) {
                        continue;
                }
-               ret = modify_pmd_table(pud, addr, next, add, direct);
+               ret = modify_pmd_table(pud, addr, next, add, direct, altmap);
                if (ret)
                        goto out;
                if (!add)
                if (!pud_none(*pud))
                        return;
        }
-       vmem_free_pages(p4d_deref(*p4d), CRST_ALLOC_ORDER);
+       vmem_free_pages(p4d_deref(*p4d), CRST_ALLOC_ORDER, NULL);
        p4d_clear(p4d);
 }
 
 static int modify_p4d_table(pgd_t *pgd, unsigned long addr, unsigned long end,
-                           bool add, bool direct)
+                           bool add, bool direct, struct vmem_altmap *altmap)
 {
        unsigned long next;
        int ret = -ENOMEM;
                                goto out;
                        p4d_populate(&init_mm, p4d, pud);
                }
-               ret = modify_pud_table(p4d, addr, next, add, direct);
+               ret = modify_pud_table(p4d, addr, next, add, direct, altmap);
                if (ret)
                        goto out;
                if (!add)
                if (!p4d_none(*p4d))
                        return;
        }
-       vmem_free_pages(pgd_deref(*pgd), CRST_ALLOC_ORDER);
+       vmem_free_pages(pgd_deref(*pgd), CRST_ALLOC_ORDER, NULL);
        pgd_clear(pgd);
 }
 
 static int modify_pagetable(unsigned long start, unsigned long end, bool add,
-                           bool direct)
+                           bool direct, struct vmem_altmap *altmap)
 {
        unsigned long addr, next;
        int ret = -ENOMEM;
                                goto out;
                        pgd_populate(&init_mm, pgd, p4d);
                }
-               ret = modify_p4d_table(pgd, addr, next, add, direct);
+               ret = modify_p4d_table(pgd, addr, next, add, direct, altmap);
                if (ret)
                        goto out;
                if (!add)
        return ret;
 }
 
-static int add_pagetable(unsigned long start, unsigned long end, bool direct)
+static int add_pagetable(unsigned long start, unsigned long end, bool direct,
+                        struct vmem_altmap *altmap)
 {
-       return modify_pagetable(start, end, true, direct);
+       return modify_pagetable(start, end, true, direct, altmap);
 }
 
-static int remove_pagetable(unsigned long start, unsigned long end, bool direct)
+static int remove_pagetable(unsigned long start, unsigned long end, bool direct,
+                           struct vmem_altmap *altmap)
 {
-       return modify_pagetable(start, end, false, direct);
+       return modify_pagetable(start, end, false, direct, altmap);
 }
 
 /*
 static int vmem_add_range(unsigned long start, unsigned long size)
 {
        start = (unsigned long)__va(start);
-       return add_pagetable(start, start + size, true);
+       return add_pagetable(start, start + size, true, NULL);
 }
 
 /*
 static void vmem_remove_range(unsigned long start, unsigned long size)
 {
        start = (unsigned long)__va(start);
-       remove_pagetable(start, start + size, true);
+       remove_pagetable(start, start + size, true, NULL);
 }
 
 /*
 
        mutex_lock(&vmem_mutex);
        /* We don't care about the node, just use NUMA_NO_NODE on allocations */
-       ret = add_pagetable(start, end, false);
+       ret = add_pagetable(start, end, false, altmap);
        if (ret)
-               remove_pagetable(start, end, false);
+               remove_pagetable(start, end, false, altmap);
        mutex_unlock(&vmem_mutex);
        return ret;
 }
                  struct vmem_altmap *altmap)
 {
        mutex_lock(&vmem_mutex);
-       remove_pagetable(start, end, false);
+       remove_pagetable(start, end, false, altmap);
        mutex_unlock(&vmem_mutex);
 }