Re: [PATCH 2/2] of: reserved_mem: allocate and map the reserved_mem array early
From: Rob Herring
Date: Thu Oct 08 2026 - 10:05:28 EST
On Thu, Oct 08, 2026 at 11:41:23AM +0200, Marek Szyprowski wrote:
> Get rid of the static, limited-size reserved_mem array and replace it
> with array allocated by memblock_alloc_raw() and accessed through a
> temporary early_memremap() mapping. Such mapping is needed for some
> architectures (like ARM64), where linear map is not yet available during
> early boot scan. Having a single, writeable array with all reserved
> regions removes the need to perform two step initialization introduced
> by commit 8a6e02d0c00e ("of: reserved_mem: Restructure how the reserved
> memory regions are processed"), so all regions can be processed
> directly during the early scan again.
>
> Suggested-by: Mike Rapoport <rppt@xxxxxxxxxx>
> Link: https://lore.kernel.org/all/asc6brs_g0ky0wOM@xxxxxxxxxx/
> Assisted-By: Claude Opus 5.5 <noreply@xxxxxxxxxxxxx>
Assisted-by: LLM
is the new way...
> Signed-off-by: Marek Szyprowski <m.szyprowski@xxxxxxxxxxx>
> ---
> drivers/of/fdt.c | 3 -
> drivers/of/of_private.h | 2 -
> drivers/of/of_reserved_mem.c | 251 ++++++++++++++---------------------
> 3 files changed, 96 insertions(+), 160 deletions(-)
>
> diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
> index ecc923102622..a58efdcbac7f 100644
> --- a/drivers/of/fdt.c
> +++ b/drivers/of/fdt.c
> @@ -1283,9 +1283,6 @@ void __init unflatten_device_tree(void)
> {
> void *fdt = initial_boot_params;
>
> - /* Save the statically-placed regions in the reserved_mem array */
> - fdt_scan_reserved_mem_late();
> -
> /* Populate an empty root node when bootloader doesn't provide one */
> if (!fdt) {
> fdt = (void *) __dtb_empty_root_begin;
> diff --git a/drivers/of/of_private.h b/drivers/of/of_private.h
> index 0ae16da066e2..895f868b4cfa 100644
> --- a/drivers/of/of_private.h
> +++ b/drivers/of/of_private.h
> @@ -9,7 +9,6 @@
> */
>
> #define FDT_ALIGN_SIZE 8
> -#define MAX_RESERVED_REGIONS 64
>
> /**
> * struct alias_prop - Alias property in 'aliases' node
> @@ -186,7 +185,6 @@ static inline struct device_node *__of_get_dma_parent(const struct device_node *
> #endif
>
> int fdt_scan_reserved_mem(void);
> -void __init fdt_scan_reserved_mem_late(void);
>
> bool of_fdt_device_is_available(const void *blob, unsigned long node);
>
> diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c
> index 300fb236ab59..6a5e53243bb7 100644
> --- a/drivers/of/of_reserved_mem.c
> +++ b/drivers/of/of_reserved_mem.c
> @@ -24,12 +24,14 @@
> #include <linux/slab.h>
> #include <linux/memblock.h>
> #include <linux/kmemleak.h>
> +#ifdef CONFIG_GENERIC_EARLY_IOREMAP
> +#include <asm/early_ioremap.h>
> +#endif
These ifdefs are the only thing I don't like. early_ioremap.h is always
in asm-generic, so do we need the ifdef here? Or does the arch have to
do something to pick it up? I don't remember.
>
> #include "of_private.h"
>
> -static struct reserved_mem reserved_mem_array[MAX_RESERVED_REGIONS] __initdata;
> -static struct reserved_mem *reserved_mem __refdata = reserved_mem_array;
> -static int total_reserved_mem_cnt = MAX_RESERVED_REGIONS;
> +static struct reserved_mem *reserved_mem __refdata;
> +static int total_reserved_mem_cnt;
> static int reserved_mem_count;
>
> static int __init early_init_dt_alloc_reserved_memory_arch(phys_addr_t size,
> @@ -59,56 +61,48 @@ static int __init early_init_dt_alloc_reserved_memory_arch(phys_addr_t size,
> }
>
> /*
> - * alloc_reserved_mem_array() - allocate memory for the reserved_mem
> - * array using memblock
> + * reserved_mem_array_map() - make the freshly allocated reserved_mem array
> + * accessible during early boot
> *
> - * This function is used to allocate memory for the reserved_mem
> - * array according to the total number of reserved memory regions
> - * defined in the DT.
> - * After the new array is allocated, the information stored in
> - * the initial static array is copied over to this new array and
> - * the new array is used from this point on.
> + * On some architectures (i.e. arm64) the linear mapping is not yet usable when
> + * the reserved memory regions are scanned, so the array has to be accessed
> + * through a temporary early mapping.
> */
> -static int __init alloc_reserved_mem_array(void)
> +static struct reserved_mem * __init reserved_mem_array_map(struct reserved_mem *array,
> + size_t size)
> {
> - struct reserved_mem *new_array;
> - size_t alloc_size, copy_size, memset_size;
> - int ret;
> +#ifdef CONFIG_GENERIC_EARLY_IOREMAP
This could at least be:
if (IS_ENABLED(CONFIG_GENERIC_EARLY_IOREMAP))
return early_memremap(__pa(array), size);
else
return array;
Assuming the header can always be included...
> + return early_memremap(__pa(array), size);
> +#else
> + return array;
> +#endif
> +}