From 5d2793a61aded9602af86e90a571f64ff07f93b3 Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Mon, 19 Apr 2021 17:25:53 +0100 Subject: [PATCH] fix(rpi4): drop /memreserve/ region Most DTBs used on the RaspberryPi contain a FDT /memreserve/ region, that covers the original secondaries' spin table. We need to reserve more memory than described there, to cover the whole of the TF-A image, so we add a /reserved-memory node to the DTB. However having the same memory region described by both methods upsets the Linux kernel and U-Boot, so we have to make sure there is only one instance describing this reserved memory. Keep our currently used /reserved-memory node, since it's more capable (it allows to mark the region as secure memory). Add some code to drop the original /memreserve/ region, since we don't need this anymore, because we take the secondaries out of their original spin loop. We explicitly check for the currently used size of 4KB for this region, to be alerted by any changes to this region in the upstream DTB. Change-Id: Ia3105560deb3f939e026f6ed715a9bbe68b56230 Signed-off-by: Andre Przywara --- plat/rpi/rpi4/rpi4_bl31_setup.c | 44 ++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/plat/rpi/rpi4/rpi4_bl31_setup.c b/plat/rpi/rpi4/rpi4_bl31_setup.c index cfacd1fe1..525985913 100644 --- a/plat/rpi/rpi4/rpi4_bl31_setup.c +++ b/plat/rpi/rpi4/rpi4_bl31_setup.c @@ -201,6 +201,44 @@ void bl31_plat_arch_setup(void) enable_mmu_el3(0); } +/* + * Remove the FDT /memreserve/ entry that covers the region at the very + * beginning of memory (if that exists). This is where the secondaries + * originally spin, but we pull them out there. + * Having overlapping /reserved-memory and /memreserve/ regions confuses + * the Linux kernel, so we need to get rid of this one. + */ +static void remove_spintable_memreserve(void *dtb) +{ + uint64_t addr, size; + int regions = fdt_num_mem_rsv(dtb); + int i; + + for (i = 0; i < regions; i++) { + if (fdt_get_mem_rsv(dtb, i, &addr, &size) != 0) { + return; + } + if (size == 0U) { + return; + } + /* We only look for the region at the beginning of DRAM. */ + if (addr != 0U) { + continue; + } + /* + * Currently the region in the existing DTs is exactly 4K + * in size. Should this value ever change, there is probably + * a reason for that, so inform the user about this. + */ + if (size == 4096U) { + fdt_del_mem_rsv(dtb, i); + return; + } + WARN("Keeping unknown /memreserve/ region at 0, size: %lld\n", + size); + } +} + static void rpi4_prepare_dtb(void) { void *dtb = (void *)rpi4_get_dtb_address(); @@ -227,7 +265,11 @@ static void rpi4_prepare_dtb(void) return; } - /* Reserve memory used by Trusted Firmware. */ + /* + * Remove the original reserved region (used for the spintable), and + * replace it with a region describing the whole of Trusted Firmware. + */ + remove_spintable_memreserve(dtb); if (fdt_add_reserved_memory(dtb, "atf@0", 0, 0x80000)) WARN("Failed to add reserved memory nodes to DT.\n");