[PATCH v2 3/3] of: request reserved memory regions so other code can't

Ahmad Fatoum a.fatoum at pengutronix.de
Thu Jun 9 04:18:10 PDT 2022


Add a new of_reserved_mem_walk that can be used to request
reserved memory regions. This avoids e.g. bootm trying to
place the kernel into a reserved region.

Signed-off-by: Rouven Czerwinski <r.czerwinski at pengutronix.de>
Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
v1 -> v2:
  - don't use of_reserve_entry accounting and instead
    directly request memory (Sascha)
---
 common/memory.c           | 21 ++++++++++--
 drivers/of/Makefile       |  1 +
 drivers/of/reserved-mem.c | 71 +++++++++++++++++++++++++++++++++++++++
 include/of.h              |  9 +++++
 4 files changed, 99 insertions(+), 3 deletions(-)
 create mode 100644 drivers/of/reserved-mem.c

diff --git a/common/memory.c b/common/memory.c
index 95995bb6e310..fd782c7f24f6 100644
--- a/common/memory.c
+++ b/common/memory.c
@@ -3,6 +3,8 @@
  * Copyright (c) 2011 Sascha Hauer <s.hauer at pengutronix.de>, Pengutronix
  */
 
+#define pr_fmt(fmt) "memory: " fmt
+
 #include <common.h>
 #include <memory.h>
 #include <of.h>
@@ -12,6 +14,7 @@
 #include <asm-generic/memory_layout.h>
 #include <asm/sections.h>
 #include <malloc.h>
+#include <of.h>
 
 /*
  * Begin and End of memory area for malloc(), and current "brk"
@@ -53,9 +56,20 @@ void mem_malloc_init(void *start, void *end)
 	mem_malloc_initialized = 1;
 }
 
-#if !defined __SANDBOX__
+static int request_reservation(const struct resource *res)
+{
+	if (!(res->flags & IORESOURCE_EXCLUSIVE))
+		return 0;
+
+	pr_debug("region %s %pa-%pa\n", res->name, &res->start, &res->end);
+
+	request_sdram_region(res->name, res->start, resource_size(res));
+	return 0;
+}
+
 static int mem_malloc_resource(void)
 {
+#if !defined __SANDBOX__
 	/*
 	 * Normally it's a bug when one of these fails,
 	 * but we have some setups where some of these
@@ -77,13 +91,14 @@ static int mem_malloc_resource(void)
 			(unsigned long)&__bss_start,
 			(unsigned long)&__bss_stop -
 			(unsigned long)&__bss_start);
+#endif
 #ifdef STACK_BASE
 	request_sdram_region("stack", STACK_BASE, STACK_SIZE);
 #endif
-	return 0;
+
+	return of_reserved_mem_walk(request_reservation);
 }
 coredevice_initcall(mem_malloc_resource);
-#endif
 
 static void *sbrk_no_zero(ptrdiff_t increment)
 {
diff --git a/drivers/of/Makefile b/drivers/of/Makefile
index ca8da71cb4f0..99b610cba85e 100644
--- a/drivers/of/Makefile
+++ b/drivers/of/Makefile
@@ -5,6 +5,7 @@ obj-$(CONFIG_OF_GPIO) += of_gpio.o
 obj-$(CONFIG_OF_PCI) += of_pci.o
 obj-y += partition.o
 obj-y += of_net.o
+obj-$(CONFIG_OFDEVICE) += reserved-mem.o
 obj-$(CONFIG_MTD) += of_mtd.o
 obj-$(CONFIG_OF_BAREBOX_DRIVERS) += barebox.o
 obj-$(CONFIG_OF_OVERLAY) += overlay.o resolver.o of_firmware.o
diff --git a/drivers/of/reserved-mem.c b/drivers/of/reserved-mem.c
new file mode 100644
index 000000000000..34e61dfea343
--- /dev/null
+++ b/drivers/of/reserved-mem.c
@@ -0,0 +1,71 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// SPDX-FileCopyrightText: 2021 Rouven Czerwinski <r.czerwinski at pengutronix.de>, Pengutronix
+
+#include <stdio.h>
+#include <of.h>
+#include <of_address.h>
+
+#define MEMRESERVE_NCELLS	2
+#define MEMRESERVE_FLAGS	(IORESOURCE_MEM | IORESOURCE_EXCLUSIVE)
+
+int of_reserved_mem_walk(int (*handler)(const struct resource *res))
+{
+	struct device_node *node, *child;
+	int ncells = 0;
+	const __be32 *reg;
+	int ret;
+
+	node = of_find_node_by_path("/reserved-memory");
+	if (node) {
+		for_each_available_child_of_node(node, child) {
+			struct resource resource = {};
+
+			/* skip e.g. linux,cma */
+			if (!of_get_property(child, "reg", NULL))
+				continue;
+
+			of_address_to_resource(child, 0, &resource);
+
+			resource.name = child->name;
+			resource.flags = MEMRESERVE_FLAGS;
+
+			ret = handler(&resource);
+			if (ret)
+				return ret;
+		}
+	}
+
+	node = of_find_node_by_path("/memreserve");
+	reg = of_get_property(node, "reg", &ncells);
+	ncells /= sizeof(__be32);
+	if (reg) {
+		char name[sizeof "fdt-memreserve-4294967295"];
+		int i = 0, n = 0;
+
+		while (i < ncells) {
+			struct resource resource = {};
+			u64 size;
+
+			snprintf(name, sizeof(name), "fdt-memreserve-%u", n++);
+			resource.name = name;
+			resource.flags = MEMRESERVE_FLAGS;
+
+			resource.start = of_read_number(reg + i, MEMRESERVE_NCELLS);
+			i += MEMRESERVE_NCELLS;
+
+			size = of_read_number(reg + i, MEMRESERVE_NCELLS);
+			i += MEMRESERVE_NCELLS;
+
+			if (!size)
+				continue;
+
+			resource.end = resource.start + size - 1;
+
+			ret = handler(&resource);
+			if (ret)
+				return ret;
+		}
+	}
+
+	return 0;
+}
diff --git a/include/of.h b/include/of.h
index 46b96277d581..c0b715924a18 100644
--- a/include/of.h
+++ b/include/of.h
@@ -64,6 +64,7 @@ void fdt_add_reserve_map(void *fdt);
 
 struct device_d;
 struct driver_d;
+struct resource;
 
 int of_fix_tree(struct device_node *);
 
@@ -317,6 +318,9 @@ struct device_node *of_find_node_by_path_or_alias(struct device_node *root,
 int of_autoenable_device_by_path(char *path);
 int of_autoenable_i2c_by_component(char *path);
 int of_prepend_machine_compatible(struct device_node *root, const char *compat);
+
+int of_reserved_mem_walk(int (*handler)(const struct resource *res));
+
 #else
 static inline bool of_node_name_eq(const struct device_node *np, const char *name)
 {
@@ -841,6 +845,11 @@ static inline int of_prepend_machine_compatible(struct device_node *root,
 	return -ENODEV;
 }
 
+static inline int of_reserved_mem_walk(int (*handler)(const struct resource *res))
+{
+	return 0;
+}
+
 #endif
 
 #define for_each_property_of_node(dn, pp) \
-- 
2.30.2




More information about the barebox mailing list