[PATCH 1/2] ARM: take memreserve FDT entries into account when discovering base of RAM

Ard Biesheuvel ardb at kernel.org
Mon Jan 11 05:30:19 EST 2021


As an enhancement to the newly added logic to cross-reference the base
of DRAM calculated by rounding the decompressor load address against the
memory nodes in the DT, take /memreserve/ entries into account as well.

This ensures that DT platforms that currently rely on TEXT_OFFSET to be
increased in order to stay clear of memory reservations no longer need
this hack in the future.

Signed-off-by: Ard Biesheuvel <ardb at kernel.org>
---
 arch/arm/boot/compressed/Makefile              |  2 ++
 arch/arm/boot/compressed/fdt_check_mem_start.c | 35 +++++++++++++++++++-
 2 files changed, 36 insertions(+), 1 deletion(-)

diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile
index fd94e27ba4fa..cf8cfe3f286c 100644
--- a/arch/arm/boot/compressed/Makefile
+++ b/arch/arm/boot/compressed/Makefile
@@ -96,6 +96,8 @@ endif
 $(foreach o, $(libfdt_objs) atags_to_fdt.o fdt_check_mem_start.o, \
 	$(eval CFLAGS_$(o) := -I $(srctree)/scripts/dtc/libfdt -fno-stack-protector))
 
+CFLAGS_fdt_check_mem_start.o += -DTEXT_OFFSET=$(TEXT_OFFSET)
+
 # These were previously generated C files. When you are building the kernel
 # with O=, make sure to remove the stale files in the output tree. Otherwise,
 # the build system wrongly compiles the stale ones.
diff --git a/arch/arm/boot/compressed/fdt_check_mem_start.c b/arch/arm/boot/compressed/fdt_check_mem_start.c
index 62450d824c3c..f81ed6ae9776 100644
--- a/arch/arm/boot/compressed/fdt_check_mem_start.c
+++ b/arch/arm/boot/compressed/fdt_check_mem_start.c
@@ -4,6 +4,19 @@
 #include <linux/libfdt.h>
 #include <linux/sizes.h>
 
+/*
+ * The ARM kernel only uses part of the 32 KiB TEXT_OFFSET window at the start
+ * of the uncompressed image, and some platforms rely on this, and have placed
+ * reserved regions right before it. This means we should only consider an
+ * overlap to be a collision if the reserved region covers the area that we
+ * actually use for page tables.
+ */
+#ifdef CONFIG_ARM_LPAE
+#define TEXT_OFFSET_FREE	(TEXT_OFFSET - 0x5000)
+#else
+#define TEXT_OFFSET_FREE	(TEXT_OFFSET - 0x4000)
+#endif
+
 static const void *get_prop(const void *fdt, const char *node_path,
 			    const char *property, int minlen)
 {
@@ -44,6 +57,24 @@ static uint64_t get_val(const fdt32_t *cells, uint32_t ncells)
 	return r;
 }
 
+static void clip_reserved_regions(const void *fdt, uint32_t *base, uint64_t *end)
+{
+	int i;
+
+	for (i = 0; i < fdt_num_mem_rsv(fdt); i++) {
+		uint64_t address, size;
+
+		if (fdt_get_mem_rsv(fdt, i, &address, &size))
+			return;
+
+		if (*base >= address && *base < (address + size))
+			*base = address + size;
+
+		if (*end >= address && *end < (address + size))
+			*end = address;
+	}
+}
+
 /*
  * Check the start of physical memory
  *
@@ -107,7 +138,9 @@ uint32_t fdt_check_mem_start(uint32_t mem_start, const void *fdt)
 
 			base = fdt32_ld(reg + addr_cells - 1);
 			end = base + size;
-			if (mem_start >= base && mem_start < end) {
+			clip_reserved_regions(fdt, &base, &end);
+			if (mem_start + TEXT_OFFSET_FREE >= base &&
+			    mem_start < end) {
 				/* Calculated address is valid, use it */
 				return mem_start;
 			}
-- 
2.17.1




More information about the linux-arm-kernel mailing list