]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
memblock: extract page freeing from free_reserved_area() into a helper
authorMike Rapoport (Microsoft) <rppt@kernel.org>
Mon, 23 Mar 2026 07:48:33 +0000 (09:48 +0200)
committerMike Rapoport (Microsoft) <rppt@kernel.org>
Wed, 1 Apr 2026 08:20:15 +0000 (11:20 +0300)
There are two functions that release pages to the buddy allocator late in
the boot: free_reserved_area() and memblock_free_late().

Currently they are using different underlying functionality,
free_reserved_area() runs each page being freed via free_reserved_page()
and memblock_free_late() uses memblock_free_pages() -> __free_pages_core(),
but in the end they both boil down to a loop that frees a range page by
page.

Extract the loop frees pages from free_reserved_area() into a helper and
use that helper in memblock_free_late().

Link: https://patch.msgid.link/20260323074836.3653702-7-rppt@kernel.org
Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
mm/memblock.c

index a42ec6a76ea0ebe9f5abb6371485f7bc7e5ebbdb..68a72bd4c8bd61a35b8f76c334b5685eb44ece63 100644 (file)
@@ -894,26 +894,12 @@ int __init_memblock memblock_remove(phys_addr_t base, phys_addr_t size)
        return memblock_remove_range(&memblock.memory, base, size);
 }
 
-unsigned long free_reserved_area(void *start, void *end, int poison, const char *s)
+static unsigned long __free_reserved_area(phys_addr_t start, phys_addr_t end,
+                                         int poison)
 {
-       phys_addr_t start_pa, end_pa;
        unsigned long pages = 0, pfn;
 
-       /*
-        * end is the first address past the region and it may be beyond what
-        * __pa() or __pa_symbol() can handle.
-        * Use the address included in the range for the conversion and add
-        * back 1 afterwards.
-        */
-       if (__is_kernel((unsigned long)start)) {
-               start_pa = __pa_symbol(start);
-               end_pa = __pa_symbol(end - 1) + 1;
-       } else {
-               start_pa = __pa(start);
-               end_pa = __pa(end - 1) + 1;
-       }
-
-       for_each_valid_pfn(pfn, PFN_UP(start_pa), PFN_DOWN(end_pa)) {
+       for_each_valid_pfn(pfn, PFN_UP(start), PFN_DOWN(end)) {
                struct page *page = pfn_to_page(pfn);
                void *direct_map_addr;
 
@@ -935,7 +921,29 @@ unsigned long free_reserved_area(void *start, void *end, int poison, const char
                free_reserved_page(page);
                pages++;
        }
+       return pages;
+}
+
+unsigned long free_reserved_area(void *start, void *end, int poison, const char *s)
+{
+       phys_addr_t start_pa, end_pa;
+       unsigned long pages;
+
+       /*
+        * end is the first address past the region and it may be beyond what
+        * __pa() or __pa_symbol() can handle.
+        * Use the address included in the range for the conversion and add back
+        * 1 afterwards.
+        */
+       if (__is_kernel((unsigned long)start)) {
+               start_pa = __pa_symbol(start);
+               end_pa = __pa_symbol(end - 1) + 1;
+       } else {
+               start_pa = __pa(start);
+               end_pa = __pa(end - 1) + 1;
+       }
 
+       pages = __free_reserved_area(start_pa, end_pa, poison);
        if (pages && s)
                pr_info("Freeing %s memory: %ldK\n", s, K(pages));
 
@@ -1811,20 +1819,15 @@ void *__init __memblock_alloc_or_panic(phys_addr_t size, phys_addr_t align,
  */
 void __init memblock_free_late(phys_addr_t base, phys_addr_t size)
 {
-       phys_addr_t cursor, end;
+       phys_addr_t end = base + size - 1;
 
-       end = base + size - 1;
        memblock_dbg("%s: [%pa-%pa] %pS\n",
                     __func__, &base, &end, (void *)_RET_IP_);
-       kmemleak_free_part_phys(base, size);
-       cursor = PFN_UP(base);
-       end = PFN_DOWN(base + size);
 
-       for (; cursor < end; cursor++) {
-               memblock_free_pages(cursor, 0);
-               totalram_pages_inc();
-       }
+       kmemleak_free_part_phys(base, size);
+       __free_reserved_area(base, base + size, -1);
 }
+
 /*
  * Remaining API functions
  */