Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

arch, mm: make releasing of memory to page allocator more explicit

The point where the memory is released from memblock to the buddy
allocator is hidden inside arch-specific mem_init()s and the call to
memblock_free_all() is needlessly duplicated in every artiste cure and
after introduction of arch_mm_preinit() hook, mem_init() implementation on
many architecture only contains the call to memblock_free_all().

Pull memblock_free_all() call into mm_core_init() and drop mem_init() on
relevant architectures to make it more explicit where the free memory is
released from memblock to the buddy allocator and to reduce code
duplication in architecture specific code.

Link: https://lkml.kernel.org/r/20250313135003.836600-14-rppt@kernel.org
Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
Acked-by: Dave Hansen <dave.hansen@linux.intel.com> [x86]
Acked-by: Geert Uytterhoeven <geert@linux-m68k.org> [m68k]
Tested-by: Mark Brown <broonie@kernel.org>
Cc: Alexander Gordeev <agordeev@linux.ibm.com>
Cc: Andreas Larsson <andreas@gaisler.com>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Ard Biesheuvel <ardb@kernel.org>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Borislav Betkov <bp@alien8.de>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: David S. Miller <davem@davemloft.net>
Cc: Dinh Nguyen <dinguyen@kernel.org>
Cc: Gerald Schaefer <gerald.schaefer@linux.ibm.com>
Cc: Guo Ren (csky) <guoren@kernel.org>
Cc: Heiko Carstens <hca@linux.ibm.com>
Cc: Helge Deller <deller@gmx.de>
Cc: Huacai Chen <chenhuacai@kernel.org>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Jiaxun Yang <jiaxun.yang@flygoat.com>
Cc: Johannes Berg <johannes@sipsolutions.net>
Cc: John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de>
Cc: Madhavan Srinivasan <maddy@linux.ibm.com>
Cc: Matt Turner <mattst88@gmail.com>
Cc: Max Filippov <jcmvbkbc@gmail.com>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Michal Simek <monstr@monstr.eu>
Cc: Palmer Dabbelt <palmer@dabbelt.com>
Cc: Richard Weinberger <richard@nod.at>
Cc: Russel King <linux@armlinux.org.uk>
Cc: Stafford Horne <shorne@gmail.com>
Cc: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
Cc: Thomas Gleinxer <tglx@linutronix.de>
Cc: Vasily Gorbik <gor@linux.ibm.com>
Cc: Vineet Gupta <vgupta@kernel.org>
Cc: Will Deacon <will@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

authored by

Mike Rapoport (Microsoft) and committed by
Andrew Morton
8afa901c 0d98484e

