1c1cc1552SCatalin Marinas /* 2c1cc1552SCatalin Marinas * Based on arch/arm/mm/init.c 3c1cc1552SCatalin Marinas * 4c1cc1552SCatalin Marinas * Copyright (C) 1995-2005 Russell King 5c1cc1552SCatalin Marinas * Copyright (C) 2012 ARM Ltd. 6c1cc1552SCatalin Marinas * 7c1cc1552SCatalin Marinas * This program is free software; you can redistribute it and/or modify 8c1cc1552SCatalin Marinas * it under the terms of the GNU General Public License version 2 as 9c1cc1552SCatalin Marinas * published by the Free Software Foundation. 10c1cc1552SCatalin Marinas * 11c1cc1552SCatalin Marinas * This program is distributed in the hope that it will be useful, 12c1cc1552SCatalin Marinas * but WITHOUT ANY WARRANTY; without even the implied warranty of 13c1cc1552SCatalin Marinas * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14c1cc1552SCatalin Marinas * GNU General Public License for more details. 15c1cc1552SCatalin Marinas * 16c1cc1552SCatalin Marinas * You should have received a copy of the GNU General Public License 17c1cc1552SCatalin Marinas * along with this program. If not, see <http://www.gnu.org/licenses/>. 18c1cc1552SCatalin Marinas */ 19c1cc1552SCatalin Marinas 20c1cc1552SCatalin Marinas #include <linux/kernel.h> 21c1cc1552SCatalin Marinas #include <linux/export.h> 22c1cc1552SCatalin Marinas #include <linux/errno.h> 23c1cc1552SCatalin Marinas #include <linux/swap.h> 24c1cc1552SCatalin Marinas #include <linux/init.h> 25c1cc1552SCatalin Marinas #include <linux/bootmem.h> 26c1cc1552SCatalin Marinas #include <linux/mman.h> 27c1cc1552SCatalin Marinas #include <linux/nodemask.h> 28c1cc1552SCatalin Marinas #include <linux/initrd.h> 29c1cc1552SCatalin Marinas #include <linux/gfp.h> 30c1cc1552SCatalin Marinas #include <linux/memblock.h> 31c1cc1552SCatalin Marinas #include <linux/sort.h> 32c1cc1552SCatalin Marinas #include <linux/of_fdt.h> 3319e7640dSCatalin Marinas #include <linux/dma-mapping.h> 346ac2104dSLaura Abbott #include <linux/dma-contiguous.h> 3586c8b27aSLeif Lindholm #include <linux/efi.h> 36a1e50a82SCatalin Marinas #include <linux/swiotlb.h> 37c1cc1552SCatalin Marinas 38a7f8de16SArd Biesheuvel #include <asm/boot.h> 3908375198SCatalin Marinas #include <asm/fixmap.h> 40f9040773SArd Biesheuvel #include <asm/kasan.h> 41a7f8de16SArd Biesheuvel #include <asm/kernel-pgtable.h> 42aa03c428SMark Rutland #include <asm/memory.h> 43c1cc1552SCatalin Marinas #include <asm/sections.h> 44c1cc1552SCatalin Marinas #include <asm/setup.h> 45c1cc1552SCatalin Marinas #include <asm/sizes.h> 46c1cc1552SCatalin Marinas #include <asm/tlb.h> 47e039ee4eSAndre Przywara #include <asm/alternative.h> 48c1cc1552SCatalin Marinas 49c1cc1552SCatalin Marinas #include "mm.h" 50c1cc1552SCatalin Marinas 51a7f8de16SArd Biesheuvel /* 52a7f8de16SArd Biesheuvel * We need to be able to catch inadvertent references to memstart_addr 53a7f8de16SArd Biesheuvel * that occur (potentially in generic code) before arm64_memblock_init() 54a7f8de16SArd Biesheuvel * executes, which assigns it its actual value. So use a default value 55a7f8de16SArd Biesheuvel * that cannot be mistaken for a real physical address. 56a7f8de16SArd Biesheuvel */ 57020d044fSArd Biesheuvel s64 memstart_addr __read_mostly = -1; 58a1e50a82SCatalin Marinas phys_addr_t arm64_dma_phys_limit __read_mostly; 59c1cc1552SCatalin Marinas 60ec2eaa73SRob Herring #ifdef CONFIG_BLK_DEV_INITRD 61c1cc1552SCatalin Marinas static int __init early_initrd(char *p) 62c1cc1552SCatalin Marinas { 63c1cc1552SCatalin Marinas unsigned long start, size; 64c1cc1552SCatalin Marinas char *endp; 65c1cc1552SCatalin Marinas 66c1cc1552SCatalin Marinas start = memparse(p, &endp); 67c1cc1552SCatalin Marinas if (*endp == ',') { 68c1cc1552SCatalin Marinas size = memparse(endp + 1, NULL); 69c1cc1552SCatalin Marinas 70a89dea58SArd Biesheuvel initrd_start = start; 71a89dea58SArd Biesheuvel initrd_end = start + size; 72c1cc1552SCatalin Marinas } 73c1cc1552SCatalin Marinas return 0; 74c1cc1552SCatalin Marinas } 75c1cc1552SCatalin Marinas early_param("initrd", early_initrd); 76ec2eaa73SRob Herring #endif 77c1cc1552SCatalin Marinas 78d50314a6SCatalin Marinas /* 79d50314a6SCatalin Marinas * Return the maximum physical address for ZONE_DMA (DMA_BIT_MASK(32)). It 80d50314a6SCatalin Marinas * currently assumes that for memory starting above 4G, 32-bit devices will 81d50314a6SCatalin Marinas * use a DMA offset. 82d50314a6SCatalin Marinas */ 83a7c61a34SJisheng Zhang static phys_addr_t __init max_zone_dma_phys(void) 84d50314a6SCatalin Marinas { 85d50314a6SCatalin Marinas phys_addr_t offset = memblock_start_of_DRAM() & GENMASK_ULL(63, 32); 86d50314a6SCatalin Marinas return min(offset + (1ULL << 32), memblock_end_of_DRAM()); 87d50314a6SCatalin Marinas } 88d50314a6SCatalin Marinas 89c1cc1552SCatalin Marinas static void __init zone_sizes_init(unsigned long min, unsigned long max) 90c1cc1552SCatalin Marinas { 91c1cc1552SCatalin Marinas struct memblock_region *reg; 92c1cc1552SCatalin Marinas unsigned long zone_size[MAX_NR_ZONES], zhole_size[MAX_NR_ZONES]; 9319e7640dSCatalin Marinas unsigned long max_dma = min; 94c1cc1552SCatalin Marinas 95c1cc1552SCatalin Marinas memset(zone_size, 0, sizeof(zone_size)); 96c1cc1552SCatalin Marinas 97c1cc1552SCatalin Marinas /* 4GB maximum for 32-bit only capable devices */ 9886a5906eSRobin Murphy #ifdef CONFIG_ZONE_DMA 99a1e50a82SCatalin Marinas max_dma = PFN_DOWN(arm64_dma_phys_limit); 10019e7640dSCatalin Marinas zone_size[ZONE_DMA] = max_dma - min; 10186a5906eSRobin Murphy #endif 10219e7640dSCatalin Marinas zone_size[ZONE_NORMAL] = max - max_dma; 103c1cc1552SCatalin Marinas 104c1cc1552SCatalin Marinas memcpy(zhole_size, zone_size, sizeof(zhole_size)); 105c1cc1552SCatalin Marinas 106c1cc1552SCatalin Marinas for_each_memblock(memory, reg) { 107c1cc1552SCatalin Marinas unsigned long start = memblock_region_memory_base_pfn(reg); 108c1cc1552SCatalin Marinas unsigned long end = memblock_region_memory_end_pfn(reg); 109c1cc1552SCatalin Marinas 110c1cc1552SCatalin Marinas if (start >= max) 111c1cc1552SCatalin Marinas continue; 11219e7640dSCatalin Marinas 11386a5906eSRobin Murphy #ifdef CONFIG_ZONE_DMA 11486a5906eSRobin Murphy if (start < max_dma) { 11519e7640dSCatalin Marinas unsigned long dma_end = min(end, max_dma); 11619e7640dSCatalin Marinas zhole_size[ZONE_DMA] -= dma_end - start; 117c1cc1552SCatalin Marinas } 11886a5906eSRobin Murphy #endif 11919e7640dSCatalin Marinas if (end > max_dma) { 120c1cc1552SCatalin Marinas unsigned long normal_end = min(end, max); 12119e7640dSCatalin Marinas unsigned long normal_start = max(start, max_dma); 122c1cc1552SCatalin Marinas zhole_size[ZONE_NORMAL] -= normal_end - normal_start; 123c1cc1552SCatalin Marinas } 124c1cc1552SCatalin Marinas } 125c1cc1552SCatalin Marinas 126c1cc1552SCatalin Marinas free_area_init_node(0, zone_size, min, zhole_size); 127c1cc1552SCatalin Marinas } 128c1cc1552SCatalin Marinas 129c1cc1552SCatalin Marinas #ifdef CONFIG_HAVE_ARCH_PFN_VALID 130c1cc1552SCatalin Marinas int pfn_valid(unsigned long pfn) 131c1cc1552SCatalin Marinas { 13268709f45SArd Biesheuvel return memblock_is_map_memory(pfn << PAGE_SHIFT); 133c1cc1552SCatalin Marinas } 134c1cc1552SCatalin Marinas EXPORT_SYMBOL(pfn_valid); 135c1cc1552SCatalin Marinas #endif 136c1cc1552SCatalin Marinas 137c1cc1552SCatalin Marinas #ifndef CONFIG_SPARSEMEM 138a7c61a34SJisheng Zhang static void __init arm64_memory_present(void) 139c1cc1552SCatalin Marinas { 140c1cc1552SCatalin Marinas } 141c1cc1552SCatalin Marinas #else 142a7c61a34SJisheng Zhang static void __init arm64_memory_present(void) 143c1cc1552SCatalin Marinas { 144c1cc1552SCatalin Marinas struct memblock_region *reg; 145c1cc1552SCatalin Marinas 146c1cc1552SCatalin Marinas for_each_memblock(memory, reg) 147c1cc1552SCatalin Marinas memory_present(0, memblock_region_memory_base_pfn(reg), 148c1cc1552SCatalin Marinas memblock_region_memory_end_pfn(reg)); 149c1cc1552SCatalin Marinas } 150c1cc1552SCatalin Marinas #endif 151c1cc1552SCatalin Marinas 1526083fe74SMark Rutland static phys_addr_t memory_limit = (phys_addr_t)ULLONG_MAX; 1536083fe74SMark Rutland 1546083fe74SMark Rutland /* 1556083fe74SMark Rutland * Limit the memory size that was specified via FDT. 1566083fe74SMark Rutland */ 1576083fe74SMark Rutland static int __init early_mem(char *p) 1586083fe74SMark Rutland { 1596083fe74SMark Rutland if (!p) 1606083fe74SMark Rutland return 1; 1616083fe74SMark Rutland 1626083fe74SMark Rutland memory_limit = memparse(p, &p) & PAGE_MASK; 1636083fe74SMark Rutland pr_notice("Memory limited to %lldMB\n", memory_limit >> 20); 1646083fe74SMark Rutland 1656083fe74SMark Rutland return 0; 1666083fe74SMark Rutland } 1676083fe74SMark Rutland early_param("mem", early_mem); 1686083fe74SMark Rutland 169c1cc1552SCatalin Marinas void __init arm64_memblock_init(void) 170c1cc1552SCatalin Marinas { 171a7f8de16SArd Biesheuvel const s64 linear_region_size = -(s64)PAGE_OFFSET; 172a7f8de16SArd Biesheuvel 173a7f8de16SArd Biesheuvel /* 174*6d2aa549SArd Biesheuvel * Ensure that the linear region takes up exactly half of the kernel 175*6d2aa549SArd Biesheuvel * virtual address space. This way, we can distinguish a linear address 176*6d2aa549SArd Biesheuvel * from a kernel/module/vmalloc address by testing a single bit. 177*6d2aa549SArd Biesheuvel */ 178*6d2aa549SArd Biesheuvel BUILD_BUG_ON(linear_region_size != BIT(VA_BITS - 1)); 179*6d2aa549SArd Biesheuvel 180*6d2aa549SArd Biesheuvel /* 181a7f8de16SArd Biesheuvel * Select a suitable value for the base of physical memory. 182a7f8de16SArd Biesheuvel */ 183a7f8de16SArd Biesheuvel memstart_addr = round_down(memblock_start_of_DRAM(), 184a7f8de16SArd Biesheuvel ARM64_MEMSTART_ALIGN); 185a7f8de16SArd Biesheuvel 186a7f8de16SArd Biesheuvel /* 187a7f8de16SArd Biesheuvel * Remove the memory that we will not be able to cover with the 188a7f8de16SArd Biesheuvel * linear mapping. Take care not to clip the kernel which may be 189a7f8de16SArd Biesheuvel * high in memory. 190a7f8de16SArd Biesheuvel */ 191020d044fSArd Biesheuvel memblock_remove(max_t(u64, memstart_addr + linear_region_size, __pa(_end)), 192a7f8de16SArd Biesheuvel ULLONG_MAX); 193a7f8de16SArd Biesheuvel if (memblock_end_of_DRAM() > linear_region_size) 194a7f8de16SArd Biesheuvel memblock_remove(0, memblock_end_of_DRAM() - linear_region_size); 195a7f8de16SArd Biesheuvel 196a7f8de16SArd Biesheuvel /* 197a7f8de16SArd Biesheuvel * Apply the memory limit if it was set. Since the kernel may be loaded 198a7f8de16SArd Biesheuvel * high up in memory, add back the kernel region that must be accessible 199a7f8de16SArd Biesheuvel * via the linear mapping. 200a7f8de16SArd Biesheuvel */ 201a7f8de16SArd Biesheuvel if (memory_limit != (phys_addr_t)ULLONG_MAX) { 2026083fe74SMark Rutland memblock_enforce_memory_limit(memory_limit); 203a7f8de16SArd Biesheuvel memblock_add(__pa(_text), (u64)(_end - _text)); 204a7f8de16SArd Biesheuvel } 2056083fe74SMark Rutland 206c031a421SArd Biesheuvel if (IS_ENABLED(CONFIG_RANDOMIZE_BASE)) { 207c031a421SArd Biesheuvel extern u16 memstart_offset_seed; 208c031a421SArd Biesheuvel u64 range = linear_region_size - 209c031a421SArd Biesheuvel (memblock_end_of_DRAM() - memblock_start_of_DRAM()); 210c031a421SArd Biesheuvel 211c031a421SArd Biesheuvel /* 212c031a421SArd Biesheuvel * If the size of the linear region exceeds, by a sufficient 213c031a421SArd Biesheuvel * margin, the size of the region that the available physical 214c031a421SArd Biesheuvel * memory spans, randomize the linear region as well. 215c031a421SArd Biesheuvel */ 216c031a421SArd Biesheuvel if (memstart_offset_seed > 0 && range >= ARM64_MEMSTART_ALIGN) { 217c031a421SArd Biesheuvel range = range / ARM64_MEMSTART_ALIGN + 1; 218c031a421SArd Biesheuvel memstart_addr -= ARM64_MEMSTART_ALIGN * 219c031a421SArd Biesheuvel ((range * memstart_offset_seed) >> 16); 220c031a421SArd Biesheuvel } 221c031a421SArd Biesheuvel } 222c031a421SArd Biesheuvel 223bd00cd5fSMark Rutland /* 224bd00cd5fSMark Rutland * Register the kernel text, kernel data, initrd, and initial 225bd00cd5fSMark Rutland * pagetables with memblock. 226bd00cd5fSMark Rutland */ 227c1cc1552SCatalin Marinas memblock_reserve(__pa(_text), _end - _text); 228c1cc1552SCatalin Marinas #ifdef CONFIG_BLK_DEV_INITRD 229a89dea58SArd Biesheuvel if (initrd_start) { 230a89dea58SArd Biesheuvel memblock_reserve(initrd_start, initrd_end - initrd_start); 231a89dea58SArd Biesheuvel 232a89dea58SArd Biesheuvel /* the generic initrd code expects virtual addresses */ 233a89dea58SArd Biesheuvel initrd_start = __phys_to_virt(initrd_start); 234a89dea58SArd Biesheuvel initrd_end = __phys_to_virt(initrd_end); 235a89dea58SArd Biesheuvel } 236c1cc1552SCatalin Marinas #endif 237c1cc1552SCatalin Marinas 2389bf14b7cSMarek Szyprowski early_init_fdt_scan_reserved_mem(); 2392d5a5612SCatalin Marinas 2402d5a5612SCatalin Marinas /* 4GB maximum for 32-bit only capable devices */ 2412d5a5612SCatalin Marinas if (IS_ENABLED(CONFIG_ZONE_DMA)) 242a1e50a82SCatalin Marinas arm64_dma_phys_limit = max_zone_dma_phys(); 243a1e50a82SCatalin Marinas else 244a1e50a82SCatalin Marinas arm64_dma_phys_limit = PHYS_MASK + 1; 245a1e50a82SCatalin Marinas dma_contiguous_reserve(arm64_dma_phys_limit); 2466ac2104dSLaura Abbott 247c1cc1552SCatalin Marinas memblock_allow_resize(); 248c1cc1552SCatalin Marinas memblock_dump_all(); 249c1cc1552SCatalin Marinas } 250c1cc1552SCatalin Marinas 251c1cc1552SCatalin Marinas void __init bootmem_init(void) 252c1cc1552SCatalin Marinas { 253c1cc1552SCatalin Marinas unsigned long min, max; 254c1cc1552SCatalin Marinas 255c1cc1552SCatalin Marinas min = PFN_UP(memblock_start_of_DRAM()); 256c1cc1552SCatalin Marinas max = PFN_DOWN(memblock_end_of_DRAM()); 257c1cc1552SCatalin Marinas 25836dd9086SVladimir Murzin early_memtest(min << PAGE_SHIFT, max << PAGE_SHIFT); 25936dd9086SVladimir Murzin 260c1cc1552SCatalin Marinas /* 261c1cc1552SCatalin Marinas * Sparsemem tries to allocate bootmem in memory_present(), so must be 262c1cc1552SCatalin Marinas * done after the fixed reservations. 263c1cc1552SCatalin Marinas */ 264c1cc1552SCatalin Marinas arm64_memory_present(); 265c1cc1552SCatalin Marinas 266c1cc1552SCatalin Marinas sparse_init(); 267c1cc1552SCatalin Marinas zone_sizes_init(min, max); 268c1cc1552SCatalin Marinas 269c1cc1552SCatalin Marinas high_memory = __va((max << PAGE_SHIFT) - 1) + 1; 270c1cc1552SCatalin Marinas max_pfn = max_low_pfn = max; 271c1cc1552SCatalin Marinas } 272c1cc1552SCatalin Marinas 273c1cc1552SCatalin Marinas #ifndef CONFIG_SPARSEMEM_VMEMMAP 274c1cc1552SCatalin Marinas static inline void free_memmap(unsigned long start_pfn, unsigned long end_pfn) 275c1cc1552SCatalin Marinas { 276c1cc1552SCatalin Marinas struct page *start_pg, *end_pg; 277c1cc1552SCatalin Marinas unsigned long pg, pgend; 278c1cc1552SCatalin Marinas 279c1cc1552SCatalin Marinas /* 280c1cc1552SCatalin Marinas * Convert start_pfn/end_pfn to a struct page pointer. 281c1cc1552SCatalin Marinas */ 282c1cc1552SCatalin Marinas start_pg = pfn_to_page(start_pfn - 1) + 1; 283c1cc1552SCatalin Marinas end_pg = pfn_to_page(end_pfn - 1) + 1; 284c1cc1552SCatalin Marinas 285c1cc1552SCatalin Marinas /* 286c1cc1552SCatalin Marinas * Convert to physical addresses, and round start upwards and end 287c1cc1552SCatalin Marinas * downwards. 288c1cc1552SCatalin Marinas */ 289c1cc1552SCatalin Marinas pg = (unsigned long)PAGE_ALIGN(__pa(start_pg)); 290c1cc1552SCatalin Marinas pgend = (unsigned long)__pa(end_pg) & PAGE_MASK; 291c1cc1552SCatalin Marinas 292c1cc1552SCatalin Marinas /* 293c1cc1552SCatalin Marinas * If there are free pages between these, free the section of the 294c1cc1552SCatalin Marinas * memmap array. 295c1cc1552SCatalin Marinas */ 296c1cc1552SCatalin Marinas if (pg < pgend) 297c1cc1552SCatalin Marinas free_bootmem(pg, pgend - pg); 298c1cc1552SCatalin Marinas } 299c1cc1552SCatalin Marinas 300c1cc1552SCatalin Marinas /* 301c1cc1552SCatalin Marinas * The mem_map array can get very big. Free the unused area of the memory map. 302c1cc1552SCatalin Marinas */ 303c1cc1552SCatalin Marinas static void __init free_unused_memmap(void) 304c1cc1552SCatalin Marinas { 305c1cc1552SCatalin Marinas unsigned long start, prev_end = 0; 306c1cc1552SCatalin Marinas struct memblock_region *reg; 307c1cc1552SCatalin Marinas 308c1cc1552SCatalin Marinas for_each_memblock(memory, reg) { 309c1cc1552SCatalin Marinas start = __phys_to_pfn(reg->base); 310c1cc1552SCatalin Marinas 311c1cc1552SCatalin Marinas #ifdef CONFIG_SPARSEMEM 312c1cc1552SCatalin Marinas /* 313c1cc1552SCatalin Marinas * Take care not to free memmap entries that don't exist due 314c1cc1552SCatalin Marinas * to SPARSEMEM sections which aren't present. 315c1cc1552SCatalin Marinas */ 316c1cc1552SCatalin Marinas start = min(start, ALIGN(prev_end, PAGES_PER_SECTION)); 317c1cc1552SCatalin Marinas #endif 318c1cc1552SCatalin Marinas /* 319c1cc1552SCatalin Marinas * If we had a previous bank, and there is a space between the 320c1cc1552SCatalin Marinas * current bank and the previous, free it. 321c1cc1552SCatalin Marinas */ 322c1cc1552SCatalin Marinas if (prev_end && prev_end < start) 323c1cc1552SCatalin Marinas free_memmap(prev_end, start); 324c1cc1552SCatalin Marinas 325c1cc1552SCatalin Marinas /* 326c1cc1552SCatalin Marinas * Align up here since the VM subsystem insists that the 327c1cc1552SCatalin Marinas * memmap entries are valid from the bank end aligned to 328c1cc1552SCatalin Marinas * MAX_ORDER_NR_PAGES. 329c1cc1552SCatalin Marinas */ 330b9bcc919SDave P Martin prev_end = ALIGN(__phys_to_pfn(reg->base + reg->size), 331c1cc1552SCatalin Marinas MAX_ORDER_NR_PAGES); 332c1cc1552SCatalin Marinas } 333c1cc1552SCatalin Marinas 334c1cc1552SCatalin Marinas #ifdef CONFIG_SPARSEMEM 335c1cc1552SCatalin Marinas if (!IS_ALIGNED(prev_end, PAGES_PER_SECTION)) 336c1cc1552SCatalin Marinas free_memmap(prev_end, ALIGN(prev_end, PAGES_PER_SECTION)); 337c1cc1552SCatalin Marinas #endif 338c1cc1552SCatalin Marinas } 339c1cc1552SCatalin Marinas #endif /* !CONFIG_SPARSEMEM_VMEMMAP */ 340c1cc1552SCatalin Marinas 341c1cc1552SCatalin Marinas /* 342c1cc1552SCatalin Marinas * mem_init() marks the free areas in the mem_map and tells us how much memory 343c1cc1552SCatalin Marinas * is free. This is done after various parts of the system have claimed their 344c1cc1552SCatalin Marinas * memory after the kernel image. 345c1cc1552SCatalin Marinas */ 346c1cc1552SCatalin Marinas void __init mem_init(void) 347c1cc1552SCatalin Marinas { 348a1e50a82SCatalin Marinas swiotlb_init(1); 349a1e50a82SCatalin Marinas 350a6583c7cSGanapatrao Kulkarni set_max_mapnr(pfn_to_page(max_pfn) - mem_map); 351c1cc1552SCatalin Marinas 352c1cc1552SCatalin Marinas #ifndef CONFIG_SPARSEMEM_VMEMMAP 353c1cc1552SCatalin Marinas free_unused_memmap(); 354c1cc1552SCatalin Marinas #endif 355bee4ebd1SJiang Liu /* this will put all unused low memory onto the freelists */ 3560c988534SJiang Liu free_all_bootmem(); 357c1cc1552SCatalin Marinas 3586879ea83SJiang Liu mem_init_print_info(NULL); 359c1cc1552SCatalin Marinas 360c1cc1552SCatalin Marinas #define MLK(b, t) b, t, ((t) - (b)) >> 10 361c1cc1552SCatalin Marinas #define MLM(b, t) b, t, ((t) - (b)) >> 20 36208375198SCatalin Marinas #define MLG(b, t) b, t, ((t) - (b)) >> 30 363c1cc1552SCatalin Marinas #define MLK_ROUNDUP(b, t) b, t, DIV_ROUND_UP(((t) - (b)), SZ_1K) 364c1cc1552SCatalin Marinas 365c1cc1552SCatalin Marinas pr_notice("Virtual kernel memory layout:\n" 366ee7f881bSLinus Walleij #ifdef CONFIG_KASAN 367ee7f881bSLinus Walleij " kasan : 0x%16lx - 0x%16lx (%6ld GB)\n" 368ee7f881bSLinus Walleij #endif 369f9040773SArd Biesheuvel " modules : 0x%16lx - 0x%16lx (%6ld MB)\n" 37008375198SCatalin Marinas " vmalloc : 0x%16lx - 0x%16lx (%6ld GB)\n" 371f9040773SArd Biesheuvel " .text : 0x%p" " - 0x%p" " (%6ld KB)\n" 3722f39b5f9SJeremy Linton " .rodata : 0x%p" " - 0x%p" " (%6ld KB)\n" 373a6e1f727SArd Biesheuvel " .init : 0x%p" " - 0x%p" " (%6ld KB)\n" 374f9040773SArd Biesheuvel " .data : 0x%p" " - 0x%p" " (%6ld KB)\n" 375c1cc1552SCatalin Marinas #ifdef CONFIG_SPARSEMEM_VMEMMAP 37608375198SCatalin Marinas " vmemmap : 0x%16lx - 0x%16lx (%6ld GB maximum)\n" 37708375198SCatalin Marinas " 0x%16lx - 0x%16lx (%6ld MB actual)\n" 378c1cc1552SCatalin Marinas #endif 37908375198SCatalin Marinas " fixed : 0x%16lx - 0x%16lx (%6ld KB)\n" 380aa03c428SMark Rutland " PCI I/O : 0x%16lx - 0x%16lx (%6ld MB)\n" 381f9040773SArd Biesheuvel " memory : 0x%16lx - 0x%16lx (%6ld MB)\n", 382ee7f881bSLinus Walleij #ifdef CONFIG_KASAN 383ee7f881bSLinus Walleij MLG(KASAN_SHADOW_START, KASAN_SHADOW_END), 384ee7f881bSLinus Walleij #endif 385f9040773SArd Biesheuvel MLM(MODULES_VADDR, MODULES_END), 38608375198SCatalin Marinas MLG(VMALLOC_START, VMALLOC_END), 3872f39b5f9SJeremy Linton MLK_ROUNDUP(_text, __start_rodata), 3882f39b5f9SJeremy Linton MLK_ROUNDUP(__start_rodata, _etext), 389a6e1f727SArd Biesheuvel MLK_ROUNDUP(__init_begin, __init_end), 390f9040773SArd Biesheuvel MLK_ROUNDUP(_sdata, _edata), 391c1cc1552SCatalin Marinas #ifdef CONFIG_SPARSEMEM_VMEMMAP 39208375198SCatalin Marinas MLG((unsigned long)vmemmap, 39308375198SCatalin Marinas (unsigned long)vmemmap + VMEMMAP_SIZE), 394c031a421SArd Biesheuvel MLM((unsigned long)phys_to_page(memblock_start_of_DRAM()), 395c1cc1552SCatalin Marinas (unsigned long)virt_to_page(high_memory)), 396c1cc1552SCatalin Marinas #endif 39708375198SCatalin Marinas MLK(FIXADDR_START, FIXADDR_TOP), 398aa03c428SMark Rutland MLM(PCI_IO_START, PCI_IO_END), 399c031a421SArd Biesheuvel MLM(__phys_to_virt(memblock_start_of_DRAM()), 400c031a421SArd Biesheuvel (unsigned long)high_memory)); 401c1cc1552SCatalin Marinas 402c1cc1552SCatalin Marinas #undef MLK 403c1cc1552SCatalin Marinas #undef MLM 404c1cc1552SCatalin Marinas #undef MLK_ROUNDUP 405c1cc1552SCatalin Marinas 406c1cc1552SCatalin Marinas /* 407c1cc1552SCatalin Marinas * Check boundaries twice: Some fundamental inconsistencies can be 408c1cc1552SCatalin Marinas * detected at build time already. 409c1cc1552SCatalin Marinas */ 410c1cc1552SCatalin Marinas #ifdef CONFIG_COMPAT 411c1cc1552SCatalin Marinas BUILD_BUG_ON(TASK_SIZE_32 > TASK_SIZE_64); 412c1cc1552SCatalin Marinas #endif 413c1cc1552SCatalin Marinas 414bee4ebd1SJiang Liu if (PAGE_SIZE >= 16384 && get_num_physpages() <= 128) { 415c1cc1552SCatalin Marinas extern int sysctl_overcommit_memory; 416c1cc1552SCatalin Marinas /* 417c1cc1552SCatalin Marinas * On a machine this small we won't get anywhere without 418c1cc1552SCatalin Marinas * overcommit, so turn it on by default. 419c1cc1552SCatalin Marinas */ 420c1cc1552SCatalin Marinas sysctl_overcommit_memory = OVERCOMMIT_ALWAYS; 421c1cc1552SCatalin Marinas } 422c1cc1552SCatalin Marinas } 423c1cc1552SCatalin Marinas 424c1cc1552SCatalin Marinas void free_initmem(void) 425c1cc1552SCatalin Marinas { 4269af5b807SJiang Liu free_initmem_default(0); 427f9040773SArd Biesheuvel fixup_init(); 428c1cc1552SCatalin Marinas } 429c1cc1552SCatalin Marinas 430c1cc1552SCatalin Marinas #ifdef CONFIG_BLK_DEV_INITRD 431c1cc1552SCatalin Marinas 432662ba3dbSWang Long static int keep_initrd __initdata; 433c1cc1552SCatalin Marinas 434662ba3dbSWang Long void __init free_initrd_mem(unsigned long start, unsigned long end) 435c1cc1552SCatalin Marinas { 4360145058cSCatalin Marinas if (!keep_initrd) 4379af5b807SJiang Liu free_reserved_area((void *)start, (void *)end, 0, "initrd"); 438c1cc1552SCatalin Marinas } 439c1cc1552SCatalin Marinas 440c1cc1552SCatalin Marinas static int __init keepinitrd_setup(char *__unused) 441c1cc1552SCatalin Marinas { 442c1cc1552SCatalin Marinas keep_initrd = 1; 443c1cc1552SCatalin Marinas return 1; 444c1cc1552SCatalin Marinas } 445c1cc1552SCatalin Marinas 446c1cc1552SCatalin Marinas __setup("keepinitrd", keepinitrd_setup); 447c1cc1552SCatalin Marinas #endif 448a7f8de16SArd Biesheuvel 449a7f8de16SArd Biesheuvel /* 450a7f8de16SArd Biesheuvel * Dump out memory limit information on panic. 451a7f8de16SArd Biesheuvel */ 452a7f8de16SArd Biesheuvel static int dump_mem_limit(struct notifier_block *self, unsigned long v, void *p) 453a7f8de16SArd Biesheuvel { 454a7f8de16SArd Biesheuvel if (memory_limit != (phys_addr_t)ULLONG_MAX) { 455a7f8de16SArd Biesheuvel pr_emerg("Memory Limit: %llu MB\n", memory_limit >> 20); 456a7f8de16SArd Biesheuvel } else { 457a7f8de16SArd Biesheuvel pr_emerg("Memory Limit: none\n"); 458a7f8de16SArd Biesheuvel } 459a7f8de16SArd Biesheuvel return 0; 460a7f8de16SArd Biesheuvel } 461a7f8de16SArd Biesheuvel 462a7f8de16SArd Biesheuvel static struct notifier_block mem_limit_notifier = { 463a7f8de16SArd Biesheuvel .notifier_call = dump_mem_limit, 464a7f8de16SArd Biesheuvel }; 465a7f8de16SArd Biesheuvel 466a7f8de16SArd Biesheuvel static int __init register_mem_limit_dumper(void) 467a7f8de16SArd Biesheuvel { 468a7f8de16SArd Biesheuvel atomic_notifier_chain_register(&panic_notifier_list, 469a7f8de16SArd Biesheuvel &mem_limit_notifier); 470a7f8de16SArd Biesheuvel return 0; 471a7f8de16SArd Biesheuvel } 472a7f8de16SArd Biesheuvel __initcall(register_mem_limit_dumper); 473