415 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2#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_addr15 *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 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 address57 * boundary58 *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 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 too92 * close to the end of the memory:93 *94 * + +95 * | +--------+---+ |96 * | | rgn + | |97 * +-----------+--------+---+------+98 * ^ ^99 * | |100 * | min_addr101 * |102 * Aligned address103 * boundary104 *105 * Expect to prioritize granting memory over satisfying the minimal address106 * 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 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 space137 * available above the minimal address above a certain address:138 *139 * +140 * | +---------+-------------|141 * | | rgn | |142 * +--------+---------+-------------+143 * ^144 * |145 * min_addr146 *147 * Expect to prioritize granting memory over satisfying the minimal address148 * requirement and to allocate next to the previously reserved region. The149 * regions get merged into one.150 */151static 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 below184 * 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 */188static 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 too220 * close to the end of the memory:221 *222 * +223 * |-----------+ + |224 * | rgn | | |225 * +-----------+--------------+-----+226 * ^ ^227 * | |228 * Aligned address min_addr229 * boundary230 *231 * Expect to prioritize granting memory over satisfying the minimal address232 * requirement. Allocation happens at beginning of the available memory.233 */234static 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 space263 * available above the minimal address above a certain address:264 *265 * +266 * |-----------+ +-------------------|267 * | rgn | | |268 * +-----------+----+-------------------+269 * ^270 * |271 * min_addr272 *273 * Expect to prioritize granting memory over satisfying the minimal address274 * requirement and to allocate at the beginning of the available memory.275 */276static 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 below309 * the start address of the available memory. Expect to allocate a region310 * at the beginning of the available memory.311 */312static 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 */341static 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 350static 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 359static 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 370static 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 381static 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 392int 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