arm64: add the initrd region to the linear mapping explicitly
[cascardo/linux.git] / arch / arm64 / mm / init.c
index 61a38ea..82ced5f 100644 (file)
@@ -190,8 +190,12 @@ void __init arm64_memblock_init(void)
         */
        memblock_remove(max_t(u64, memstart_addr + linear_region_size, __pa(_end)),
                        ULLONG_MAX);
-       if (memblock_end_of_DRAM() > linear_region_size)
-               memblock_remove(0, memblock_end_of_DRAM() - linear_region_size);
+       if (memstart_addr + linear_region_size < memblock_end_of_DRAM()) {
+               /* ensure that memstart_addr remains sufficiently aligned */
+               memstart_addr = round_up(memblock_end_of_DRAM() - linear_region_size,
+                                        ARM64_MEMSTART_ALIGN);
+               memblock_remove(0, memstart_addr);
+       }
 
        /*
         * Apply the memory limit if it was set. Since the kernel may be loaded
@@ -203,6 +207,35 @@ void __init arm64_memblock_init(void)
                memblock_add(__pa(_text), (u64)(_end - _text));
        }
 
+       if (IS_ENABLED(CONFIG_BLK_DEV_INITRD) && initrd_start) {
+               /*
+                * Add back the memory we just removed if it results in the
+                * initrd to become inaccessible via the linear mapping.
+                * Otherwise, this is a no-op
+                */
+               u64 base = initrd_start & PAGE_MASK;
+               u64 size = PAGE_ALIGN(initrd_end) - base;
+
+               /*
+                * We can only add back the initrd memory if we don't end up
+                * with more memory than we can address via the linear mapping.
+                * It is up to the bootloader to position the kernel and the
+                * initrd reasonably close to each other (i.e., within 32 GB of
+                * each other) so that all granule/#levels combinations can
+                * always access both.
+                */
+               if (WARN(base < memblock_start_of_DRAM() ||
+                        base + size > memblock_start_of_DRAM() +
+                                      linear_region_size,
+                       "initrd not fully accessible via the linear mapping -- please check your bootloader ...\n")) {
+                       initrd_start = 0;
+               } else {
+                       memblock_remove(base, size); /* clear MEMBLOCK_ flags */
+                       memblock_add(base, size);
+                       memblock_reserve(base, size);
+               }
+       }
+
        if (IS_ENABLED(CONFIG_RANDOMIZE_BASE)) {
                extern u16 memstart_offset_seed;
                u64 range = linear_region_size -
@@ -362,42 +395,38 @@ void __init mem_init(void)
 #define MLG(b, t) b, t, ((t) - (b)) >> 30
 #define MLK_ROUNDUP(b, t) b, t, DIV_ROUND_UP(((t) - (b)), SZ_1K)
 
-       pr_notice("Virtual kernel memory layout:\n"
-#ifdef CONFIG_KASAN
-                 "    kasan   : 0x%16lx - 0x%16lx   (%6ld GB)\n"
-#endif
-                 "    modules : 0x%16lx - 0x%16lx   (%6ld MB)\n"
-                 "    vmalloc : 0x%16lx - 0x%16lx   (%6ld GB)\n"
-                 "      .text : 0x%p" " - 0x%p" "   (%6ld KB)\n"
-                 "    .rodata : 0x%p" " - 0x%p" "   (%6ld KB)\n"
-                 "      .init : 0x%p" " - 0x%p" "   (%6ld KB)\n"
-                 "      .data : 0x%p" " - 0x%p" "   (%6ld KB)\n"
-#ifdef CONFIG_SPARSEMEM_VMEMMAP
-                 "    vmemmap : 0x%16lx - 0x%16lx   (%6ld GB maximum)\n"
-                 "              0x%16lx - 0x%16lx   (%6ld MB actual)\n"
-#endif
-                 "    fixed   : 0x%16lx - 0x%16lx   (%6ld KB)\n"
-                 "    PCI I/O : 0x%16lx - 0x%16lx   (%6ld MB)\n"
-                 "    memory  : 0x%16lx - 0x%16lx   (%6ld MB)\n",
+       pr_notice("Virtual kernel memory layout:\n");
 #ifdef CONFIG_KASAN
-                 MLG(KASAN_SHADOW_START, KASAN_SHADOW_END),
+       pr_cont("    kasan   : 0x%16lx - 0x%16lx   (%6ld GB)\n",
+               MLG(KASAN_SHADOW_START, KASAN_SHADOW_END));
 #endif
-                 MLM(MODULES_VADDR, MODULES_END),
-                 MLG(VMALLOC_START, VMALLOC_END),
-                 MLK_ROUNDUP(_text, __start_rodata),
-                 MLK_ROUNDUP(__start_rodata, _etext),
-                 MLK_ROUNDUP(__init_begin, __init_end),
-                 MLK_ROUNDUP(_sdata, _edata),
+       pr_cont("    modules : 0x%16lx - 0x%16lx   (%6ld MB)\n",
+               MLM(MODULES_VADDR, MODULES_END));
+       pr_cont("    vmalloc : 0x%16lx - 0x%16lx   (%6ld GB)\n",
+               MLG(VMALLOC_START, VMALLOC_END));
+       pr_cont("      .text : 0x%p" " - 0x%p" "   (%6ld KB)\n"
+               "    .rodata : 0x%p" " - 0x%p" "   (%6ld KB)\n"
+               "      .init : 0x%p" " - 0x%p" "   (%6ld KB)\n"
+               "      .data : 0x%p" " - 0x%p" "   (%6ld KB)\n",
+               MLK_ROUNDUP(_text, __start_rodata),
+               MLK_ROUNDUP(__start_rodata, _etext),
+               MLK_ROUNDUP(__init_begin, __init_end),
+               MLK_ROUNDUP(_sdata, _edata));
 #ifdef CONFIG_SPARSEMEM_VMEMMAP
-                 MLG(VMEMMAP_START,
-                     VMEMMAP_START + VMEMMAP_SIZE),
-                 MLM((unsigned long)phys_to_page(memblock_start_of_DRAM()),
-                     (unsigned long)virt_to_page(high_memory)),
+       pr_cont("    vmemmap : 0x%16lx - 0x%16lx   (%6ld GB maximum)\n"
+               "              0x%16lx - 0x%16lx   (%6ld MB actual)\n",
+               MLG(VMEMMAP_START,
+                   VMEMMAP_START + VMEMMAP_SIZE),
+               MLM((unsigned long)phys_to_page(memblock_start_of_DRAM()),
+                   (unsigned long)virt_to_page(high_memory)));
 #endif
-                 MLK(FIXADDR_START, FIXADDR_TOP),
-                 MLM(PCI_IO_START, PCI_IO_END),
-                 MLM(__phys_to_virt(memblock_start_of_DRAM()),
-                     (unsigned long)high_memory));
+       pr_cont("    fixed   : 0x%16lx - 0x%16lx   (%6ld KB)\n",
+               MLK(FIXADDR_START, FIXADDR_TOP));
+       pr_cont("    PCI I/O : 0x%16lx - 0x%16lx   (%6ld MB)\n",
+               MLM(PCI_IO_START, PCI_IO_END));
+       pr_cont("    memory  : 0x%16lx - 0x%16lx   (%6ld MB)\n",
+               MLM(__phys_to_virt(memblock_start_of_DRAM()),
+                   (unsigned long)high_memory));
 
 #undef MLK
 #undef MLM