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