Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 #include "alloc_helpers_api.h"
0003 
0004 /*
0005  * A simple test that tries to allocate a memory region above a specified,
0006  * aligned address:
0007  *
0008  *             +
0009  *  |          +-----------+         |
0010  *  |          |    rgn    |         |
0011  *  +----------+-----------+---------+
0012  *             ^
0013  *             |
0014  *             Aligned min_addr
0015  *
0016  * Expect to allocate a cleared region at the minimal memory address.
0017  */
0018 static int alloc_from_simple_generic_check(void)
0019 {
0020     struct memblock_region *rgn = &memblock.reserved.regions[0];
0021     void *allocated_ptr = NULL;
0022     char *b;
0023 
0024     PREFIX_PUSH();
0025 
0026     phys_addr_t size = SZ_16;
0027     phys_addr_t min_addr;
0028 
0029     setup_memblock();
0030 
0031     min_addr = memblock_end_of_DRAM() - SMP_CACHE_BYTES;
0032 
0033     allocated_ptr = memblock_alloc_from(size, SMP_CACHE_BYTES, min_addr);
0034     b = (char *)allocated_ptr;
0035 
0036     ASSERT_NE(allocated_ptr, NULL);
0037     ASSERT_EQ(*b, 0);
0038 
0039     ASSERT_EQ(rgn->size, size);
0040     ASSERT_EQ(rgn->base, min_addr);
0041 
0042     ASSERT_EQ(memblock.reserved.cnt, 1);
0043     ASSERT_EQ(memblock.reserved.total_size, size);
0044 
0045     test_pass_pop();
0046 
0047     return 0;
0048 }
0049 
0050 /*
0051  * A test that tries to allocate a memory region above a certain address.
0052  * The minimal address here is not aligned:
0053  *
0054  *         +      +
0055  *  |      +      +---------+            |
0056  *  |      |      |   rgn   |            |
0057  *  +------+------+---------+------------+
0058  *         ^      ^------.
0059  *         |             |
0060  *       min_addr        Aligned address
0061  *                       boundary
0062  *
0063  * Expect to allocate a cleared region at the closest aligned memory address.
0064  */
0065 static int alloc_from_misaligned_generic_check(void)
0066 {
0067     struct memblock_region *rgn = &memblock.reserved.regions[0];
0068     void *allocated_ptr = NULL;
0069     char *b;
0070 
0071     PREFIX_PUSH();
0072 
0073     phys_addr_t size = SZ_32;
0074     phys_addr_t min_addr;
0075 
0076     setup_memblock();
0077 
0078     /* A misaligned address */
0079     min_addr = memblock_end_of_DRAM() - (SMP_CACHE_BYTES * 2 - 1);
0080 
0081     allocated_ptr = memblock_alloc_from(size, SMP_CACHE_BYTES, min_addr);
0082     b = (char *)allocated_ptr;
0083 
0084     ASSERT_NE(allocated_ptr, NULL);
0085     ASSERT_EQ(*b, 0);
0086 
0087     ASSERT_EQ(rgn->size, size);
0088     ASSERT_EQ(rgn->base, memblock_end_of_DRAM() - SMP_CACHE_BYTES);
0089 
0090     ASSERT_EQ(memblock.reserved.cnt, 1);
0091     ASSERT_EQ(memblock.reserved.total_size, size);
0092 
0093     test_pass_pop();
0094 
0095     return 0;
0096 }
0097 
0098 /*
0099  * A test that tries to allocate a memory region above an address that is too
0100  * close to the end of the memory:
0101  *
0102  *              +        +
0103  *  |           +--------+---+      |
0104  *  |           |   rgn  +   |      |
0105  *  +-----------+--------+---+------+
0106  *              ^        ^
0107  *              |        |
0108  *              |        min_addr
0109  *              |
0110  *              Aligned address
0111  *              boundary
0112  *
0113  * Expect to prioritize granting memory over satisfying the minimal address
0114  * requirement.
0115  */
0116 static int alloc_from_top_down_high_addr_check(void)
0117 {
0118     struct memblock_region *rgn = &memblock.reserved.regions[0];
0119     void *allocated_ptr = NULL;
0120 
0121     PREFIX_PUSH();
0122 
0123     phys_addr_t size = SZ_32;
0124     phys_addr_t min_addr;
0125 
0126     setup_memblock();
0127 
0128     /* The address is too close to the end of the memory */
0129     min_addr = memblock_end_of_DRAM() - SZ_16;
0130 
0131     allocated_ptr = memblock_alloc_from(size, SMP_CACHE_BYTES, min_addr);
0132 
0133     ASSERT_NE(allocated_ptr, NULL);
0134     ASSERT_EQ(rgn->size, size);
0135     ASSERT_EQ(rgn->base, memblock_end_of_DRAM() - SMP_CACHE_BYTES);
0136 
0137     ASSERT_EQ(memblock.reserved.cnt, 1);
0138     ASSERT_EQ(memblock.reserved.total_size, size);
0139 
0140     test_pass_pop();
0141 
0142     return 0;
0143 }
0144 
0145 /*
0146  * A test that tries to allocate a memory region when there is no space
0147  * available above the minimal address above a certain address:
0148  *
0149  *                     +
0150  *  |        +---------+-------------|
0151  *  |        |   rgn   |             |
0152  *  +--------+---------+-------------+
0153  *                     ^
0154  *                     |
0155  *                     min_addr
0156  *
0157  * Expect to prioritize granting memory over satisfying the minimal address
0158  * requirement and to allocate next to the previously reserved region. The
0159  * regions get merged into one.
0160  */
0161 static int alloc_from_top_down_no_space_above_check(void)
0162 {
0163     struct memblock_region *rgn = &memblock.reserved.regions[0];
0164     void *allocated_ptr = NULL;
0165 
0166     PREFIX_PUSH();
0167 
0168     phys_addr_t r1_size = SZ_64;
0169     phys_addr_t r2_size = SZ_2;
0170     phys_addr_t total_size = r1_size + r2_size;
0171     phys_addr_t min_addr;
0172 
0173     setup_memblock();
0174 
0175     min_addr = memblock_end_of_DRAM() - SMP_CACHE_BYTES * 2;
0176 
0177     /* No space above this address */
0178     memblock_reserve(min_addr, r2_size);
0179 
0180     allocated_ptr = memblock_alloc_from(r1_size, SMP_CACHE_BYTES, min_addr);
0181 
0182     ASSERT_NE(allocated_ptr, NULL);
0183     ASSERT_EQ(rgn->base, min_addr - r1_size);
0184     ASSERT_EQ(rgn->size, total_size);
0185 
0186     ASSERT_EQ(memblock.reserved.cnt, 1);
0187     ASSERT_EQ(memblock.reserved.total_size, total_size);
0188 
0189     test_pass_pop();
0190 
0191     return 0;
0192 }
0193 
0194 /*
0195  * A test that tries to allocate a memory region with a minimal address below
0196  * the start address of the available memory. As the allocation is top-down,
0197  * first reserve a region that will force allocation near the start.
0198  * Expect successful allocation and merge of both regions.
0199  */
0200 static int alloc_from_top_down_min_addr_cap_check(void)
0201 {
0202     struct memblock_region *rgn = &memblock.reserved.regions[0];
0203     void *allocated_ptr = NULL;
0204 
0205     PREFIX_PUSH();
0206 
0207     phys_addr_t r1_size = SZ_64;
0208     phys_addr_t min_addr;
0209     phys_addr_t start_addr;
0210 
0211     setup_memblock();
0212 
0213     start_addr = (phys_addr_t)memblock_start_of_DRAM();
0214     min_addr = start_addr - SMP_CACHE_BYTES * 3;
0215 
0216     memblock_reserve(start_addr + r1_size, MEM_SIZE - r1_size);
0217 
0218     allocated_ptr = memblock_alloc_from(r1_size, SMP_CACHE_BYTES, min_addr);
0219 
0220     ASSERT_NE(allocated_ptr, NULL);
0221     ASSERT_EQ(rgn->base, start_addr);
0222     ASSERT_EQ(rgn->size, MEM_SIZE);
0223 
0224     ASSERT_EQ(memblock.reserved.cnt, 1);
0225     ASSERT_EQ(memblock.reserved.total_size, MEM_SIZE);
0226 
0227     test_pass_pop();
0228 
0229     return 0;
0230 }
0231 
0232 /*
0233  * A test that tries to allocate a memory region above an address that is too
0234  * close to the end of the memory:
0235  *
0236  *                             +
0237  *  |-----------+              +     |
0238  *  |    rgn    |              |     |
0239  *  +-----------+--------------+-----+
0240  *  ^                          ^
0241  *  |                          |
0242  *  Aligned address            min_addr
0243  *  boundary
0244  *
0245  * Expect to prioritize granting memory over satisfying the minimal address
0246  * requirement. Allocation happens at beginning of the available memory.
0247  */
0248 static int alloc_from_bottom_up_high_addr_check(void)
0249 {
0250     struct memblock_region *rgn = &memblock.reserved.regions[0];
0251     void *allocated_ptr = NULL;
0252 
0253     PREFIX_PUSH();
0254 
0255     phys_addr_t size = SZ_32;
0256     phys_addr_t min_addr;
0257 
0258     setup_memblock();
0259 
0260     /* The address is too close to the end of the memory */
0261     min_addr = memblock_end_of_DRAM() - SZ_8;
0262 
0263     allocated_ptr = memblock_alloc_from(size, SMP_CACHE_BYTES, min_addr);
0264 
0265     ASSERT_NE(allocated_ptr, NULL);
0266     ASSERT_EQ(rgn->size, size);
0267     ASSERT_EQ(rgn->base, memblock_start_of_DRAM());
0268 
0269     ASSERT_EQ(memblock.reserved.cnt, 1);
0270     ASSERT_EQ(memblock.reserved.total_size, size);
0271 
0272     test_pass_pop();
0273 
0274     return 0;
0275 }
0276 
0277 /*
0278  * A test that tries to allocate a memory region when there is no space
0279  * available above the minimal address above a certain address:
0280  *
0281  *                   +
0282  *  |-----------+    +-------------------|
0283  *  |    rgn    |    |                   |
0284  *  +-----------+----+-------------------+
0285  *                   ^
0286  *                   |
0287  *                   min_addr
0288  *
0289  * Expect to prioritize granting memory over satisfying the minimal address
0290  * requirement and to allocate at the beginning of the available memory.
0291  */
0292 static int alloc_from_bottom_up_no_space_above_check(void)
0293 {
0294     struct memblock_region *rgn = &memblock.reserved.regions[0];
0295     void *allocated_ptr = NULL;
0296 
0297     PREFIX_PUSH();
0298 
0299     phys_addr_t r1_size = SZ_64;
0300     phys_addr_t min_addr;
0301     phys_addr_t r2_size;
0302 
0303     setup_memblock();
0304 
0305     min_addr = memblock_start_of_DRAM() + SZ_128;
0306     r2_size = memblock_end_of_DRAM() - min_addr;
0307 
0308     /* No space above this address */
0309     memblock_reserve(min_addr - SMP_CACHE_BYTES, r2_size);
0310 
0311     allocated_ptr = memblock_alloc_from(r1_size, SMP_CACHE_BYTES, min_addr);
0312 
0313     ASSERT_NE(allocated_ptr, NULL);
0314     ASSERT_EQ(rgn->base, memblock_start_of_DRAM());
0315     ASSERT_EQ(rgn->size, r1_size);
0316 
0317     ASSERT_EQ(memblock.reserved.cnt, 2);
0318     ASSERT_EQ(memblock.reserved.total_size, r1_size + r2_size);
0319 
0320     test_pass_pop();
0321 
0322     return 0;
0323 }
0324 
0325 /*
0326  * A test that tries to allocate a memory region with a minimal address below
0327  * the start address of the available memory. Expect to allocate a region
0328  * at the beginning of the available memory.
0329  */
0330 static int alloc_from_bottom_up_min_addr_cap_check(void)
0331 {
0332     struct memblock_region *rgn = &memblock.reserved.regions[0];
0333     void *allocated_ptr = NULL;
0334 
0335     PREFIX_PUSH();
0336 
0337     phys_addr_t r1_size = SZ_64;
0338     phys_addr_t min_addr;
0339     phys_addr_t start_addr;
0340 
0341     setup_memblock();
0342 
0343     start_addr = (phys_addr_t)memblock_start_of_DRAM();
0344     min_addr = start_addr - SMP_CACHE_BYTES * 3;
0345 
0346     allocated_ptr = memblock_alloc_from(r1_size, SMP_CACHE_BYTES, min_addr);
0347 
0348     ASSERT_NE(allocated_ptr, NULL);
0349     ASSERT_EQ(rgn->base, start_addr);
0350     ASSERT_EQ(rgn->size, r1_size);
0351 
0352     ASSERT_EQ(memblock.reserved.cnt, 1);
0353     ASSERT_EQ(memblock.reserved.total_size, r1_size);
0354 
0355     test_pass_pop();
0356 
0357     return 0;
0358 }
0359 
0360 /* Test case wrappers */
0361 static int alloc_from_simple_check(void)
0362 {
0363     test_print("\tRunning %s...\n", __func__);
0364     memblock_set_bottom_up(false);
0365     alloc_from_simple_generic_check();
0366     memblock_set_bottom_up(true);
0367     alloc_from_simple_generic_check();
0368 
0369     return 0;
0370 }
0371 
0372 static int alloc_from_misaligned_check(void)
0373 {
0374     test_print("\tRunning %s...\n", __func__);
0375     memblock_set_bottom_up(false);
0376     alloc_from_misaligned_generic_check();
0377     memblock_set_bottom_up(true);
0378     alloc_from_misaligned_generic_check();
0379 
0380     return 0;
0381 }
0382 
0383 static int alloc_from_high_addr_check(void)
0384 {
0385     test_print("\tRunning %s...\n", __func__);
0386     memblock_set_bottom_up(false);
0387     alloc_from_top_down_high_addr_check();
0388     memblock_set_bottom_up(true);
0389     alloc_from_bottom_up_high_addr_check();
0390 
0391     return 0;
0392 }
0393 
0394 static int alloc_from_no_space_above_check(void)
0395 {
0396     test_print("\tRunning %s...\n", __func__);
0397     memblock_set_bottom_up(false);
0398     alloc_from_top_down_no_space_above_check();
0399     memblock_set_bottom_up(true);
0400     alloc_from_bottom_up_no_space_above_check();
0401 
0402     return 0;
0403 }
0404 
0405 static int alloc_from_min_addr_cap_check(void)
0406 {
0407     test_print("\tRunning %s...\n", __func__);
0408     memblock_set_bottom_up(false);
0409     alloc_from_top_down_min_addr_cap_check();
0410     memblock_set_bottom_up(true);
0411     alloc_from_bottom_up_min_addr_cap_check();
0412 
0413     return 0;
0414 }
0415 
0416 int memblock_alloc_helpers_checks(void)
0417 {
0418     const char *func_testing = "memblock_alloc_from";
0419 
0420     prefix_reset();
0421     prefix_push(func_testing);
0422     test_print("Running %s tests...\n", func_testing);
0423 
0424     reset_memblock_attributes();
0425     dummy_physical_memory_init();
0426 
0427     alloc_from_simple_check();
0428     alloc_from_misaligned_check();
0429     alloc_from_high_addr_check();
0430     alloc_from_no_space_above_check();
0431     alloc_from_min_addr_cap_check();
0432 
0433     dummy_physical_memory_cleanup();
0434 
0435     prefix_pop();
0436 
0437     return 0;
0438 }