162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Based on arch/arm/mm/init.c 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 1995-2005 Russell King 662306a36Sopenharmony_ci * Copyright (C) 2012 ARM Ltd. 762306a36Sopenharmony_ci */ 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include <linux/kernel.h> 1062306a36Sopenharmony_ci#include <linux/export.h> 1162306a36Sopenharmony_ci#include <linux/errno.h> 1262306a36Sopenharmony_ci#include <linux/swap.h> 1362306a36Sopenharmony_ci#include <linux/init.h> 1462306a36Sopenharmony_ci#include <linux/cache.h> 1562306a36Sopenharmony_ci#include <linux/mman.h> 1662306a36Sopenharmony_ci#include <linux/nodemask.h> 1762306a36Sopenharmony_ci#include <linux/initrd.h> 1862306a36Sopenharmony_ci#include <linux/gfp.h> 1962306a36Sopenharmony_ci#include <linux/memblock.h> 2062306a36Sopenharmony_ci#include <linux/sort.h> 2162306a36Sopenharmony_ci#include <linux/of.h> 2262306a36Sopenharmony_ci#include <linux/of_fdt.h> 2362306a36Sopenharmony_ci#include <linux/dma-direct.h> 2462306a36Sopenharmony_ci#include <linux/dma-map-ops.h> 2562306a36Sopenharmony_ci#include <linux/efi.h> 2662306a36Sopenharmony_ci#include <linux/swiotlb.h> 2762306a36Sopenharmony_ci#include <linux/vmalloc.h> 2862306a36Sopenharmony_ci#include <linux/mm.h> 2962306a36Sopenharmony_ci#include <linux/kexec.h> 3062306a36Sopenharmony_ci#include <linux/crash_dump.h> 3162306a36Sopenharmony_ci#include <linux/hugetlb.h> 3262306a36Sopenharmony_ci#include <linux/acpi_iort.h> 3362306a36Sopenharmony_ci#include <linux/kmemleak.h> 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci#include <asm/boot.h> 3662306a36Sopenharmony_ci#include <asm/fixmap.h> 3762306a36Sopenharmony_ci#include <asm/kasan.h> 3862306a36Sopenharmony_ci#include <asm/kernel-pgtable.h> 3962306a36Sopenharmony_ci#include <asm/kvm_host.h> 4062306a36Sopenharmony_ci#include <asm/memory.h> 4162306a36Sopenharmony_ci#include <asm/numa.h> 4262306a36Sopenharmony_ci#include <asm/sections.h> 4362306a36Sopenharmony_ci#include <asm/setup.h> 4462306a36Sopenharmony_ci#include <linux/sizes.h> 4562306a36Sopenharmony_ci#include <asm/tlb.h> 4662306a36Sopenharmony_ci#include <asm/alternative.h> 4762306a36Sopenharmony_ci#include <asm/xen/swiotlb-xen.h> 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci/* 5062306a36Sopenharmony_ci * We need to be able to catch inadvertent references to memstart_addr 5162306a36Sopenharmony_ci * that occur (potentially in generic code) before arm64_memblock_init() 5262306a36Sopenharmony_ci * executes, which assigns it its actual value. So use a default value 5362306a36Sopenharmony_ci * that cannot be mistaken for a real physical address. 5462306a36Sopenharmony_ci */ 5562306a36Sopenharmony_cis64 memstart_addr __ro_after_init = -1; 5662306a36Sopenharmony_ciEXPORT_SYMBOL(memstart_addr); 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci/* 5962306a36Sopenharmony_ci * If the corresponding config options are enabled, we create both ZONE_DMA 6062306a36Sopenharmony_ci * and ZONE_DMA32. By default ZONE_DMA covers the 32-bit addressable memory 6162306a36Sopenharmony_ci * unless restricted on specific platforms (e.g. 30-bit on Raspberry Pi 4). 6262306a36Sopenharmony_ci * In such case, ZONE_DMA32 covers the rest of the 32-bit addressable memory, 6362306a36Sopenharmony_ci * otherwise it is empty. 6462306a36Sopenharmony_ci */ 6562306a36Sopenharmony_ciphys_addr_t __ro_after_init arm64_dma_phys_limit; 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci/* Current arm64 boot protocol requires 2MB alignment */ 6862306a36Sopenharmony_ci#define CRASH_ALIGN SZ_2M 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci#define CRASH_ADDR_LOW_MAX arm64_dma_phys_limit 7162306a36Sopenharmony_ci#define CRASH_ADDR_HIGH_MAX (PHYS_MASK + 1) 7262306a36Sopenharmony_ci#define CRASH_HIGH_SEARCH_BASE SZ_4G 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci#define DEFAULT_CRASH_KERNEL_LOW_SIZE (128UL << 20) 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci/* 7762306a36Sopenharmony_ci * To make optimal use of block mappings when laying out the linear 7862306a36Sopenharmony_ci * mapping, round down the base of physical memory to a size that can 7962306a36Sopenharmony_ci * be mapped efficiently, i.e., either PUD_SIZE (4k granule) or PMD_SIZE 8062306a36Sopenharmony_ci * (64k granule), or a multiple that can be mapped using contiguous bits 8162306a36Sopenharmony_ci * in the page tables: 32 * PMD_SIZE (16k granule) 8262306a36Sopenharmony_ci */ 8362306a36Sopenharmony_ci#if defined(CONFIG_ARM64_4K_PAGES) 8462306a36Sopenharmony_ci#define ARM64_MEMSTART_SHIFT PUD_SHIFT 8562306a36Sopenharmony_ci#elif defined(CONFIG_ARM64_16K_PAGES) 8662306a36Sopenharmony_ci#define ARM64_MEMSTART_SHIFT CONT_PMD_SHIFT 8762306a36Sopenharmony_ci#else 8862306a36Sopenharmony_ci#define ARM64_MEMSTART_SHIFT PMD_SHIFT 8962306a36Sopenharmony_ci#endif 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci/* 9262306a36Sopenharmony_ci * sparsemem vmemmap imposes an additional requirement on the alignment of 9362306a36Sopenharmony_ci * memstart_addr, due to the fact that the base of the vmemmap region 9462306a36Sopenharmony_ci * has a direct correspondence, and needs to appear sufficiently aligned 9562306a36Sopenharmony_ci * in the virtual address space. 9662306a36Sopenharmony_ci */ 9762306a36Sopenharmony_ci#if ARM64_MEMSTART_SHIFT < SECTION_SIZE_BITS 9862306a36Sopenharmony_ci#define ARM64_MEMSTART_ALIGN (1UL << SECTION_SIZE_BITS) 9962306a36Sopenharmony_ci#else 10062306a36Sopenharmony_ci#define ARM64_MEMSTART_ALIGN (1UL << ARM64_MEMSTART_SHIFT) 10162306a36Sopenharmony_ci#endif 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_cistatic int __init reserve_crashkernel_low(unsigned long long low_size) 10462306a36Sopenharmony_ci{ 10562306a36Sopenharmony_ci unsigned long long low_base; 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci low_base = memblock_phys_alloc_range(low_size, CRASH_ALIGN, 0, CRASH_ADDR_LOW_MAX); 10862306a36Sopenharmony_ci if (!low_base) { 10962306a36Sopenharmony_ci pr_err("cannot allocate crashkernel low memory (size:0x%llx).\n", low_size); 11062306a36Sopenharmony_ci return -ENOMEM; 11162306a36Sopenharmony_ci } 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci pr_info("crashkernel low memory reserved: 0x%08llx - 0x%08llx (%lld MB)\n", 11462306a36Sopenharmony_ci low_base, low_base + low_size, low_size >> 20); 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci crashk_low_res.start = low_base; 11762306a36Sopenharmony_ci crashk_low_res.end = low_base + low_size - 1; 11862306a36Sopenharmony_ci insert_resource(&iomem_resource, &crashk_low_res); 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci return 0; 12162306a36Sopenharmony_ci} 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci/* 12462306a36Sopenharmony_ci * reserve_crashkernel() - reserves memory for crash kernel 12562306a36Sopenharmony_ci * 12662306a36Sopenharmony_ci * This function reserves memory area given in "crashkernel=" kernel command 12762306a36Sopenharmony_ci * line parameter. The memory reserved is used by dump capture kernel when 12862306a36Sopenharmony_ci * primary kernel is crashing. 12962306a36Sopenharmony_ci */ 13062306a36Sopenharmony_cistatic void __init reserve_crashkernel(void) 13162306a36Sopenharmony_ci{ 13262306a36Sopenharmony_ci unsigned long long crash_low_size = 0, search_base = 0; 13362306a36Sopenharmony_ci unsigned long long crash_max = CRASH_ADDR_LOW_MAX; 13462306a36Sopenharmony_ci unsigned long long crash_base, crash_size; 13562306a36Sopenharmony_ci char *cmdline = boot_command_line; 13662306a36Sopenharmony_ci bool fixed_base = false; 13762306a36Sopenharmony_ci bool high = false; 13862306a36Sopenharmony_ci int ret; 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci if (!IS_ENABLED(CONFIG_KEXEC_CORE)) 14162306a36Sopenharmony_ci return; 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci /* crashkernel=X[@offset] */ 14462306a36Sopenharmony_ci ret = parse_crashkernel(cmdline, memblock_phys_mem_size(), 14562306a36Sopenharmony_ci &crash_size, &crash_base); 14662306a36Sopenharmony_ci if (ret == -ENOENT) { 14762306a36Sopenharmony_ci ret = parse_crashkernel_high(cmdline, 0, &crash_size, &crash_base); 14862306a36Sopenharmony_ci if (ret || !crash_size) 14962306a36Sopenharmony_ci return; 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci /* 15262306a36Sopenharmony_ci * crashkernel=Y,low can be specified or not, but invalid value 15362306a36Sopenharmony_ci * is not allowed. 15462306a36Sopenharmony_ci */ 15562306a36Sopenharmony_ci ret = parse_crashkernel_low(cmdline, 0, &crash_low_size, &crash_base); 15662306a36Sopenharmony_ci if (ret == -ENOENT) 15762306a36Sopenharmony_ci crash_low_size = DEFAULT_CRASH_KERNEL_LOW_SIZE; 15862306a36Sopenharmony_ci else if (ret) 15962306a36Sopenharmony_ci return; 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci search_base = CRASH_HIGH_SEARCH_BASE; 16262306a36Sopenharmony_ci crash_max = CRASH_ADDR_HIGH_MAX; 16362306a36Sopenharmony_ci high = true; 16462306a36Sopenharmony_ci } else if (ret || !crash_size) { 16562306a36Sopenharmony_ci /* The specified value is invalid */ 16662306a36Sopenharmony_ci return; 16762306a36Sopenharmony_ci } 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_ci crash_size = PAGE_ALIGN(crash_size); 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci /* User specifies base address explicitly. */ 17262306a36Sopenharmony_ci if (crash_base) { 17362306a36Sopenharmony_ci fixed_base = true; 17462306a36Sopenharmony_ci search_base = crash_base; 17562306a36Sopenharmony_ci crash_max = crash_base + crash_size; 17662306a36Sopenharmony_ci } 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ciretry: 17962306a36Sopenharmony_ci crash_base = memblock_phys_alloc_range(crash_size, CRASH_ALIGN, 18062306a36Sopenharmony_ci search_base, crash_max); 18162306a36Sopenharmony_ci if (!crash_base) { 18262306a36Sopenharmony_ci /* 18362306a36Sopenharmony_ci * For crashkernel=size[KMG]@offset[KMG], print out failure 18462306a36Sopenharmony_ci * message if can't reserve the specified region. 18562306a36Sopenharmony_ci */ 18662306a36Sopenharmony_ci if (fixed_base) { 18762306a36Sopenharmony_ci pr_warn("crashkernel reservation failed - memory is in use.\n"); 18862306a36Sopenharmony_ci return; 18962306a36Sopenharmony_ci } 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ci /* 19262306a36Sopenharmony_ci * For crashkernel=size[KMG], if the first attempt was for 19362306a36Sopenharmony_ci * low memory, fall back to high memory, the minimum required 19462306a36Sopenharmony_ci * low memory will be reserved later. 19562306a36Sopenharmony_ci */ 19662306a36Sopenharmony_ci if (!high && crash_max == CRASH_ADDR_LOW_MAX) { 19762306a36Sopenharmony_ci crash_max = CRASH_ADDR_HIGH_MAX; 19862306a36Sopenharmony_ci search_base = CRASH_ADDR_LOW_MAX; 19962306a36Sopenharmony_ci crash_low_size = DEFAULT_CRASH_KERNEL_LOW_SIZE; 20062306a36Sopenharmony_ci goto retry; 20162306a36Sopenharmony_ci } 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci /* 20462306a36Sopenharmony_ci * For crashkernel=size[KMG],high, if the first attempt was 20562306a36Sopenharmony_ci * for high memory, fall back to low memory. 20662306a36Sopenharmony_ci */ 20762306a36Sopenharmony_ci if (high && crash_max == CRASH_ADDR_HIGH_MAX) { 20862306a36Sopenharmony_ci crash_max = CRASH_ADDR_LOW_MAX; 20962306a36Sopenharmony_ci search_base = 0; 21062306a36Sopenharmony_ci goto retry; 21162306a36Sopenharmony_ci } 21262306a36Sopenharmony_ci pr_warn("cannot allocate crashkernel (size:0x%llx)\n", 21362306a36Sopenharmony_ci crash_size); 21462306a36Sopenharmony_ci return; 21562306a36Sopenharmony_ci } 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci if ((crash_base >= CRASH_ADDR_LOW_MAX) && crash_low_size && 21862306a36Sopenharmony_ci reserve_crashkernel_low(crash_low_size)) { 21962306a36Sopenharmony_ci memblock_phys_free(crash_base, crash_size); 22062306a36Sopenharmony_ci return; 22162306a36Sopenharmony_ci } 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_ci pr_info("crashkernel reserved: 0x%016llx - 0x%016llx (%lld MB)\n", 22462306a36Sopenharmony_ci crash_base, crash_base + crash_size, crash_size >> 20); 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_ci /* 22762306a36Sopenharmony_ci * The crashkernel memory will be removed from the kernel linear 22862306a36Sopenharmony_ci * map. Inform kmemleak so that it won't try to access it. 22962306a36Sopenharmony_ci */ 23062306a36Sopenharmony_ci kmemleak_ignore_phys(crash_base); 23162306a36Sopenharmony_ci if (crashk_low_res.end) 23262306a36Sopenharmony_ci kmemleak_ignore_phys(crashk_low_res.start); 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci crashk_res.start = crash_base; 23562306a36Sopenharmony_ci crashk_res.end = crash_base + crash_size - 1; 23662306a36Sopenharmony_ci insert_resource(&iomem_resource, &crashk_res); 23762306a36Sopenharmony_ci} 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci/* 24062306a36Sopenharmony_ci * Return the maximum physical address for a zone accessible by the given bits 24162306a36Sopenharmony_ci * limit. If DRAM starts above 32-bit, expand the zone to the maximum 24262306a36Sopenharmony_ci * available memory, otherwise cap it at 32-bit. 24362306a36Sopenharmony_ci */ 24462306a36Sopenharmony_cistatic phys_addr_t __init max_zone_phys(unsigned int zone_bits) 24562306a36Sopenharmony_ci{ 24662306a36Sopenharmony_ci phys_addr_t zone_mask = DMA_BIT_MASK(zone_bits); 24762306a36Sopenharmony_ci phys_addr_t phys_start = memblock_start_of_DRAM(); 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci if (phys_start > U32_MAX) 25062306a36Sopenharmony_ci zone_mask = PHYS_ADDR_MAX; 25162306a36Sopenharmony_ci else if (phys_start > zone_mask) 25262306a36Sopenharmony_ci zone_mask = U32_MAX; 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ci return min(zone_mask, memblock_end_of_DRAM() - 1) + 1; 25562306a36Sopenharmony_ci} 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_cistatic void __init zone_sizes_init(void) 25862306a36Sopenharmony_ci{ 25962306a36Sopenharmony_ci unsigned long max_zone_pfns[MAX_NR_ZONES] = {0}; 26062306a36Sopenharmony_ci unsigned int __maybe_unused acpi_zone_dma_bits; 26162306a36Sopenharmony_ci unsigned int __maybe_unused dt_zone_dma_bits; 26262306a36Sopenharmony_ci phys_addr_t __maybe_unused dma32_phys_limit = max_zone_phys(32); 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_ci#ifdef CONFIG_ZONE_DMA 26562306a36Sopenharmony_ci acpi_zone_dma_bits = fls64(acpi_iort_dma_get_max_cpu_address()); 26662306a36Sopenharmony_ci dt_zone_dma_bits = fls64(of_dma_get_max_cpu_address(NULL)); 26762306a36Sopenharmony_ci zone_dma_bits = min3(32U, dt_zone_dma_bits, acpi_zone_dma_bits); 26862306a36Sopenharmony_ci arm64_dma_phys_limit = max_zone_phys(zone_dma_bits); 26962306a36Sopenharmony_ci max_zone_pfns[ZONE_DMA] = PFN_DOWN(arm64_dma_phys_limit); 27062306a36Sopenharmony_ci#endif 27162306a36Sopenharmony_ci#ifdef CONFIG_ZONE_DMA32 27262306a36Sopenharmony_ci max_zone_pfns[ZONE_DMA32] = PFN_DOWN(dma32_phys_limit); 27362306a36Sopenharmony_ci if (!arm64_dma_phys_limit) 27462306a36Sopenharmony_ci arm64_dma_phys_limit = dma32_phys_limit; 27562306a36Sopenharmony_ci#endif 27662306a36Sopenharmony_ci if (!arm64_dma_phys_limit) 27762306a36Sopenharmony_ci arm64_dma_phys_limit = PHYS_MASK + 1; 27862306a36Sopenharmony_ci max_zone_pfns[ZONE_NORMAL] = max_pfn; 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_ci free_area_init(max_zone_pfns); 28162306a36Sopenharmony_ci} 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_ciint pfn_is_map_memory(unsigned long pfn) 28462306a36Sopenharmony_ci{ 28562306a36Sopenharmony_ci phys_addr_t addr = PFN_PHYS(pfn); 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_ci /* avoid false positives for bogus PFNs, see comment in pfn_valid() */ 28862306a36Sopenharmony_ci if (PHYS_PFN(addr) != pfn) 28962306a36Sopenharmony_ci return 0; 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_ci return memblock_is_map_memory(addr); 29262306a36Sopenharmony_ci} 29362306a36Sopenharmony_ciEXPORT_SYMBOL(pfn_is_map_memory); 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_cistatic phys_addr_t memory_limit __ro_after_init = PHYS_ADDR_MAX; 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_ci/* 29862306a36Sopenharmony_ci * Limit the memory size that was specified via FDT. 29962306a36Sopenharmony_ci */ 30062306a36Sopenharmony_cistatic int __init early_mem(char *p) 30162306a36Sopenharmony_ci{ 30262306a36Sopenharmony_ci if (!p) 30362306a36Sopenharmony_ci return 1; 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_ci memory_limit = memparse(p, &p) & PAGE_MASK; 30662306a36Sopenharmony_ci pr_notice("Memory limited to %lldMB\n", memory_limit >> 20); 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ci return 0; 30962306a36Sopenharmony_ci} 31062306a36Sopenharmony_ciearly_param("mem", early_mem); 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_civoid __init arm64_memblock_init(void) 31362306a36Sopenharmony_ci{ 31462306a36Sopenharmony_ci s64 linear_region_size = PAGE_END - _PAGE_OFFSET(vabits_actual); 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci /* 31762306a36Sopenharmony_ci * Corner case: 52-bit VA capable systems running KVM in nVHE mode may 31862306a36Sopenharmony_ci * be limited in their ability to support a linear map that exceeds 51 31962306a36Sopenharmony_ci * bits of VA space, depending on the placement of the ID map. Given 32062306a36Sopenharmony_ci * that the placement of the ID map may be randomized, let's simply 32162306a36Sopenharmony_ci * limit the kernel's linear map to 51 bits as well if we detect this 32262306a36Sopenharmony_ci * configuration. 32362306a36Sopenharmony_ci */ 32462306a36Sopenharmony_ci if (IS_ENABLED(CONFIG_KVM) && vabits_actual == 52 && 32562306a36Sopenharmony_ci is_hyp_mode_available() && !is_kernel_in_hyp_mode()) { 32662306a36Sopenharmony_ci pr_info("Capping linear region to 51 bits for KVM in nVHE mode on LVA capable hardware.\n"); 32762306a36Sopenharmony_ci linear_region_size = min_t(u64, linear_region_size, BIT(51)); 32862306a36Sopenharmony_ci } 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_ci /* Remove memory above our supported physical address size */ 33162306a36Sopenharmony_ci memblock_remove(1ULL << PHYS_MASK_SHIFT, ULLONG_MAX); 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_ci /* 33462306a36Sopenharmony_ci * Select a suitable value for the base of physical memory. 33562306a36Sopenharmony_ci */ 33662306a36Sopenharmony_ci memstart_addr = round_down(memblock_start_of_DRAM(), 33762306a36Sopenharmony_ci ARM64_MEMSTART_ALIGN); 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_ci if ((memblock_end_of_DRAM() - memstart_addr) > linear_region_size) 34062306a36Sopenharmony_ci pr_warn("Memory doesn't fit in the linear mapping, VA_BITS too small\n"); 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_ci /* 34362306a36Sopenharmony_ci * Remove the memory that we will not be able to cover with the 34462306a36Sopenharmony_ci * linear mapping. Take care not to clip the kernel which may be 34562306a36Sopenharmony_ci * high in memory. 34662306a36Sopenharmony_ci */ 34762306a36Sopenharmony_ci memblock_remove(max_t(u64, memstart_addr + linear_region_size, 34862306a36Sopenharmony_ci __pa_symbol(_end)), ULLONG_MAX); 34962306a36Sopenharmony_ci if (memstart_addr + linear_region_size < memblock_end_of_DRAM()) { 35062306a36Sopenharmony_ci /* ensure that memstart_addr remains sufficiently aligned */ 35162306a36Sopenharmony_ci memstart_addr = round_up(memblock_end_of_DRAM() - linear_region_size, 35262306a36Sopenharmony_ci ARM64_MEMSTART_ALIGN); 35362306a36Sopenharmony_ci memblock_remove(0, memstart_addr); 35462306a36Sopenharmony_ci } 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci /* 35762306a36Sopenharmony_ci * If we are running with a 52-bit kernel VA config on a system that 35862306a36Sopenharmony_ci * does not support it, we have to place the available physical 35962306a36Sopenharmony_ci * memory in the 48-bit addressable part of the linear region, i.e., 36062306a36Sopenharmony_ci * we have to move it upward. Since memstart_addr represents the 36162306a36Sopenharmony_ci * physical address of PAGE_OFFSET, we have to *subtract* from it. 36262306a36Sopenharmony_ci */ 36362306a36Sopenharmony_ci if (IS_ENABLED(CONFIG_ARM64_VA_BITS_52) && (vabits_actual != 52)) 36462306a36Sopenharmony_ci memstart_addr -= _PAGE_OFFSET(48) - _PAGE_OFFSET(52); 36562306a36Sopenharmony_ci 36662306a36Sopenharmony_ci /* 36762306a36Sopenharmony_ci * Apply the memory limit if it was set. Since the kernel may be loaded 36862306a36Sopenharmony_ci * high up in memory, add back the kernel region that must be accessible 36962306a36Sopenharmony_ci * via the linear mapping. 37062306a36Sopenharmony_ci */ 37162306a36Sopenharmony_ci if (memory_limit != PHYS_ADDR_MAX) { 37262306a36Sopenharmony_ci memblock_mem_limit_remove_map(memory_limit); 37362306a36Sopenharmony_ci memblock_add(__pa_symbol(_text), (u64)(_end - _text)); 37462306a36Sopenharmony_ci } 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_ci if (IS_ENABLED(CONFIG_BLK_DEV_INITRD) && phys_initrd_size) { 37762306a36Sopenharmony_ci /* 37862306a36Sopenharmony_ci * Add back the memory we just removed if it results in the 37962306a36Sopenharmony_ci * initrd to become inaccessible via the linear mapping. 38062306a36Sopenharmony_ci * Otherwise, this is a no-op 38162306a36Sopenharmony_ci */ 38262306a36Sopenharmony_ci u64 base = phys_initrd_start & PAGE_MASK; 38362306a36Sopenharmony_ci u64 size = PAGE_ALIGN(phys_initrd_start + phys_initrd_size) - base; 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_ci /* 38662306a36Sopenharmony_ci * We can only add back the initrd memory if we don't end up 38762306a36Sopenharmony_ci * with more memory than we can address via the linear mapping. 38862306a36Sopenharmony_ci * It is up to the bootloader to position the kernel and the 38962306a36Sopenharmony_ci * initrd reasonably close to each other (i.e., within 32 GB of 39062306a36Sopenharmony_ci * each other) so that all granule/#levels combinations can 39162306a36Sopenharmony_ci * always access both. 39262306a36Sopenharmony_ci */ 39362306a36Sopenharmony_ci if (WARN(base < memblock_start_of_DRAM() || 39462306a36Sopenharmony_ci base + size > memblock_start_of_DRAM() + 39562306a36Sopenharmony_ci linear_region_size, 39662306a36Sopenharmony_ci "initrd not fully accessible via the linear mapping -- please check your bootloader ...\n")) { 39762306a36Sopenharmony_ci phys_initrd_size = 0; 39862306a36Sopenharmony_ci } else { 39962306a36Sopenharmony_ci memblock_add(base, size); 40062306a36Sopenharmony_ci memblock_clear_nomap(base, size); 40162306a36Sopenharmony_ci memblock_reserve(base, size); 40262306a36Sopenharmony_ci } 40362306a36Sopenharmony_ci } 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_ci if (IS_ENABLED(CONFIG_RANDOMIZE_BASE)) { 40662306a36Sopenharmony_ci extern u16 memstart_offset_seed; 40762306a36Sopenharmony_ci u64 mmfr0 = read_cpuid(ID_AA64MMFR0_EL1); 40862306a36Sopenharmony_ci int parange = cpuid_feature_extract_unsigned_field( 40962306a36Sopenharmony_ci mmfr0, ID_AA64MMFR0_EL1_PARANGE_SHIFT); 41062306a36Sopenharmony_ci s64 range = linear_region_size - 41162306a36Sopenharmony_ci BIT(id_aa64mmfr0_parange_to_phys_shift(parange)); 41262306a36Sopenharmony_ci 41362306a36Sopenharmony_ci /* 41462306a36Sopenharmony_ci * If the size of the linear region exceeds, by a sufficient 41562306a36Sopenharmony_ci * margin, the size of the region that the physical memory can 41662306a36Sopenharmony_ci * span, randomize the linear region as well. 41762306a36Sopenharmony_ci */ 41862306a36Sopenharmony_ci if (memstart_offset_seed > 0 && range >= (s64)ARM64_MEMSTART_ALIGN) { 41962306a36Sopenharmony_ci range /= ARM64_MEMSTART_ALIGN; 42062306a36Sopenharmony_ci memstart_addr -= ARM64_MEMSTART_ALIGN * 42162306a36Sopenharmony_ci ((range * memstart_offset_seed) >> 16); 42262306a36Sopenharmony_ci } 42362306a36Sopenharmony_ci } 42462306a36Sopenharmony_ci 42562306a36Sopenharmony_ci /* 42662306a36Sopenharmony_ci * Register the kernel text, kernel data, initrd, and initial 42762306a36Sopenharmony_ci * pagetables with memblock. 42862306a36Sopenharmony_ci */ 42962306a36Sopenharmony_ci memblock_reserve(__pa_symbol(_stext), _end - _stext); 43062306a36Sopenharmony_ci if (IS_ENABLED(CONFIG_BLK_DEV_INITRD) && phys_initrd_size) { 43162306a36Sopenharmony_ci /* the generic initrd code expects virtual addresses */ 43262306a36Sopenharmony_ci initrd_start = __phys_to_virt(phys_initrd_start); 43362306a36Sopenharmony_ci initrd_end = initrd_start + phys_initrd_size; 43462306a36Sopenharmony_ci } 43562306a36Sopenharmony_ci 43662306a36Sopenharmony_ci early_init_fdt_scan_reserved_mem(); 43762306a36Sopenharmony_ci 43862306a36Sopenharmony_ci high_memory = __va(memblock_end_of_DRAM() - 1) + 1; 43962306a36Sopenharmony_ci} 44062306a36Sopenharmony_ci 44162306a36Sopenharmony_civoid __init bootmem_init(void) 44262306a36Sopenharmony_ci{ 44362306a36Sopenharmony_ci unsigned long min, max; 44462306a36Sopenharmony_ci 44562306a36Sopenharmony_ci min = PFN_UP(memblock_start_of_DRAM()); 44662306a36Sopenharmony_ci max = PFN_DOWN(memblock_end_of_DRAM()); 44762306a36Sopenharmony_ci 44862306a36Sopenharmony_ci early_memtest(min << PAGE_SHIFT, max << PAGE_SHIFT); 44962306a36Sopenharmony_ci 45062306a36Sopenharmony_ci max_pfn = max_low_pfn = max; 45162306a36Sopenharmony_ci min_low_pfn = min; 45262306a36Sopenharmony_ci 45362306a36Sopenharmony_ci arch_numa_init(); 45462306a36Sopenharmony_ci 45562306a36Sopenharmony_ci /* 45662306a36Sopenharmony_ci * must be done after arch_numa_init() which calls numa_init() to 45762306a36Sopenharmony_ci * initialize node_online_map that gets used in hugetlb_cma_reserve() 45862306a36Sopenharmony_ci * while allocating required CMA size across online nodes. 45962306a36Sopenharmony_ci */ 46062306a36Sopenharmony_ci#if defined(CONFIG_HUGETLB_PAGE) && defined(CONFIG_CMA) 46162306a36Sopenharmony_ci arm64_hugetlb_cma_reserve(); 46262306a36Sopenharmony_ci#endif 46362306a36Sopenharmony_ci 46462306a36Sopenharmony_ci kvm_hyp_reserve(); 46562306a36Sopenharmony_ci 46662306a36Sopenharmony_ci /* 46762306a36Sopenharmony_ci * sparse_init() tries to allocate memory from memblock, so must be 46862306a36Sopenharmony_ci * done after the fixed reservations 46962306a36Sopenharmony_ci */ 47062306a36Sopenharmony_ci sparse_init(); 47162306a36Sopenharmony_ci zone_sizes_init(); 47262306a36Sopenharmony_ci 47362306a36Sopenharmony_ci /* 47462306a36Sopenharmony_ci * Reserve the CMA area after arm64_dma_phys_limit was initialised. 47562306a36Sopenharmony_ci */ 47662306a36Sopenharmony_ci dma_contiguous_reserve(arm64_dma_phys_limit); 47762306a36Sopenharmony_ci 47862306a36Sopenharmony_ci /* 47962306a36Sopenharmony_ci * request_standard_resources() depends on crashkernel's memory being 48062306a36Sopenharmony_ci * reserved, so do it here. 48162306a36Sopenharmony_ci */ 48262306a36Sopenharmony_ci reserve_crashkernel(); 48362306a36Sopenharmony_ci 48462306a36Sopenharmony_ci memblock_dump_all(); 48562306a36Sopenharmony_ci} 48662306a36Sopenharmony_ci 48762306a36Sopenharmony_ci/* 48862306a36Sopenharmony_ci * mem_init() marks the free areas in the mem_map and tells us how much memory 48962306a36Sopenharmony_ci * is free. This is done after various parts of the system have claimed their 49062306a36Sopenharmony_ci * memory after the kernel image. 49162306a36Sopenharmony_ci */ 49262306a36Sopenharmony_civoid __init mem_init(void) 49362306a36Sopenharmony_ci{ 49462306a36Sopenharmony_ci bool swiotlb = max_pfn > PFN_DOWN(arm64_dma_phys_limit); 49562306a36Sopenharmony_ci 49662306a36Sopenharmony_ci if (IS_ENABLED(CONFIG_DMA_BOUNCE_UNALIGNED_KMALLOC)) 49762306a36Sopenharmony_ci swiotlb = true; 49862306a36Sopenharmony_ci 49962306a36Sopenharmony_ci swiotlb_init(swiotlb, SWIOTLB_VERBOSE); 50062306a36Sopenharmony_ci 50162306a36Sopenharmony_ci /* this will put all unused low memory onto the freelists */ 50262306a36Sopenharmony_ci memblock_free_all(); 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_ci /* 50562306a36Sopenharmony_ci * Check boundaries twice: Some fundamental inconsistencies can be 50662306a36Sopenharmony_ci * detected at build time already. 50762306a36Sopenharmony_ci */ 50862306a36Sopenharmony_ci#ifdef CONFIG_COMPAT 50962306a36Sopenharmony_ci BUILD_BUG_ON(TASK_SIZE_32 > DEFAULT_MAP_WINDOW_64); 51062306a36Sopenharmony_ci#endif 51162306a36Sopenharmony_ci 51262306a36Sopenharmony_ci /* 51362306a36Sopenharmony_ci * Selected page table levels should match when derived from 51462306a36Sopenharmony_ci * scratch using the virtual address range and page size. 51562306a36Sopenharmony_ci */ 51662306a36Sopenharmony_ci BUILD_BUG_ON(ARM64_HW_PGTABLE_LEVELS(CONFIG_ARM64_VA_BITS) != 51762306a36Sopenharmony_ci CONFIG_PGTABLE_LEVELS); 51862306a36Sopenharmony_ci 51962306a36Sopenharmony_ci if (PAGE_SIZE >= 16384 && get_num_physpages() <= 128) { 52062306a36Sopenharmony_ci extern int sysctl_overcommit_memory; 52162306a36Sopenharmony_ci /* 52262306a36Sopenharmony_ci * On a machine this small we won't get anywhere without 52362306a36Sopenharmony_ci * overcommit, so turn it on by default. 52462306a36Sopenharmony_ci */ 52562306a36Sopenharmony_ci sysctl_overcommit_memory = OVERCOMMIT_ALWAYS; 52662306a36Sopenharmony_ci } 52762306a36Sopenharmony_ci} 52862306a36Sopenharmony_ci 52962306a36Sopenharmony_civoid free_initmem(void) 53062306a36Sopenharmony_ci{ 53162306a36Sopenharmony_ci free_reserved_area(lm_alias(__init_begin), 53262306a36Sopenharmony_ci lm_alias(__init_end), 53362306a36Sopenharmony_ci POISON_FREE_INITMEM, "unused kernel"); 53462306a36Sopenharmony_ci /* 53562306a36Sopenharmony_ci * Unmap the __init region but leave the VM area in place. This 53662306a36Sopenharmony_ci * prevents the region from being reused for kernel modules, which 53762306a36Sopenharmony_ci * is not supported by kallsyms. 53862306a36Sopenharmony_ci */ 53962306a36Sopenharmony_ci vunmap_range((u64)__init_begin, (u64)__init_end); 54062306a36Sopenharmony_ci} 54162306a36Sopenharmony_ci 54262306a36Sopenharmony_civoid dump_mem_limit(void) 54362306a36Sopenharmony_ci{ 54462306a36Sopenharmony_ci if (memory_limit != PHYS_ADDR_MAX) { 54562306a36Sopenharmony_ci pr_emerg("Memory Limit: %llu MB\n", memory_limit >> 20); 54662306a36Sopenharmony_ci } else { 54762306a36Sopenharmony_ci pr_emerg("Memory Limit: none\n"); 54862306a36Sopenharmony_ci } 54962306a36Sopenharmony_ci} 550