lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20251117180435.GB225586-robh@kernel.org>
Date: Mon, 17 Nov 2025 12:04:35 -0600
From: Rob Herring <robh@...nel.org>
To: Gregory CLEMENT <gregory.clement@...tlin.com>
Cc: Saravana Kannan <saravanak@...gle.com>,
	Linus Walleij <linus.walleij@...aro.org>,
	Miquel Raynal <miquel.raynal@...tlin.com>,
	Richard Weinberger <richard@....at>,
	Vignesh Raghavendra <vigneshr@...com>,
	Krzysztof Kozlowski <krzk+dt@...nel.org>,
	Conor Dooley <conor+dt@...nel.org>,
	Thomas Petazzoni <thomas.petazzoni@...tlin.com>,
	Vladimir Kondratiev <vladimir.kondratiev@...ileye.com>,
	Benoît Monin <benoit.monin@...tlin.com>,
	Théo Lebrun <theo.lebrun@...tlin.com>,
	devicetree@...r.kernel.org, linux-kernel@...r.kernel.org,
	linux-arm-kernel@...ts.infradead.org, linux-mtd@...ts.infradead.org
Subject: Re: [PATCH 1/3] of: reserved_mem: Support multiple 'reg' entries for
 memory-region

On Mon, Nov 17, 2025 at 06:00:14PM +0100, Gregory CLEMENT wrote:
> The Device Tree specification allows a "memory-region" node to have
> multiple 'reg' entries, but the current kernel implementation only
> processes the first entry. This can lead to drivers not being able to
> access all the reserved memory regions specified in the Device Tree.
> 
> This patch extends the reserved memory handling to support multiple
> 'reg' entries for a single "memory-region" node. The existing exported
> functions remain unchanged for backward compatibility, but new APIs
> are introduced to allow drivers to access all reserved memory regions.
> 
> Signed-off-by: Gregory CLEMENT <gregory.clement@...tlin.com>
> ---
>  drivers/of/of_reserved_mem.c    | 141 ++++++++++++++++++++++++++++++++++++----
>  include/linux/of_reserved_mem.h |   4 ++
>  2 files changed, 133 insertions(+), 12 deletions(-)
> 
> diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c
> index 2e9ea751ed2df..2477933883903 100644
> --- a/drivers/of/of_reserved_mem.c
> +++ b/drivers/of/of_reserved_mem.c
> @@ -159,6 +159,7 @@ static int __init __reserved_mem_reserve_reg(unsigned long node,
>  	int len;
>  	const __be32 *prop;
>  	bool nomap;
> +	int count = 0;
>  
>  	prop = of_get_flat_dt_prop(node, "reg", &len);
>  	if (!prop)
> @@ -183,6 +184,7 @@ static int __init __reserved_mem_reserve_reg(unsigned long node,
>  				dma_contiguous_early_fixup(base, size);
>  			pr_debug("Reserved memory: reserved region for node '%s': base %pa, size %lu MiB\n",
>  				uname, &base, (unsigned long)(size / SZ_1M));
> +			count++;
>  		} else {
>  			pr_err("Reserved memory: failed to reserve memory for node '%s': base %pa, size %lu MiB\n",
>  			       uname, &base, (unsigned long)(size / SZ_1M));
> @@ -190,7 +192,7 @@ static int __init __reserved_mem_reserve_reg(unsigned long node,
>  
>  		len -= t_len;
>  	}
> -	return 0;
> +	return count;
>  }
>  
>  /*
> @@ -235,7 +237,7 @@ void __init fdt_scan_reserved_mem_reg_nodes(void)
>  	phys_addr_t base, size;
>  	const __be32 *prop;
>  	int node, child;
> -	int len;
> +	int len, i;
>  
>  	if (!fdt)
>  		return;
> @@ -273,12 +275,12 @@ void __init fdt_scan_reserved_mem_reg_nodes(void)
>  		if (len > t_len)
>  			pr_warn("%s() ignores %d regions in node '%s'\n",
>  				__func__, len / t_len - 1, uname);
> -
> -		base = dt_mem_next_cell(dt_root_addr_cells, &prop);
> -		size = dt_mem_next_cell(dt_root_size_cells, &prop);

FYI, there's some changes around this code in flight.

> -
> -		if (size)
> -			fdt_reserved_mem_save_node(child, uname, base, size);
> +		for (i = 0; i < len; i += t_len) {
> +			base = dt_mem_next_cell(dt_root_addr_cells, &prop);
> +			size = dt_mem_next_cell(dt_root_size_cells, &prop);
> +			if (size)
> +				fdt_reserved_mem_save_node(child, uname, base, size);
> +		}
>  	}
>  
>  	/* check for overlapping reserved regions */
> @@ -308,16 +310,16 @@ int __init fdt_scan_reserved_mem(void)
>  
>  	fdt_for_each_subnode(child, fdt, node) {
>  		const char *uname;
> -		int err;
> +		int err, ret;
>  
>  		if (!of_fdt_device_is_available(fdt, child))
>  			continue;
>  
>  		uname = fdt_get_name(fdt, child, NULL);
>  
> -		err = __reserved_mem_reserve_reg(child, uname);
> -		if (!err)
> -			count++;
> +		ret = __reserved_mem_reserve_reg(child, uname);
> +		if (ret > 0)
> +			count += ret;
>  		/*
>  		 * Save the nodes for the dynamically-placed regions
>  		 * into an array which will be used for allocation right
> @@ -750,6 +752,37 @@ struct reserved_mem *of_reserved_mem_lookup(struct device_node *np)
>  }
>  EXPORT_SYMBOL_GPL(of_reserved_mem_lookup);
>  
> +/**
> + * of_reserved_mem_array_lookup() - acquire reserved_mem array from a device node
> + * @np:		node pointer of the desired reserved-memory region
> + * @rmrm:	pointer to the first elemennt of the reserved_mem struct of the memory region
> + *
> + * This function allows drivers to acquire a reference to the array of the
> + *  reserved_mem struct based on a device node handle.
> + *
> + * Returns the number reserved_mem elements
> + */
> +int of_reserved_mem_array_lookup(struct device_node *np,
> +				 struct reserved_mem **rmem)
> +{
> +	const char *name;
> +	int i, count = 0;
> +
> +	if (!np->full_name)
> +		return 0;
> +
> +	name = kbasename(np->full_name);
> +	for (i = 0; i < reserved_mem_count; i++)
> +		if (!strcmp(reserved_mem[i].name, name)) {
> +			if (!count)
> +				*rmem = &reserved_mem[i];
> +			count++;
> +		}
> +
> +	return count;
> +}
> +EXPORT_SYMBOL_GPL(of_reserved_mem_array_lookup);

Do you need this function? I'm trying to do away with drivers using 
struct reserved_mem in favor of the resource functions.

> +
>  /**
>   * of_reserved_mem_region_to_resource() - Get a reserved memory region as a resource
>   * @np:		node containing 'memory-region' property
> @@ -785,6 +818,49 @@ int of_reserved_mem_region_to_resource(const struct device_node *np,
>  }
>  EXPORT_SYMBOL_GPL(of_reserved_mem_region_to_resource);
>  
> +/**
> + * of_reserved_mem_region_to_resource_array() - Get a reserved memory region as a resources
> + * @dev:	device associated to the node
> + * @np:		node containing 'memory-region' property
> + * @idx:	index of 'memory-region' property to lookup
> + * @res:	Pointer to an array of struct resource pointers to fill in with reserved regions
> + *
> + * This function allows drivers to lookup a node's 'memory-region' property
> + * entries by index and fill an array of struct resource pointers for the entries.
> + *
> + * Returns the number of resources filled in @res on success.
> + * Returns -ENODEV if 'memory-region' is missing or unavailable,
> + * -EINVAL for any other error.
> + */
> +int of_reserved_mem_region_to_resource_array(struct device *dev, const struct device_node *np,
> +					     unsigned int idx, struct resource **res)
> +{
> +	struct reserved_mem *rmem;
> +	int count, i;
> +	struct resource *r;
> +
> +	if (!np)
> +		return -EINVAL;
> +
> +	struct device_node __free(device_node) *target = of_parse_phandle(np, "memory-region", idx);
> +	if (!target || !of_device_is_available(target))
> +		return -ENODEV;
> +
> +	count = of_reserved_mem_array_lookup(target, &rmem);
> +	if (count <= 0)
> +		return -EINVAL;
> +
> +	*res = devm_kzalloc(dev, count * sizeof(struct resource), GFP_KERNEL);
> +	r = res[0];
> +	for (i = 0; i < count; i++) {
> +		resource_set_range(&r[i], rmem[i].base, rmem[i].size);
> +		r[i].flags = IORESOURCE_MEM;
> +		r[i].name = rmem[i].name;
> +	}
> +	return count;
> +}
> +EXPORT_SYMBOL_GPL(of_reserved_mem_region_to_resource_array);
> +
>  /**
>   * of_reserved_mem_region_to_resource_byname() - Get a reserved memory region as a resource
>   * @np:		node containing 'memory-region' property
> @@ -829,3 +905,44 @@ int of_reserved_mem_region_count(const struct device_node *np)
>  	return of_count_phandle_with_args(np, "memory-region", NULL);
>  }
>  EXPORT_SYMBOL_GPL(of_reserved_mem_region_count);
> +
> +/**
> + * of_reserved_mem_region_count() - Return the total number of reserved memory regions
> + * @np:		node containing 'memory-region' property
> + *
> + * This function counts the total number of reserved memory regions referenced
> + * by a node's 'memory-region' property. It iterates over each phandle and sums
> + * the number of regions found in each referenced reserved memory node.
> + *
> + * Returns the total number of reserved memory regions on success.
> + * This function allows drivers to retrieve the number of entries for a node's
> + * 'memory-region' property.
> + *
> + * Returns total number of reserved memory regions on success, or negative error
> + * code on a malformed property.
> + */
> +int of_reserved_mem_region_total_count(const struct device_node *np)
> +{
> +	int nregion = of_count_phandle_with_args(np, "memory-region", NULL);
> +	struct device_node *target;
> +	int i, nregs = 0;
> +
> +	for (i = 0; i < nregion; i++) {
> +		struct reserved_mem *rmem;
> +
> +		target = of_parse_phandle(np, "memory-region", i);
> +		if (!target)
> +			return -ENODEV;
> +
> +		if (!of_device_is_available(target)) {
> +			of_node_put(target);
> +			return 0;
> +		}
> +
> +		nregs += of_reserved_mem_array_lookup(target, &rmem);
> +
> +		of_node_put(target);
> +	};
> +	return nregs;
> +}
> +EXPORT_SYMBOL_GPL(of_reserved_mem_region_total_count);

Do you have a user?

Rob

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