linux/drivers/of
Oreoluwa Babatunde 8a6e02d0c0 of: reserved_mem: Restructure how the reserved memory regions are processed
Reserved memory regions defined in the devicetree can be broken up into
two groups:
i) Statically-placed reserved memory regions
i.e. regions defined with a static start address and size using the
     "reg" property.
ii) Dynamically-placed reserved memory regions.
i.e. regions defined by specifying an address range where they can be
     placed in memory using the "alloc_ranges" and "size" properties.

These regions are processed and set aside at boot time.
This is done in two stages as seen below:

Stage 1:
At this stage, fdt_scan_reserved_mem() scans through the child nodes of
the reserved_memory node using the flattened devicetree and does the
following:

1) If the node represents a statically-placed reserved memory region,
   i.e. if it is defined using the "reg" property:
   - Call memblock_reserve() or memblock_mark_nomap() as needed.
   - Add the information for that region into the reserved_mem array
     using fdt_reserved_mem_save_node().
     i.e. fdt_reserved_mem_save_node(node, name, base, size).

2) If the node represents a dynamically-placed reserved memory region,
   i.e. if it is defined using "alloc-ranges" and "size" properties:
   - Add the information for that region to the reserved_mem array with
     the starting address and size set to 0.
     i.e. fdt_reserved_mem_save_node(node, name, 0, 0).
   Note: This region is saved to the array with a starting address of 0
   because a starting address is not yet allocated for it.

Stage 2:
After iterating through all the reserved memory nodes and storing their
relevant information in the reserved_mem array,fdt_init_reserved_mem() is
called and does the following:

1) For statically-placed reserved memory regions:
   - Call the region specific init function using
     __reserved_mem_init_node().
2) For dynamically-placed reserved memory regions:
   - Call __reserved_mem_alloc_size() which is used to allocate memory
     for each of these regions, and mark them as nomap if they have the
     nomap property specified in the DT.
   - Call the region specific init function.

The current size of the resvered_mem array is 64 as is defined by
MAX_RESERVED_REGIONS. This means that there is a limitation of 64 for
how many reserved memory regions can be specified on a system.
As systems continue to grow more and more complex, the number of
reserved memory regions needed are also growing and are starting to hit
this 64 count limit, hence the need to make the reserved_mem array
dynamically sized (i.e. dynamically allocating memory for the
reserved_mem array using membock_alloc_*).

On architectures such as arm64, memory allocated using memblock is
writable only after the page tables have been setup. This means that if
the reserved_mem array is going to be dynamically allocated, it needs to
happen after the page tables have been setup, not before.

Since the reserved memory regions are currently being processed and
added to the array before the page tables are setup, there is a need to
change the order in which some of the processing is done to allow for
the reserved_mem array to be dynamically sized.

It is possible to process the statically-placed reserved memory regions
without needing to store them in the reserved_mem array until after the
page tables have been setup because all the information stored in the
array is readily available in the devicetree and can be referenced at
any time.
Dynamically-placed reserved memory regions on the other hand get
assigned a start address only at runtime, and hence need a place to be
stored once they are allocated since there is no other referrence to the
start address for these regions.

Hence this patch changes the processing order of the reserved memory
regions in the following ways:

Step 1:
fdt_scan_reserved_mem() scans through the child nodes of
the reserved_memory node using the flattened devicetree and does the
following:

1) If the node represents a statically-placed reserved memory region,
   i.e. if it is defined using the "reg" property:
   - Call memblock_reserve() or memblock_mark_nomap() as needed.

2) If the node represents a dynamically-placed reserved memory region,
   i.e. if it is defined using "alloc-ranges" and "size" properties:
   - Call __reserved_mem_alloc_size() which will:
     i) Allocate memory for the reserved region and call
     memblock_mark_nomap() as needed.
     ii) Call the region specific initialization function using
     fdt_init_reserved_mem_node().
     iii) Save the region information in the reserved_mem array using
     fdt_reserved_mem_save_node().

Step 2:
1) This stage of the reserved memory processing is now only used to add
   the statically-placed reserved memory regions into the reserved_mem
   array using fdt_scan_reserved_mem_reg_nodes(), as well as call their
   region specific initialization functions.

2) This step has also been moved to be after the page tables are
   setup. Moving this will allow us to replace the reserved_mem
   array with a dynamically sized array before storing the rest of
   these regions.

Signed-off-by: Oreoluwa Babatunde <quic_obabatun@quicinc.com>
Link: https://lore.kernel.org/r/20241008220624.551309-2-quic_obabatun@quicinc.com
Signed-off-by: Rob Herring (Arm) <robh@kernel.org>
2024-10-15 10:34:15 -05:00
..
unittest-data of: Fix double free in of_parse_phandle_with_args_map 2024-01-09 12:54:02 -06:00
.kunitconfig of: Add a KUnit test for overlays and test managed APIs 2024-07-29 15:33:12 -07:00
address.c of/address: Constify of_busses[] array and pointers 2024-10-15 08:58:36 -05:00
base.c of: Constify struct property pointers 2024-10-15 08:58:36 -05:00
cpu.c of: Constify struct device_node function arguments 2024-10-15 08:58:36 -05:00
device.c OF: Simplify of_iommu_configure() 2024-07-04 14:36:04 +01:00
dynamic.c of: Constify of_changeset_entry function arguments 2024-10-15 08:58:36 -05:00
empty_root.dts of: Create of_root if no dtb provided by firmware 2024-03-08 12:50:39 -06:00
fdt_address.c
fdt.c of: reserved_mem: Restructure how the reserved memory regions are processed 2024-10-15 10:34:15 -05:00
irq.c of: Constify struct device_node function arguments 2024-10-15 08:58:36 -05:00
Kconfig of: Add a KUnit test for overlays and test managed APIs 2024-07-29 15:33:12 -07:00
kexec.c arm64, crash: wrap crash dumping code into crash related ifdefs 2024-02-23 17:48:23 -08:00
kobj.c of: Constify safe_name() kobject arg 2024-10-15 08:58:36 -05:00
kunit_overlay_test.dtso of: Add a KUnit test for overlays and test managed APIs 2024-07-29 15:33:12 -07:00
Makefile of: Add a KUnit test for overlays and test managed APIs 2024-07-29 15:33:12 -07:00
module.c Devicetree for v6.10: 2024-05-17 17:27:49 -07:00
of_kunit_helpers.c of: Add test managed wrappers for of_overlay_apply()/of_node_put() 2024-07-29 15:33:12 -07:00
of_numa.c of:of_numa: remove unused macro 2024-10-08 09:47:30 -05:00
of_private.h of: reserved_mem: Restructure how the reserved memory regions are processed 2024-10-15 10:34:15 -05:00
of_reserved_mem.c of: reserved_mem: Restructure how the reserved memory regions are processed 2024-10-15 10:34:15 -05:00
of_test.c of: of_test: add MODULE_DESCRIPTION() 2024-05-28 12:10:00 -05:00
overlay_test.c of: Add a KUnit test for overlays and test managed APIs 2024-07-29 15:33:12 -07:00
overlay.c of: Constify struct property pointers 2024-10-15 08:58:36 -05:00
pdt.c of: Remove struct device_node.type pointer 2019-01-10 16:24:44 -06:00
platform.c The core clk framework is left largely untouched this time around except for 2024-09-23 15:01:48 -07:00
property.c of: Constify struct property pointers 2024-10-15 08:58:36 -05:00
resolver.c of: Constify struct property pointers 2024-10-15 08:58:36 -05:00
unittest.c Kbuild updates for v6.12 2024-09-24 13:02:06 -07:00