[PATCH] arm: Adjust memory boundaries after reservations
Nicolas Pitre
nicolas.pitre at linaro.org
Wed Dec 14 13:50:02 PST 2016
On Tue, 13 Dec 2016, Laura Abbott wrote:
> The poorly named sanity_check_meminfo is responsible for setting up the
> boundary for lowmem/highmem. This needs to be set up before memblock
> reservations can occur. At the time memblock reservations can occur,
> memory can also be removed from the system. This can throw off the
> calculation of the lowmem/highmem boundary. On some systems this may be
> harmless, on others this may result in incorrect ranges being passed to
> the main memory allocator. Correct this by recalcuating the
> lowmem/highmem boundary after all reservations have been made.
> As part of this, rename sanity_check_meminfo to actually refect what the
> function is doing.
>
> Reported-by: Magnus Lilja <lilja.magnus at gmail.com>
> Signed-off-by: Laura Abbott <labbott at redhat.com>
Acked-by: Nicolas Pitre <nico at linaro.org>
> ---
> The particular issue I reproduced for
> https://marc.info/?l=linux-arm-kernel&m=148145259511248 involved the lowmem
> boundary being greater than the end of ram thanks to the memblock_steal.
> The re-calcuation should have no effect unless memory was actually removed
> from the system. Putting it in arm_memblock_steal doesn't cover all cases
> either since the devicetree memory map can also remove memory.
> ---
> arch/arm/kernel/setup.c | 12 ++++++++++--
> arch/arm/mm/mmu.c | 15 +++++++++------
> arch/arm/mm/nommu.c | 2 +-
> 3 files changed, 20 insertions(+), 9 deletions(-)
>
> diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
> index 34e3f3c..62f91bd 100644
> --- a/arch/arm/kernel/setup.c
> +++ b/arch/arm/kernel/setup.c
> @@ -81,7 +81,7 @@ __setup("fpe=", fpe_setup);
> extern void init_default_cache_policy(unsigned long);
> extern void paging_init(const struct machine_desc *desc);
> extern void early_paging_init(const struct machine_desc *);
> -extern void sanity_check_meminfo(void);
> +extern void update_memory_bounds(void);
> extern enum reboot_mode reboot_mode;
> extern void setup_dma_zone(const struct machine_desc *desc);
>
> @@ -1093,8 +1093,16 @@ void __init setup_arch(char **cmdline_p)
> setup_dma_zone(mdesc);
> xen_early_init();
> efi_init();
> - sanity_check_meminfo();
> + /*
> + * We need to make sure the calculation for lowmem/highmem is set
> + * appropriately before reserving/allocating any memory
> + */
> + update_memory_bounds();
> arm_memblock_init(mdesc);
> + /*
> + * Memory may have been removed so the bounds need to be recalcuated.
> + */
> + update_memory_bounds();
>
> early_ioremap_reset();
>
> diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
> index 4001dd1..666e789 100644
> --- a/arch/arm/mm/mmu.c
> +++ b/arch/arm/mm/mmu.c
> @@ -1152,13 +1152,14 @@ early_param("vmalloc", early_vmalloc);
>
> phys_addr_t arm_lowmem_limit __initdata = 0;
>
> -void __init sanity_check_meminfo(void)
> +void __init update_memory_bounds(void)
> {
> phys_addr_t memblock_limit = 0;
> int highmem = 0;
> u64 vmalloc_limit;
> struct memblock_region *reg;
> bool should_use_highmem = false;
> + phys_addr_t lowmem_limit = 0;
>
> /*
> * Let's use our own (unoptimized) equivalent of __pa() that is
> @@ -1196,18 +1197,18 @@ void __init sanity_check_meminfo(void)
> pr_notice("Truncating RAM at %pa-%pa",
> &block_start, &block_end);
> block_end = vmalloc_limit;
> - pr_cont(" to -%pa", &block_end);
> + pr_cont(" to -%pa\n", &block_end);
> memblock_remove(vmalloc_limit, overlap_size);
> should_use_highmem = true;
> }
> }
>
> if (!highmem) {
> - if (block_end > arm_lowmem_limit) {
> + if (block_end > lowmem_limit) {
> if (reg->size > size_limit)
> - arm_lowmem_limit = vmalloc_limit;
> + lowmem_limit = vmalloc_limit;
> else
> - arm_lowmem_limit = block_end;
> + lowmem_limit = block_end;
> }
>
> /*
> @@ -1227,12 +1228,14 @@ void __init sanity_check_meminfo(void)
> if (!IS_ALIGNED(block_start, PMD_SIZE))
> memblock_limit = block_start;
> else if (!IS_ALIGNED(block_end, PMD_SIZE))
> - memblock_limit = arm_lowmem_limit;
> + memblock_limit = lowmem_limit;
> }
>
> }
> }
>
> + arm_lowmem_limit = lowmem_limit;
> +
> if (should_use_highmem)
> pr_notice("Consider using a HIGHMEM enabled kernel.\n");
>
> diff --git a/arch/arm/mm/nommu.c b/arch/arm/mm/nommu.c
> index 2740967..e5bc874 100644
> --- a/arch/arm/mm/nommu.c
> +++ b/arch/arm/mm/nommu.c
> @@ -295,7 +295,7 @@ void __init arm_mm_memblock_reserve(void)
> #endif
> }
>
> -void __init sanity_check_meminfo(void)
> +void __init update_memory_bounds(void)
> {
> phys_addr_t end;
> sanity_check_meminfo_mpu();
> --
> 2.7.4
>
>
More information about the linux-arm-kernel
mailing list