[PATCH v3] arm: Support initrd with address in boot alias region
Matija Glavinic Pecotic
matija.glavinic-pecotic.ext at nokia.com
Thu Aug 18 07:52:22 PDT 2022
When bootloader passes address of initrd in boot alias region, initrd
will fail on memblock_is_region_memory as memblock with such address
doesn't exist. Problem was uncovered by commit fe7db7570379 ("of/fdt:
Populate phys_initrd_start/phys_initrd_size from FDT") which removed
__virt_to_phys on the initrd physical address. Earlier, __virt_to_phys
on our platform coincidentally sanitized address.
Initrd address in bootalias region is valid to be passed by bootloader,
in our case it was done by kexec:
$ cat /proc/iomem
[cut]
c0000000-d4da1fff : System RAM (boot alias)
840000000-854da1fff : System RAM
840008000-840bfffff : Kernel code
840e00000-840ee56fb : Kernel data
[cut]
880000000-8ffffffff : System RAM
arch/arm/kernel/setup.c:
/*
* Some systems have a special memory alias which is only
* used for booting. We need to advertise this region to
* kexec-tools so they know where bootable RAM is located.
*/
boot_alias_start = phys_to_idmap(start);
if (arm_has_idmap_alias() && boot_alias_start != IDMAP_INVALID_ADDR) {
res = memblock_alloc(sizeof(*res), SMP_CACHE_BYTES);
if (!res)
panic("%s: Failed to allocate %zu bytes\n",
__func__, sizeof(*res));
res->name = "System RAM (boot alias)";
res->start = boot_alias_start;
res->end = phys_to_idmap(res_end);
res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
request_resource(&iomem_resource, res);
}
Fix by trying to sanitize address in case of invalid physical address
for platforms (e.g. Keystone 2) supporting it.
Signed-off-by: Matija Glavinic Pecotic <matija.glavinic-pecotic.ext at nokia.com>
---
v2: Rebased against current tree, update commit message to capture
previous discussion (http://lists.infradead.org/pipermail/linux-arm-kernel/2020-September/605344.html)
v3: moved implementation from generic code to arm's mm
arch/arm/mm/init.c | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index ce64bdb55a16..b248c2459f4d 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -180,11 +180,27 @@ void check_cpu_icache_size(int cpuid)
}
#endif
+static void sanitize_initrd_address(void)
+{
+ /*
+ * If initrd is not on valid physical address, reason could
+ * be due to bootloader passing address from bootalias region.
+ * Try to sanitize such address for platforms supporting boot
+ * aliases.
+ */
+ if (!pfn_valid(__phys_to_pfn(phys_initrd_start))) {
+ pr_info("initrd at invalid address, trying to use boot alias\n");
+ if (arm_has_idmap_alias())
+ phys_initrd_start = idmap_to_phys(phys_initrd_start);
+ }
+}
+
void __init arm_memblock_init(const struct machine_desc *mdesc)
{
/* Register the kernel text, kernel data and initrd with memblock. */
memblock_reserve(__pa(KERNEL_START), KERNEL_END - KERNEL_START);
+ sanitize_initrd_address();
reserve_initrd_mem();
arm_mm_memblock_reserve();
--
2.26.0
More information about the linux-arm-kernel
mailing list