[PATCH v2] arm: Support initrd with address in boot alias region
Matija Glavinic Pecotic
matija.glavinic-pecotic.ext at nokia.com
Thu Aug 18 01:39:39 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)
init/initramfs.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/init/initramfs.c b/init/initramfs.c
index 18229cfe8906..27c50910c55f 100644
--- a/init/initramfs.c
+++ b/init/initramfs.c
@@ -591,6 +591,21 @@ void __init reserve_initrd_mem(void)
if (!phys_initrd_size)
return;
+
+#ifdef CONFIG_ARM
+ /*
+ * 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);
+ }
+#endif
+
/*
* Round the memory region to page boundaries as per free_initrd_mem()
* This allows us to detect whether the pages overlapping the initrd
--
2.26.0
More information about the linux-arm-kernel
mailing list