+7 -136
-6
arch/alpha/mm/init.c
··· 273 273 } 274 274 #endif 275 275 276 - void __init 277 - mem_init(void) 278 - { 279 - memblock_free_all(); 280 - } 281 - 282 276 static const pgprot_t protection_map[16] = { 283 277 [VM_NONE] = _PAGE_P(_PAGE_FOE | _PAGE_FOW | 284 278 _PAGE_FOR),
-11
arch/arc/mm/init.c
··· 169 169 BUILD_BUG_ON((PTRS_PER_PTE * sizeof(pte_t)) > PAGE_SIZE); 170 170 } 171 171 172 - /* 173 - * mem_init - initializes memory 174 - * 175 - * Frees up bootmem 176 - * Calculates and displays memory available/used 177 - */ 178 - void __init mem_init(void) 179 - { 180 - memblock_free_all(); 181 - } 182 - 183 172 #ifdef CONFIG_HIGHMEM 184 173 int pfn_valid(unsigned long pfn) 185 174 {
-11
arch/arm/mm/init.c
··· 263 263 #endif 264 264 } 265 265 266 - /* 267 - * mem_init() marks the free areas in the mem_map and tells us how much 268 - * memory is free. This is done after various parts of the system have 269 - * claimed their memory after the kernel image. 270 - */ 271 - void __init mem_init(void) 272 - { 273 - /* this will put all unused low memory onto the freelists */ 274 - memblock_free_all(); 275 - } 276 - 277 266 #ifdef CONFIG_STRICT_KERNEL_RWX 278 267 struct section_perm { 279 268 const char *name;
-11
arch/arm64/mm/init.c
··· 406 406 } 407 407 } 408 408 409 - /* 410 - * mem_init() marks the free areas in the mem_map and tells us how much memory 411 - * is free. This is done after various parts of the system have claimed their 412 - * memory after the kernel image. 413 - */ 414 - void __init mem_init(void) 415 - { 416 - /* this will put all unused low memory onto the freelists */ 417 - memblock_free_all(); 418 - } 419 - 420 409 void free_initmem(void) 421 410 { 422 411 void *lm_init_begin = lm_alias(__init_begin);
-5
arch/csky/mm/init.c
··· 42 42 __page_aligned_bss; 43 43 EXPORT_SYMBOL(empty_zero_page); 44 44 45 - void __init mem_init(void) 46 - { 47 - memblock_free_all(); 48 - } 49 - 50 45 void free_initmem(void) 51 46 { 52 47 free_initmem_default(-1);
-18
arch/hexagon/mm/init.c
··· 43 43 /* checkpatch says don't init this to 0. */ 44 44 unsigned long long kmap_generation; 45 45 46 - /* 47 - * mem_init - initializes memory 48 - * 49 - * Frees up bootmem 50 - * Fixes up more stuff for HIGHMEM 51 - * Calculates and displays memory available/used 52 - */ 53 - void __init mem_init(void) 54 - { 55 - /* No idea where this is actually declared. Seems to evade LXR. */ 56 - memblock_free_all(); 57 - 58 - /* 59 - * To-Do: someone somewhere should wipe out the bootmem map 60 - * after we're done? 61 - */ 62 - } 63 - 64 46 void sync_icache_dcache(pte_t pte) 65 47 { 66 48 unsigned long addr;
-5
arch/loongarch/kernel/numa.c
··· 387 387 free_area_init(zones_size); 388 388 } 389 389 390 - void __init mem_init(void) 391 - { 392 - memblock_free_all(); 393 - } 394 - 395 390 int pcibus_to_node(struct pci_bus *bus) 396 391 { 397 392 return dev_to_node(&bus->dev);
-5
arch/loongarch/mm/init.c
··· 75 75 76 76 free_area_init(max_zone_pfns); 77 77 } 78 - 79 - void __init mem_init(void) 80 - { 81 - memblock_free_all(); 82 - } 83 78 #endif /* !CONFIG_NUMA */ 84 79 85 80 void __ref free_initmem(void)
-2
arch/m68k/mm/init.c
··· 121 121 122 122 void __init mem_init(void) 123 123 { 124 - /* this will put all memory onto the freelists */ 125 - memblock_free_all(); 126 124 init_pointer_tables(); 127 125 }
-3
arch/microblaze/mm/init.c
··· 107 107 108 108 void __init mem_init(void) 109 109 { 110 - /* this will put all memory onto the freelists */ 111 - memblock_free_all(); 112 - 113 110 mem_init_done = 1; 114 111 } 115 112
-5
arch/mips/mm/init.c
··· 451 451 } 452 452 #endif /* !CONFIG_NUMA */ 453 453 454 - void __init mem_init(void) 455 - { 456 - memblock_free_all(); 457 - } 458 - 459 454 void free_init_pages(const char *what, unsigned long begin, unsigned long end) 460 455 { 461 456 unsigned long pfn;
-6
arch/nios2/mm/init.c
··· 60 60 (unsigned long)empty_zero_page + PAGE_SIZE); 61 61 } 62 62 63 - void __init mem_init(void) 64 - { 65 - /* this will put all memory onto the freelists */ 66 - memblock_free_all(); 67 - } 68 - 69 63 void __init mmu_init(void) 70 64 { 71 65 flush_tlb_all();
-3
arch/openrisc/mm/init.c
··· 196 196 /* clear the zero-page */ 197 197 memset((void *)empty_zero_page, 0, PAGE_SIZE); 198 198 199 - /* this will put all low memory onto the freelists */ 200 - memblock_free_all(); 201 - 202 199 printk("mem_init_done ...........................................\n"); 203 200 mem_init_done = 1; 204 201 return;
-2
arch/parisc/mm/init.c
··· 562 562 BUILD_BUG_ON(TMPALIAS_MAP_START >= 0x80000000); 563 563 #endif 564 564 565 - memblock_free_all(); 566 - 567 565 #ifdef CONFIG_PA11 568 566 if (boot_cpu_data.cpu_type == pcxl2 || boot_cpu_data.cpu_type == pcxl) { 569 567 pcxl_dma_start = (unsigned long)SET_MAP_OFFSET(MAP_START);
-5
arch/powerpc/mm/mem.c
··· 327 327 #endif /* CONFIG_PPC32 */ 328 328 } 329 329 330 - void __init mem_init(void) 331 - { 332 - memblock_free_all(); 333 - } 334 - 335 330 void free_initmem(void) 336 331 { 337 332 ppc_md.progress = ppc_printk_progress;
-5
arch/riscv/mm/init.c
··· 196 196 print_vm_layout(); 197 197 } 198 198 199 - void __init mem_init(void) 200 - { 201 - memblock_free_all(); 202 - } 203 - 204 199 /* Limit the memory size via mem. */ 205 200 static phys_addr_t memory_limit; 206 201 #ifdef CONFIG_XIP_KERNEL
-6
arch/s390/mm/init.c
··· 165 165 setup_zero_pages(); /* Setup zeroed pages. */ 166 166 } 167 167 168 - void __init mem_init(void) 169 - { 170 - /* this will put all low memory onto the freelists */ 171 - memblock_free_all(); 172 - } 173 - 174 168 unsigned long memory_block_size_bytes(void) 175 169 { 176 170 /*
-2
arch/sh/mm/init.c
··· 330 330 331 331 void __init mem_init(void) 332 332 { 333 - memblock_free_all(); 334 - 335 333 /* Set this up early, so we can take care of the zero page */ 336 334 cpu_cache_init(); 337 335
-5
arch/sparc/mm/init_32.c
··· 264 264 taint_real_pages(); 265 265 } 266 266 267 - void __init mem_init(void) 268 - { 269 - memblock_free_all(); 270 - } 271 - 272 267 void sparc_flush_page_to_ram(struct page *page) 273 268 { 274 269 unsigned long vaddr = (unsigned long)page_address(page);
-2
arch/sparc/mm/init_64.c
··· 2505 2505 } 2506 2506 void __init mem_init(void) 2507 2507 { 2508 - memblock_free_all(); 2509 - 2510 2508 /* 2511 2509 * Must be done after boot memory is put on freelist, because here we 2512 2510 * might set fields in deferred struct pages that have not yet been
-2
arch/um/kernel/mem.c
··· 71 71 72 72 void __init mem_init(void) 73 73 { 74 - /* this will put all low memory onto the freelists */ 75 - memblock_free_all(); 76 74 kmalloc_ok = 1; 77 75 } 78 76
-3
arch/x86/mm/init_32.c
··· 702 702 703 703 void __init mem_init(void) 704 704 { 705 - /* this will put all low memory onto the freelists */ 706 - memblock_free_all(); 707 - 708 705 after_bootmem = 1; 709 706 x86_init.hyper.init_after_bootmem(); 710 707
-2
arch/x86/mm/init_64.c
··· 1357 1357 { 1358 1358 /* clear_bss() already clear the empty_zero_page */ 1359 1359 1360 - /* this will put all memory onto the freelists */ 1361 - memblock_free_all(); 1362 1360 after_bootmem = 1; 1363 1361 x86_init.hyper.init_after_bootmem(); 1364 1362
-9
arch/xtensa/mm/init.c
··· 129 129 print_vm_layout(); 130 130 } 131 131 132 - /* 133 - * Initialize memory pages. 134 - */ 135 - 136 - void __init mem_init(void) 137 - { 138 - memblock_free_all(); 139 - } 140 - 141 132 static void __init parse_memmap_one(char *p) 142 133 { 143 134 char *oldp;
-1
include/linux/memblock.h
··· 133 133 int memblock_clear_nomap(phys_addr_t base, phys_addr_t size); 134 134 int memblock_reserved_mark_noinit(phys_addr_t base, phys_addr_t size); 135 135 136 - void memblock_free_all(void); 137 136 void memblock_free(void *ptr, size_t size); 138 137 void reset_all_zones_managed_pages(void); 139 138
+2 -1
mm/internal.h
··· 1475 1475 } 1476 1476 1477 1477 extern bool mirrored_kernelcore; 1478 - extern bool memblock_has_mirror(void); 1478 + bool memblock_has_mirror(void); 1479 + void memblock_free_all(void); 1479 1480 1480 1481 static __always_inline void vma_set_range(struct vm_area_struct *vma, 1481 1482 unsigned long start, unsigned long end,
+5
mm/mm_init.c
··· 2738 2738 { 2739 2739 } 2740 2740 2741 + void __init __weak mem_init(void) 2742 + { 2743 + } 2744 + 2741 2745 /* 2742 2746 * Set up kernel memory allocators 2743 2747 */ ··· 2765 2761 report_meminit(); 2766 2762 kmsan_init_shadow(); 2767 2763 stack_depot_early_init(); 2764 + memblock_free_all(); 2768 2765 mem_init(); 2769 2766 kmem_cache_init(); 2770 2767 /*