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