arm64: respect mem= for EFI
authorMark Rutland <mark.rutland@arm.com>
Thu, 15 Jan 2015 16:42:14 +0000 (16:42 +0000)
committerAlex Shi <alex.shi@linaro.org>
Thu, 23 Apr 2015 06:44:35 +0000 (14:44 +0800)
When booting with EFI, we acquire the EFI memory map after parsing the
early params. This unfortuantely renders the option useless as we call
memblock_enforce_memory_limit (which uses memblock_remove_range behind
the scenes) before we've added any memblocks. We end up removing
nothing, then adding all of memory later when efi_init calls
reserve_regions.

Instead, we can log the limit and apply this later when we do the rest
of the memblock work in memblock_init, which should work regardless of
the presence of EFI. At the same time we may as well move the early
parameter into arm64's mm/init.c, close to arm64_memblock_init.

Any memory which must be mapped (e.g. for use by EFI runtime services)
must be mapped explicitly reather than relying on the linear mapping,
which may be truncated as a result of a mem= option passed on the kernel
command line.

Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Acked-by: Catalin Marinas <catalin.marinas@arm.com>
Acked-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Tested-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Leif Lindholm <leif.lindholm@linaro.org>
Cc: Will Deacon <will.deacon@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
(cherry picked from commit 6083fe74b7bfffc2c7be8c711596608bda0cda6e)
Signed-off-by: Alex Shi <alex.shi@linaro.org>
arch/arm64/kernel/setup.c
arch/arm64/mm/init.c

index 97676952b2699452a02f86135515ee7eedd61d5e..9d704df65a6a4e79727a27b049a1d26066c6842c 100644 (file)
@@ -369,25 +369,6 @@ void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align)
        return __va(memblock_alloc(size, align));
 }
 
-/*
- * Limit the memory size that was specified via FDT.
- */
-static int __init early_mem(char *p)
-{
-       phys_addr_t limit;
-
-       if (!p)
-               return 1;
-
-       limit = memparse(p, &p) & PAGE_MASK;
-       pr_notice("Memory limited to %lldMB\n", limit >> 20);
-
-       memblock_enforce_memory_limit(limit);
-
-       return 0;
-}
-early_param("mem", early_mem);
-
 static void __init request_standard_resources(void)
 {
        struct memblock_region *region;
index d0f86b74fce65fc8e7f2b4675fdc6aa3940a1972..f2bded0254c32a4aa4692fd4b022582a6e1c6bbb 100644 (file)
@@ -141,11 +141,30 @@ static void arm64_memory_present(void)
 }
 #endif
 
+static phys_addr_t memory_limit = (phys_addr_t)ULLONG_MAX;
+
+/*
+ * Limit the memory size that was specified via FDT.
+ */
+static int __init early_mem(char *p)
+{
+       if (!p)
+               return 1;
+
+       memory_limit = memparse(p, &p) & PAGE_MASK;
+       pr_notice("Memory limited to %lldMB\n", memory_limit >> 20);
+
+       return 0;
+}
+early_param("mem", early_mem);
+
 void __init arm64_memblock_init(void)
 {
        u64 *reserve_map, base, size;
        phys_addr_t dma_phys_limit = 0;
 
+       memblock_enforce_memory_limit(memory_limit);
+
        /*
         * Register the kernel text, kernel data, initrd, and initial
         * pagetables with memblock.