[PATCH 05/11] of: platform: remap memory when encountering virtual-reg property

Ahmad Fatoum a.fatoum at pengutronix.de
Sun May 21 22:28:29 PDT 2023


Quoting the Device Tree specification v0.4-rc1[1]:

  The virtual-reg property specifies an effective address that maps to the
  first physical address specified in the reg property of the device node.
  This property enables boot programs to provide client programs with virtual-
  to-physical mappings that have been set up.

The only upstream use of this device tree property are some PowerPC
device trees that use it to find the virtual address of the early UART.

Let's start handling this property in barebox as well by remapping the
device to start at virtual-reg.

[1]: https://github.com/devicetree-org/devicetree-specification/releases/tag/v0.4-rc1

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 .../bindings/barebox/virtual-reg.rst          | 29 +++++++++++++++++++
 drivers/mtd/nor/cfi_flash.c                   |  5 +++-
 drivers/of/platform.c                         | 20 +++++++++++++
 3 files changed, 53 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/barebox/virtual-reg.rst

diff --git a/Documentation/devicetree/bindings/barebox/virtual-reg.rst b/Documentation/devicetree/bindings/barebox/virtual-reg.rst
new file mode 100644
index 000000000000..7d576d0cef6f
--- /dev/null
+++ b/Documentation/devicetree/bindings/barebox/virtual-reg.rst
@@ -0,0 +1,29 @@
+virtual-reg property
+====================
+
+The ``virtual-reg`` property provides a hint on the 32-bit virtual
+address mapping the first physical base address in the ``reg`` property.
+This is meant to allow the OS to use the boot firmware's virtual memory
+mapping to access device resources early in the kernel boot process.
+
+When barebox is compiled with ``CONFIG_MMU`` support and the
+implementation supports remapping, devices with ``virtual_reg`` will have
+all their resources remapped at the physical/virtual address offset calculated
+by subtracting ``virtual-reg`` from the first address in ``reg``.
+
+This is normally used to map I/O memory away from the zero page, so it
+can be used again to trap null pointer dereferences, while allowing
+full access to the device memory::
+
+.. code-block:: none
+
+   &{/soc} {
+   	#address-cells = <1>;
+   	#size-cells = <1>;
+
+        flash at 0 {
+             reg = <0 0x10000>;
+             virtual-reg = <0x1000>;
+	     /* => memory region remapped from [0x1000, 0x11000] to [0x0000, 0x10000] */
+        };
+  };
diff --git a/drivers/mtd/nor/cfi_flash.c b/drivers/mtd/nor/cfi_flash.c
index b7499c93aee4..10542c710118 100644
--- a/drivers/mtd/nor/cfi_flash.c
+++ b/drivers/mtd/nor/cfi_flash.c
@@ -973,7 +973,10 @@ static int cfi_probe_one(struct flash_info *info, int num)
 		return PTR_ERR(iores);
 	info->base = IOMEM(iores->start);
 
-	/* TODO: either remap memory region or disable NULL pointer page */
+	/*
+	 * Platforms hitting this should remap memory region, e.g. via virtual-reg
+	 * device tree property or disable MMU.
+	 */
 	if (IS_ENABLED(CONFIG_MMU) && iores->start == 0)
 		return -EPERM;
 
diff --git a/drivers/of/platform.c b/drivers/of/platform.c
index 23b8fa79348b..ab737629325a 100644
--- a/drivers/of/platform.c
+++ b/drivers/of/platform.c
@@ -12,6 +12,7 @@
 #include <of.h>
 #include <of_address.h>
 #include <linux/amba/bus.h>
+#include <mmu.h>
 
 /**
  * of_find_device_by_node - Find the platform_device associated with a node
@@ -145,6 +146,7 @@ struct device *of_platform_device_create(struct device_node *np,
 	struct resource *res = NULL, temp_res;
 	resource_size_t resinval;
 	int i, ret, num_reg = 0;
+	u32 virt;
 
 	if (!of_device_is_available(np))
 		return NULL;
@@ -186,6 +188,24 @@ struct device *of_platform_device_create(struct device_node *np,
 
 	of_dma_configure(dev, np);
 
+	if (num_reg && !of_property_read_u32(np, "virtual-reg", &virt)) {
+		resource_size_t remap_offset = virt - res[0].start;
+
+		for (i = 0; i < num_reg; i++) {
+			void *new_virt = (void *)res[i].start + remap_offset;
+			resource_size_t size = resource_size(&res[i]);
+
+			ret = arch_remap_range(new_virt, res[i].start, size, MAP_UNCACHED);
+			if (!ret) {
+				debug("%s: remap device %s resource %d: %pa -> 0x%p\n",
+				      __func__, dev_name(dev), i, &res[i].start, new_virt);
+
+				res[i].start = (resource_size_t)new_virt;
+				res[i].end = res[i].start + size - 1;
+			}
+		}
+	}
+
 	resinval = (-1);
 
 	debug("%s: register device %s, io=%pa\n",
-- 
2.39.2




More information about the barebox mailing list