X-Git-Url: http://git.monstr.eu/?p=linux-2.6-microblaze.git;a=blobdiff_plain;f=arch%2Farm64%2Fmm%2Finit.c;fp=arch%2Farm64%2Fmm%2Finit.c;h=37a81754d9b61f7a47fa3b29f0fd4159fddf3608;hp=5a16f57157161c0f5b59a8e9e60447bd3b20827d;hb=e99f23c5bf59219d0cd9b6e0d7d4c1b641a98704;hpb=85f58eb1889826b9745737718723a80b639e0fbd diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c index 5a16f5715716..37a81754d9b6 100644 --- a/arch/arm64/mm/init.c +++ b/arch/arm64/mm/init.c @@ -75,6 +75,7 @@ phys_addr_t arm64_dma_phys_limit __ro_after_init; static void __init reserve_crashkernel(void) { unsigned long long crash_base, crash_size; + unsigned long long crash_max = arm64_dma_phys_limit; int ret; ret = parse_crashkernel(boot_command_line, memblock_phys_mem_size(), @@ -85,33 +86,18 @@ static void __init reserve_crashkernel(void) crash_size = PAGE_ALIGN(crash_size); - if (crash_base == 0) { - /* Current arm64 boot protocol requires 2MB alignment */ - crash_base = memblock_find_in_range(0, arm64_dma_phys_limit, - crash_size, SZ_2M); - if (crash_base == 0) { - pr_warn("cannot allocate crashkernel (size:0x%llx)\n", - crash_size); - return; - } - } else { - /* User specifies base address explicitly. */ - if (!memblock_is_region_memory(crash_base, crash_size)) { - pr_warn("cannot reserve crashkernel: region is not memory\n"); - return; - } - - if (memblock_is_region_reserved(crash_base, crash_size)) { - pr_warn("cannot reserve crashkernel: region overlaps reserved memory\n"); - return; - } + /* User specifies base address explicitly. */ + if (crash_base) + crash_max = crash_base + crash_size; - if (!IS_ALIGNED(crash_base, SZ_2M)) { - pr_warn("cannot reserve crashkernel: base address is not 2MB aligned\n"); - return; - } + /* Current arm64 boot protocol requires 2MB alignment */ + crash_base = memblock_phys_alloc_range(crash_size, SZ_2M, + crash_base, crash_max); + if (!crash_base) { + pr_warn("cannot allocate crashkernel (size:0x%llx)\n", + crash_size); + return; } - memblock_reserve(crash_base, crash_size); pr_info("crashkernel reserved: 0x%016llx - 0x%016llx (%lld MB)\n", crash_base, crash_base + crash_size, crash_size >> 20); @@ -130,57 +116,6 @@ static void __init reserve_crashkernel(void) } #endif /* CONFIG_KEXEC_CORE */ -#ifdef CONFIG_CRASH_DUMP -static int __init early_init_dt_scan_elfcorehdr(unsigned long node, - const char *uname, int depth, void *data) -{ - const __be32 *reg; - int len; - - if (depth != 1 || strcmp(uname, "chosen") != 0) - return 0; - - reg = of_get_flat_dt_prop(node, "linux,elfcorehdr", &len); - if (!reg || (len < (dt_root_addr_cells + dt_root_size_cells))) - return 1; - - elfcorehdr_addr = dt_mem_next_cell(dt_root_addr_cells, ®); - elfcorehdr_size = dt_mem_next_cell(dt_root_size_cells, ®); - - return 1; -} - -/* - * reserve_elfcorehdr() - reserves memory for elf core header - * - * This function reserves the memory occupied by an elf core header - * described in the device tree. This region contains all the - * information about primary kernel's core image and is used by a dump - * capture kernel to access the system memory on primary kernel. - */ -static void __init reserve_elfcorehdr(void) -{ - of_scan_flat_dt(early_init_dt_scan_elfcorehdr, NULL); - - if (!elfcorehdr_size) - return; - - if (memblock_is_region_reserved(elfcorehdr_addr, elfcorehdr_size)) { - pr_warn("elfcorehdr is overlapped\n"); - return; - } - - memblock_reserve(elfcorehdr_addr, elfcorehdr_size); - - pr_info("Reserving %lldKB of memory at 0x%llx for elfcorehdr\n", - elfcorehdr_size >> 10, elfcorehdr_addr); -} -#else -static void __init reserve_elfcorehdr(void) -{ -} -#endif /* CONFIG_CRASH_DUMP */ - /* * Return the maximum physical address for a zone accessible by the given bits * limit. If DRAM starts above 32-bit, expand the zone to the maximum @@ -225,6 +160,43 @@ static void __init zone_sizes_init(unsigned long min, unsigned long max) free_area_init(max_zone_pfns); } +int pfn_valid(unsigned long pfn) +{ + phys_addr_t addr = PFN_PHYS(pfn); + struct mem_section *ms; + + /* + * Ensure the upper PAGE_SHIFT bits are clear in the + * pfn. Else it might lead to false positives when + * some of the upper bits are set, but the lower bits + * match a valid pfn. + */ + if (PHYS_PFN(addr) != pfn) + return 0; + + if (pfn_to_section_nr(pfn) >= NR_MEM_SECTIONS) + return 0; + + ms = __pfn_to_section(pfn); + if (!valid_section(ms)) + return 0; + + /* + * ZONE_DEVICE memory does not have the memblock entries. + * memblock_is_map_memory() check for ZONE_DEVICE based + * addresses will always fail. Even the normal hotplugged + * memory will never have MEMBLOCK_NOMAP flag set in their + * memblock entries. Skip memblock search for all non early + * memory sections covering all of hotplug memory including + * both normal and ZONE_DEVICE based. + */ + if (!early_section(ms)) + return pfn_section_valid(ms, pfn); + + return memblock_is_memory(addr); +} +EXPORT_SYMBOL(pfn_valid); + int pfn_is_map_memory(unsigned long pfn) { phys_addr_t addr = PFN_PHYS(pfn); @@ -254,38 +226,6 @@ static int __init early_mem(char *p) } early_param("mem", early_mem); -static int __init early_init_dt_scan_usablemem(unsigned long node, - const char *uname, int depth, void *data) -{ - struct memblock_region *usablemem = data; - const __be32 *reg; - int len; - - if (depth != 1 || strcmp(uname, "chosen") != 0) - return 0; - - reg = of_get_flat_dt_prop(node, "linux,usable-memory-range", &len); - if (!reg || (len < (dt_root_addr_cells + dt_root_size_cells))) - return 1; - - usablemem->base = dt_mem_next_cell(dt_root_addr_cells, ®); - usablemem->size = dt_mem_next_cell(dt_root_size_cells, ®); - - return 1; -} - -static void __init fdt_enforce_memory_region(void) -{ - struct memblock_region reg = { - .size = 0, - }; - - of_scan_flat_dt(early_init_dt_scan_usablemem, ®); - - if (reg.size) - memblock_cap_memory_range(reg.base, reg.size); -} - void __init arm64_memblock_init(void) { s64 linear_region_size = PAGE_END - _PAGE_OFFSET(vabits_actual); @@ -304,9 +244,6 @@ void __init arm64_memblock_init(void) linear_region_size = min_t(u64, linear_region_size, BIT(51)); } - /* Handle linux,usable-memory-range property */ - fdt_enforce_memory_region(); - /* Remove memory above our supported physical address size */ memblock_remove(1ULL << PHYS_MASK_SHIFT, ULLONG_MAX); @@ -415,8 +352,6 @@ void __init arm64_memblock_init(void) early_init_fdt_scan_reserved_mem(); - reserve_elfcorehdr(); - high_memory = __va(memblock_end_of_DRAM() - 1) + 1; }