Skip to content

Commit 00c9a45

Browse files
Oreoluwa Babatunderobherring
authored andcommitted
of: reserved_mem: Add code to dynamically allocate reserved_mem array
The reserved_mem array is statically allocated with a size of MAX_RESERVED_REGIONS(64). Therefore, if the number of reserved_mem regions exceeds this size, there will not be enough space to store all the data. Hence, extend the use of the static array by introducing a dynamically allocated array based on the number of reserved memory regions specified in the DT. On architectures such as arm64, memblock allocated memory is not writable until after the page tables have been setup. Hence, the dynamic allocation of the reserved_mem array will need to be done only after the page tables have been setup. As a result, a temporary static array is still needed in the initial stages to store the information of the dynamically-placed reserved memory regions because the start address is selected only at run-time and is not stored anywhere else. It is not possible to wait until the reserved_mem array is allocated because this is done after the page tables are setup and the reserved memory regions need to be initialized before then. After the reserved_mem array is allocated, all entries from the static array is copied over to the new array, and the rest of the information for the statically-placed reserved memory regions are read in from the DT and stored in the new array as well. Once the init process is completed, the temporary static array is released back to the system because it is no longer needed. This is achieved by marking it as __initdata. Signed-off-by: Oreoluwa Babatunde <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Rob Herring (Arm) <[email protected]>
1 parent 8a6e02d commit 00c9a45

File tree

1 file changed

+59
-4
lines changed

1 file changed

+59
-4
lines changed

drivers/of/of_reserved_mem.c

Lines changed: 59 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@
2727

2828
#include "of_private.h"
2929

30-
static struct reserved_mem reserved_mem[MAX_RESERVED_REGIONS];
30+
static struct reserved_mem reserved_mem_array[MAX_RESERVED_REGIONS] __initdata;
31+
static struct reserved_mem *reserved_mem __refdata = reserved_mem_array;
32+
static int total_reserved_mem_cnt = MAX_RESERVED_REGIONS;
3133
static int reserved_mem_count;
3234

3335
static int __init early_init_dt_alloc_reserved_memory_arch(phys_addr_t size,
@@ -55,6 +57,50 @@ static int __init early_init_dt_alloc_reserved_memory_arch(phys_addr_t size,
5557
return err;
5658
}
5759

60+
/*
61+
* alloc_reserved_mem_array() - allocate memory for the reserved_mem
62+
* array using memblock
63+
*
64+
* This function is used to allocate memory for the reserved_mem
65+
* array according to the total number of reserved memory regions
66+
* defined in the DT.
67+
* After the new array is allocated, the information stored in
68+
* the initial static array is copied over to this new array and
69+
* the new array is used from this point on.
70+
*/
71+
static void __init alloc_reserved_mem_array(void)
72+
{
73+
struct reserved_mem *new_array;
74+
size_t alloc_size, copy_size, memset_size;
75+
76+
alloc_size = array_size(total_reserved_mem_cnt, sizeof(*new_array));
77+
if (alloc_size == SIZE_MAX) {
78+
pr_err("Failed to allocate memory for reserved_mem array with err: %d", -EOVERFLOW);
79+
return;
80+
}
81+
82+
new_array = memblock_alloc(alloc_size, SMP_CACHE_BYTES);
83+
if (!new_array) {
84+
pr_err("Failed to allocate memory for reserved_mem array with err: %d", -ENOMEM);
85+
return;
86+
}
87+
88+
copy_size = array_size(reserved_mem_count, sizeof(*new_array));
89+
if (copy_size == SIZE_MAX) {
90+
memblock_free(new_array, alloc_size);
91+
total_reserved_mem_cnt = MAX_RESERVED_REGIONS;
92+
pr_err("Failed to allocate memory for reserved_mem array with err: %d", -EOVERFLOW);
93+
return;
94+
}
95+
96+
memset_size = alloc_size - copy_size;
97+
98+
memcpy(new_array, reserved_mem, copy_size);
99+
memset(new_array + reserved_mem_count, 0, memset_size);
100+
101+
reserved_mem = new_array;
102+
}
103+
58104
static void __init fdt_init_reserved_mem_node(struct reserved_mem *rmem);
59105
/*
60106
* fdt_reserved_mem_save_node() - save fdt node for second pass initialization
@@ -64,7 +110,7 @@ static void __init fdt_reserved_mem_save_node(unsigned long node, const char *un
64110
{
65111
struct reserved_mem *rmem = &reserved_mem[reserved_mem_count];
66112

67-
if (reserved_mem_count == ARRAY_SIZE(reserved_mem)) {
113+
if (reserved_mem_count == total_reserved_mem_cnt) {
68114
pr_err("not enough space for all defined regions.\n");
69115
return;
70116
}
@@ -193,6 +239,9 @@ void __init fdt_scan_reserved_mem_reg_nodes(void)
193239
return;
194240
}
195241

242+
/* Attempt dynamic allocation of a new reserved_mem array */
243+
alloc_reserved_mem_array();
244+
196245
if (__reserved_mem_check_root(node)) {
197246
pr_err("Reserved memory: unsupported node format, ignoring\n");
198247
return;
@@ -232,7 +281,7 @@ static int __init __reserved_mem_alloc_size(unsigned long node, const char *unam
232281
int __init fdt_scan_reserved_mem(void)
233282
{
234283
int node, child;
235-
int dynamic_nodes_cnt = 0;
284+
int dynamic_nodes_cnt = 0, count = 0;
236285
int dynamic_nodes[MAX_RESERVED_REGIONS];
237286
const void *fdt = initial_boot_params;
238287

@@ -255,6 +304,8 @@ int __init fdt_scan_reserved_mem(void)
255304
uname = fdt_get_name(fdt, child, NULL);
256305

257306
err = __reserved_mem_reserve_reg(child, uname);
307+
if (!err)
308+
count++;
258309
/*
259310
* Save the nodes for the dynamically-placed regions
260311
* into an array which will be used for allocation right
@@ -269,11 +320,15 @@ int __init fdt_scan_reserved_mem(void)
269320
}
270321
for (int i = 0; i < dynamic_nodes_cnt; i++) {
271322
const char *uname;
323+
int err;
272324

273325
child = dynamic_nodes[i];
274326
uname = fdt_get_name(fdt, child, NULL);
275-
__reserved_mem_alloc_size(child, uname);
327+
err = __reserved_mem_alloc_size(child, uname);
328+
if (!err)
329+
count++;
276330
}
331+
total_reserved_mem_cnt = count;
277332
return 0;
278333
}
279334

0 commit comments

Comments
 (0)