void __ref vmemmap_free(unsigned long start, unsigned long end, struct vmem_altmap *altmap) { unsigned long page_size = 1 << mmu_psize_defs[mmu_vmemmap_psize].shift; unsigned long page_order = get_order(page_size); unsigned long alt_start = ~0, alt_end = ~0; unsigned long base_pfn; start = _ALIGN_DOWN(start, page_size); if (altmap) { alt_start = altmap->base_pfn; alt_end = altmap->base_pfn + altmap->reserve + altmap->free + altmap->alloc + altmap->align; } pr_debug("vmemmap_free %lx...%lx\n", start, end); for (; start < end; start += page_size) { unsigned long nr_pages, addr; struct page *section_base; struct page *page; /* * the section has already be marked as invalid, so * vmemmap_populated() true means some other sections still * in this page, so skip it. */ if (vmemmap_populated(start, page_size)) continue; addr = vmemmap_list_free(start); if (!addr) continue; page = pfn_to_page(addr >> PAGE_SHIFT); section_base = pfn_to_page(vmemmap_section_start(start)); nr_pages = 1 << page_order; base_pfn = PHYS_PFN(addr); if (base_pfn >= alt_start && base_pfn < alt_end) { vmem_altmap_free(altmap, nr_pages); } else if (PageReserved(page)) { /* allocated from bootmem */ if (page_size < PAGE_SIZE) { /* * this shouldn't happen, but if it is * the case, leave the memory there */ WARN_ON_ONCE(1); } else { while (nr_pages--) free_reserved_page(page++); } } else { free_pages((unsigned long)(__va(addr)), page_order); } vmemmap_remove_mapping(start, page_size); } }
void __ref vmemmap_free(unsigned long start, unsigned long end) { unsigned long page_size = 1 << mmu_psize_defs[mmu_vmemmap_psize].shift; start = _ALIGN_DOWN(start, page_size); pr_debug("vmemmap_free %lx...%lx\n", start, end); for (; start < end; start += page_size) { unsigned long addr; /* * the section has already be marked as invalid, so * vmemmap_populated() true means some other sections still * in this page, so skip it. */ if (vmemmap_populated(start, page_size)) continue; addr = vmemmap_list_free(start); if (addr) { struct page *page = pfn_to_page(addr >> PAGE_SHIFT); if (PageReserved(page)) { /* allocated from bootmem */ if (page_size < PAGE_SIZE) { /* * this shouldn't happen, but if it is * the case, leave the memory there */ WARN_ON_ONCE(1); } else { unsigned int nr_pages = 1 << get_order(page_size); while (nr_pages--) free_reserved_page(page++); } } else free_pages((unsigned long)(__va(addr)), get_order(page_size)); vmemmap_remove_mapping(start, page_size); } } }
int __meminit vmemmap_populate(unsigned long start, unsigned long end, int node, struct vmem_altmap *altmap) { unsigned long page_size = 1 << mmu_psize_defs[mmu_vmemmap_psize].shift; /* Align to the page size of the linear mapping. */ start = _ALIGN_DOWN(start, page_size); pr_debug("vmemmap_populate %lx..%lx, node %d\n", start, end, node); for (; start < end; start += page_size) { void *p = NULL; int rc; if (vmemmap_populated(start, page_size)) continue; /* * Allocate from the altmap first if we have one. This may * fail due to alignment issues when using 16MB hugepages, so * fall back to system memory if the altmap allocation fail. */ if (altmap) p = altmap_alloc_block_buf(page_size, altmap); if (!p) p = vmemmap_alloc_block_buf(page_size, node); if (!p) return -ENOMEM; vmemmap_list_populate(__pa(p), start, node); pr_debug(" * %016lx..%016lx allocated at %p\n", start, start + page_size, p); rc = vmemmap_create_mapping(start, page_size, __pa(p)); if (rc < 0) { pr_warn("%s: Unable to create vmemmap mapping: %d\n", __func__, rc); return -EFAULT; } } return 0; }
int __meminit vmemmap_populate(unsigned long start, unsigned long end, int node) { unsigned long page_size = 1 << mmu_psize_defs[mmu_vmemmap_psize].shift; /* Align to the page size of the linear mapping. */ start = _ALIGN_DOWN(start, page_size); pr_debug("vmemmap_populate %lx..%lx, node %d\n", start, end, node); for (; start < end; start += page_size) { struct vmem_altmap *altmap; void *p; int rc; if (vmemmap_populated(start, page_size)) continue; /* altmap lookups only work at section boundaries */ altmap = to_vmem_altmap(SECTION_ALIGN_DOWN(start)); p = __vmemmap_alloc_block_buf(page_size, node, altmap); if (!p) return -ENOMEM; vmemmap_list_populate(__pa(p), start, node); pr_debug(" * %016lx..%016lx allocated at %p\n", start, start + page_size, p); rc = vmemmap_create_mapping(start, page_size, __pa(p)); if (rc < 0) { pr_warning( "vmemmap_populate: Unable to create vmemmap mapping: %d\n", rc); return -EFAULT; } } return 0; }
int __meminit vmemmap_populate(unsigned long start, unsigned long end, int node) { unsigned long page_size = 1 << mmu_psize_defs[mmu_vmemmap_psize].shift; /* Align to the page size of the linear mapping. */ start = _ALIGN_DOWN(start, page_size); pr_debug("vmemmap_populate %lx..%lx, node %d\n", start, end, node); for (; start < end; start += page_size) { void *p; int rc; if (vmemmap_populated(start, page_size)) continue; p = vmemmap_alloc_block(page_size, node); if (!p) return -ENOMEM; vmemmap_list_populate(__pa(p), start, node); pr_debug(" * %016lx..%016lx allocated at %p\n", start, start + page_size, p); rc = vmemmap_create_mapping(start, page_size, __pa(p)); if (rc < 0) { pr_warning( "vmemmap_populate: Unable to create vmemmap mapping: %d\n", rc); return -EFAULT; } } return 0; }