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