alloc_helpers_api.c (10135B)
1// SPDX-License-Identifier: GPL-2.0-or-later 2#include "alloc_helpers_api.h" 3 4/* 5 * A simple test that tries to allocate a memory region above a specified, 6 * aligned address: 7 * 8 * + 9 * | +-----------+ | 10 * | | rgn | | 11 * +----------+-----------+---------+ 12 * ^ 13 * | 14 * Aligned min_addr 15 * 16 * Expect to allocate a cleared region at the minimal memory address. 17 */ 18static int alloc_from_simple_generic_check(void) 19{ 20 struct memblock_region *rgn = &memblock.reserved.regions[0]; 21 void *allocated_ptr = NULL; 22 char *b; 23 24 phys_addr_t size = SZ_16; 25 phys_addr_t min_addr; 26 27 setup_memblock(); 28 29 min_addr = memblock_end_of_DRAM() - SMP_CACHE_BYTES; 30 31 allocated_ptr = memblock_alloc_from(size, SMP_CACHE_BYTES, min_addr); 32 b = (char *)allocated_ptr; 33 34 assert(allocated_ptr); 35 assert(*b == 0); 36 37 assert(rgn->size == size); 38 assert(rgn->base == min_addr); 39 40 assert(memblock.reserved.cnt == 1); 41 assert(memblock.reserved.total_size == size); 42 43 return 0; 44} 45 46/* 47 * A test that tries to allocate a memory region above a certain address. 48 * The minimal address here is not aligned: 49 * 50 * + + 51 * | + +---------+ | 52 * | | | rgn | | 53 * +------+------+---------+------------+ 54 * ^ ^------. 55 * | | 56 * min_addr Aligned address 57 * boundary 58 * 59 * Expect to allocate a cleared region at the closest aligned memory address. 60 */ 61static int alloc_from_misaligned_generic_check(void) 62{ 63 struct memblock_region *rgn = &memblock.reserved.regions[0]; 64 void *allocated_ptr = NULL; 65 char *b; 66 67 phys_addr_t size = SZ_32; 68 phys_addr_t min_addr; 69 70 setup_memblock(); 71 72 /* A misaligned address */ 73 min_addr = memblock_end_of_DRAM() - (SMP_CACHE_BYTES * 2 - 1); 74 75 allocated_ptr = memblock_alloc_from(size, SMP_CACHE_BYTES, min_addr); 76 b = (char *)allocated_ptr; 77 78 assert(allocated_ptr); 79 assert(*b == 0); 80 81 assert(rgn->size == size); 82 assert(rgn->base == memblock_end_of_DRAM() - SMP_CACHE_BYTES); 83 84 assert(memblock.reserved.cnt == 1); 85 assert(memblock.reserved.total_size == size); 86 87 return 0; 88} 89 90/* 91 * A test that tries to allocate a memory region above an address that is too 92 * close to the end of the memory: 93 * 94 * + + 95 * | +--------+---+ | 96 * | | rgn + | | 97 * +-----------+--------+---+------+ 98 * ^ ^ 99 * | | 100 * | min_addr 101 * | 102 * Aligned address 103 * boundary 104 * 105 * Expect to prioritize granting memory over satisfying the minimal address 106 * requirement. 107 */ 108static int alloc_from_top_down_high_addr_check(void) 109{ 110 struct memblock_region *rgn = &memblock.reserved.regions[0]; 111 void *allocated_ptr = NULL; 112 113 phys_addr_t size = SZ_32; 114 phys_addr_t min_addr; 115 116 setup_memblock(); 117 118 /* The address is too close to the end of the memory */ 119 min_addr = memblock_end_of_DRAM() - SZ_16; 120 121 allocated_ptr = memblock_alloc_from(size, SMP_CACHE_BYTES, min_addr); 122 123 assert(allocated_ptr); 124 assert(rgn->size == size); 125 assert(rgn->base == memblock_end_of_DRAM() - SMP_CACHE_BYTES); 126 127 assert(memblock.reserved.cnt == 1); 128 assert(memblock.reserved.total_size == size); 129 130 return 0; 131} 132 133/* 134 * A test that tries to allocate a memory region when there is no space 135 * available above the minimal address above a certain address: 136 * 137 * + 138 * | +---------+-------------| 139 * | | rgn | | 140 * +--------+---------+-------------+ 141 * ^ 142 * | 143 * min_addr 144 * 145 * Expect to prioritize granting memory over satisfying the minimal address 146 * requirement and to allocate next to the previously reserved region. The 147 * regions get merged into one. 148 */ 149static int alloc_from_top_down_no_space_above_check(void) 150{ 151 struct memblock_region *rgn = &memblock.reserved.regions[0]; 152 void *allocated_ptr = NULL; 153 154 phys_addr_t r1_size = SZ_64; 155 phys_addr_t r2_size = SZ_2; 156 phys_addr_t total_size = r1_size + r2_size; 157 phys_addr_t min_addr; 158 159 setup_memblock(); 160 161 min_addr = memblock_end_of_DRAM() - SMP_CACHE_BYTES * 2; 162 163 /* No space above this address */ 164 memblock_reserve(min_addr, r2_size); 165 166 allocated_ptr = memblock_alloc_from(r1_size, SMP_CACHE_BYTES, min_addr); 167 168 assert(allocated_ptr); 169 assert(rgn->base == min_addr - r1_size); 170 assert(rgn->size == total_size); 171 172 assert(memblock.reserved.cnt == 1); 173 assert(memblock.reserved.total_size == total_size); 174 175 return 0; 176} 177 178/* 179 * A test that tries to allocate a memory region with a minimal address below 180 * the start address of the available memory. As the allocation is top-down, 181 * first reserve a region that will force allocation near the start. 182 * Expect successful allocation and merge of both regions. 183 */ 184static int alloc_from_top_down_min_addr_cap_check(void) 185{ 186 struct memblock_region *rgn = &memblock.reserved.regions[0]; 187 void *allocated_ptr = NULL; 188 189 phys_addr_t r1_size = SZ_64; 190 phys_addr_t min_addr; 191 phys_addr_t start_addr; 192 193 setup_memblock(); 194 195 start_addr = (phys_addr_t)memblock_start_of_DRAM(); 196 min_addr = start_addr - SMP_CACHE_BYTES * 3; 197 198 memblock_reserve(start_addr + r1_size, MEM_SIZE - r1_size); 199 200 allocated_ptr = memblock_alloc_from(r1_size, SMP_CACHE_BYTES, min_addr); 201 202 assert(allocated_ptr); 203 assert(rgn->base == start_addr); 204 assert(rgn->size == MEM_SIZE); 205 206 assert(memblock.reserved.cnt == 1); 207 assert(memblock.reserved.total_size == MEM_SIZE); 208 209 return 0; 210} 211 212/* 213 * A test that tries to allocate a memory region above an address that is too 214 * close to the end of the memory: 215 * 216 * + 217 * |-----------+ + | 218 * | rgn | | | 219 * +-----------+--------------+-----+ 220 * ^ ^ 221 * | | 222 * Aligned address min_addr 223 * boundary 224 * 225 * Expect to prioritize granting memory over satisfying the minimal address 226 * requirement. Allocation happens at beginning of the available memory. 227 */ 228static int alloc_from_bottom_up_high_addr_check(void) 229{ 230 struct memblock_region *rgn = &memblock.reserved.regions[0]; 231 void *allocated_ptr = NULL; 232 233 phys_addr_t size = SZ_32; 234 phys_addr_t min_addr; 235 236 setup_memblock(); 237 238 /* The address is too close to the end of the memory */ 239 min_addr = memblock_end_of_DRAM() - SZ_8; 240 241 allocated_ptr = memblock_alloc_from(size, SMP_CACHE_BYTES, min_addr); 242 243 assert(allocated_ptr); 244 assert(rgn->size == size); 245 assert(rgn->base == memblock_start_of_DRAM()); 246 247 assert(memblock.reserved.cnt == 1); 248 assert(memblock.reserved.total_size == size); 249 250 return 0; 251} 252 253/* 254 * A test that tries to allocate a memory region when there is no space 255 * available above the minimal address above a certain address: 256 * 257 * + 258 * |-----------+ +-------------------| 259 * | rgn | | | 260 * +-----------+----+-------------------+ 261 * ^ 262 * | 263 * min_addr 264 * 265 * Expect to prioritize granting memory over satisfying the minimal address 266 * requirement and to allocate at the beginning of the available memory. 267 */ 268static int alloc_from_bottom_up_no_space_above_check(void) 269{ 270 struct memblock_region *rgn = &memblock.reserved.regions[0]; 271 void *allocated_ptr = NULL; 272 273 phys_addr_t r1_size = SZ_64; 274 phys_addr_t min_addr; 275 phys_addr_t r2_size; 276 277 setup_memblock(); 278 279 min_addr = memblock_start_of_DRAM() + SZ_128; 280 r2_size = memblock_end_of_DRAM() - min_addr; 281 282 /* No space above this address */ 283 memblock_reserve(min_addr - SMP_CACHE_BYTES, r2_size); 284 285 allocated_ptr = memblock_alloc_from(r1_size, SMP_CACHE_BYTES, min_addr); 286 287 assert(allocated_ptr); 288 assert(rgn->base == memblock_start_of_DRAM()); 289 assert(rgn->size == r1_size); 290 291 assert(memblock.reserved.cnt == 2); 292 assert(memblock.reserved.total_size == r1_size + r2_size); 293 294 return 0; 295} 296 297/* 298 * A test that tries to allocate a memory region with a minimal address below 299 * the start address of the available memory. Expect to allocate a region 300 * at the beginning of the available memory. 301 */ 302static int alloc_from_bottom_up_min_addr_cap_check(void) 303{ 304 struct memblock_region *rgn = &memblock.reserved.regions[0]; 305 void *allocated_ptr = NULL; 306 307 phys_addr_t r1_size = SZ_64; 308 phys_addr_t min_addr; 309 phys_addr_t start_addr; 310 311 setup_memblock(); 312 313 start_addr = (phys_addr_t)memblock_start_of_DRAM(); 314 min_addr = start_addr - SMP_CACHE_BYTES * 3; 315 316 allocated_ptr = memblock_alloc_from(r1_size, SMP_CACHE_BYTES, min_addr); 317 318 assert(allocated_ptr); 319 assert(rgn->base == start_addr); 320 assert(rgn->size == r1_size); 321 322 assert(memblock.reserved.cnt == 1); 323 assert(memblock.reserved.total_size == r1_size); 324 325 return 0; 326} 327 328/* Test case wrappers */ 329static int alloc_from_simple_check(void) 330{ 331 memblock_set_bottom_up(false); 332 alloc_from_simple_generic_check(); 333 memblock_set_bottom_up(true); 334 alloc_from_simple_generic_check(); 335 336 return 0; 337} 338 339static int alloc_from_misaligned_check(void) 340{ 341 memblock_set_bottom_up(false); 342 alloc_from_misaligned_generic_check(); 343 memblock_set_bottom_up(true); 344 alloc_from_misaligned_generic_check(); 345 346 return 0; 347} 348 349static int alloc_from_high_addr_check(void) 350{ 351 memblock_set_bottom_up(false); 352 alloc_from_top_down_high_addr_check(); 353 memblock_set_bottom_up(true); 354 alloc_from_bottom_up_high_addr_check(); 355 356 return 0; 357} 358 359static int alloc_from_no_space_above_check(void) 360{ 361 memblock_set_bottom_up(false); 362 alloc_from_top_down_no_space_above_check(); 363 memblock_set_bottom_up(true); 364 alloc_from_bottom_up_no_space_above_check(); 365 366 return 0; 367} 368 369static int alloc_from_min_addr_cap_check(void) 370{ 371 memblock_set_bottom_up(false); 372 alloc_from_top_down_min_addr_cap_check(); 373 memblock_set_bottom_up(true); 374 alloc_from_bottom_up_min_addr_cap_check(); 375 376 return 0; 377} 378 379int memblock_alloc_helpers_checks(void) 380{ 381 reset_memblock_attributes(); 382 dummy_physical_memory_init(); 383 384 alloc_from_simple_check(); 385 alloc_from_misaligned_check(); 386 alloc_from_high_addr_check(); 387 alloc_from_no_space_above_check(); 388 alloc_from_min_addr_cap_check(); 389 390 dummy_physical_memory_cleanup(); 391 392 return 0; 393}