Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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 <quic_obabatun@quicinc.com>
Link: https://lore.kernel.org/r/20241008220624.551309-3-quic_obabatun@quicinc.com
Signed-off-by: Rob Herring (Arm) <robh@kernel.org>

authored by

Oreoluwa Babatunde and committed by
Rob Herring (Arm)
00c9a452 8a6e02d0

+59 -4
+59 -4
drivers/of/of_reserved_mem.c
··· 27 27 28 28 #include "of_private.h" 29 29 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; 31 33 static int reserved_mem_count; 32 34 33 35 static int __init early_init_dt_alloc_reserved_memory_arch(phys_addr_t size, ··· 57 55 return err; 58 56 } 59 57 58 + /* 59 + * alloc_reserved_mem_array() - allocate memory for the reserved_mem 60 + * array using memblock 61 + * 62 + * This function is used to allocate memory for the reserved_mem 63 + * array according to the total number of reserved memory regions 64 + * defined in the DT. 65 + * After the new array is allocated, the information stored in 66 + * the initial static array is copied over to this new array and 67 + * the new array is used from this point on. 68 + */ 69 + static void __init alloc_reserved_mem_array(void) 70 + { 71 + struct reserved_mem *new_array; 72 + size_t alloc_size, copy_size, memset_size; 73 + 74 + alloc_size = array_size(total_reserved_mem_cnt, sizeof(*new_array)); 75 + if (alloc_size == SIZE_MAX) { 76 + pr_err("Failed to allocate memory for reserved_mem array with err: %d", -EOVERFLOW); 77 + return; 78 + } 79 + 80 + new_array = memblock_alloc(alloc_size, SMP_CACHE_BYTES); 81 + if (!new_array) { 82 + pr_err("Failed to allocate memory for reserved_mem array with err: %d", -ENOMEM); 83 + return; 84 + } 85 + 86 + copy_size = array_size(reserved_mem_count, sizeof(*new_array)); 87 + if (copy_size == SIZE_MAX) { 88 + memblock_free(new_array, alloc_size); 89 + total_reserved_mem_cnt = MAX_RESERVED_REGIONS; 90 + pr_err("Failed to allocate memory for reserved_mem array with err: %d", -EOVERFLOW); 91 + return; 92 + } 93 + 94 + memset_size = alloc_size - copy_size; 95 + 96 + memcpy(new_array, reserved_mem, copy_size); 97 + memset(new_array + reserved_mem_count, 0, memset_size); 98 + 99 + reserved_mem = new_array; 100 + } 101 + 60 102 static void __init fdt_init_reserved_mem_node(struct reserved_mem *rmem); 61 103 /* 62 104 * fdt_reserved_mem_save_node() - save fdt node for second pass initialization ··· 110 64 { 111 65 struct reserved_mem *rmem = &reserved_mem[reserved_mem_count]; 112 66 113 - if (reserved_mem_count == ARRAY_SIZE(reserved_mem)) { 67 + if (reserved_mem_count == total_reserved_mem_cnt) { 114 68 pr_err("not enough space for all defined regions.\n"); 115 69 return; 116 70 } ··· 239 193 return; 240 194 } 241 195 196 + /* Attempt dynamic allocation of a new reserved_mem array */ 197 + alloc_reserved_mem_array(); 198 + 242 199 if (__reserved_mem_check_root(node)) { 243 200 pr_err("Reserved memory: unsupported node format, ignoring\n"); 244 201 return; ··· 281 232 int __init fdt_scan_reserved_mem(void) 282 233 { 283 234 int node, child; 284 - int dynamic_nodes_cnt = 0; 235 + int dynamic_nodes_cnt = 0, count = 0; 285 236 int dynamic_nodes[MAX_RESERVED_REGIONS]; 286 237 const void *fdt = initial_boot_params; 287 238 ··· 304 255 uname = fdt_get_name(fdt, child, NULL); 305 256 306 257 err = __reserved_mem_reserve_reg(child, uname); 258 + if (!err) 259 + count++; 307 260 /* 308 261 * Save the nodes for the dynamically-placed regions 309 262 * into an array which will be used for allocation right ··· 320 269 } 321 270 for (int i = 0; i < dynamic_nodes_cnt; i++) { 322 271 const char *uname; 272 + int err; 323 273 324 274 child = dynamic_nodes[i]; 325 275 uname = fdt_get_name(fdt, child, NULL); 326 - __reserved_mem_alloc_size(child, uname); 276 + err = __reserved_mem_alloc_size(child, uname); 277 + if (!err) 278 + count++; 327 279 } 280 + total_reserved_mem_cnt = count; 328 281 return 0; 329 282 } 330 283