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@xxxxxxxxxxxxxx> --- .../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@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