Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 #include <string.h>
0003 #include <linux/memblock.h>
0004 #include "basic_api.h"
0005 
0006 #define EXPECTED_MEMBLOCK_REGIONS           128
0007 #define FUNC_ADD                    "memblock_add"
0008 #define FUNC_RESERVE                    "memblock_reserve"
0009 #define FUNC_REMOVE                 "memblock_remove"
0010 #define FUNC_FREE                   "memblock_free"
0011 
0012 static int memblock_initialization_check(void)
0013 {
0014     PREFIX_PUSH();
0015 
0016     ASSERT_NE(memblock.memory.regions, NULL);
0017     ASSERT_EQ(memblock.memory.cnt, 1);
0018     ASSERT_EQ(memblock.memory.max, EXPECTED_MEMBLOCK_REGIONS);
0019     ASSERT_EQ(strcmp(memblock.memory.name, "memory"), 0);
0020 
0021     ASSERT_NE(memblock.reserved.regions, NULL);
0022     ASSERT_EQ(memblock.reserved.cnt, 1);
0023     ASSERT_EQ(memblock.memory.max, EXPECTED_MEMBLOCK_REGIONS);
0024     ASSERT_EQ(strcmp(memblock.reserved.name, "reserved"), 0);
0025 
0026     ASSERT_EQ(memblock.bottom_up, false);
0027     ASSERT_EQ(memblock.current_limit, MEMBLOCK_ALLOC_ANYWHERE);
0028 
0029     test_pass_pop();
0030 
0031     return 0;
0032 }
0033 
0034 /*
0035  * A simple test that adds a memory block of a specified base address
0036  * and size to the collection of available memory regions (memblock.memory).
0037  * Expect to create a new entry. The region counter and total memory get
0038  * updated.
0039  */
0040 static int memblock_add_simple_check(void)
0041 {
0042     struct memblock_region *rgn;
0043 
0044     rgn = &memblock.memory.regions[0];
0045 
0046     struct region r = {
0047         .base = SZ_1G,
0048         .size = SZ_4M
0049     };
0050 
0051     PREFIX_PUSH();
0052 
0053     reset_memblock_regions();
0054     memblock_add(r.base, r.size);
0055 
0056     ASSERT_EQ(rgn->base, r.base);
0057     ASSERT_EQ(rgn->size, r.size);
0058 
0059     ASSERT_EQ(memblock.memory.cnt, 1);
0060     ASSERT_EQ(memblock.memory.total_size, r.size);
0061 
0062     test_pass_pop();
0063 
0064     return 0;
0065 }
0066 
0067 /*
0068  * A simple test that adds a memory block of a specified base address, size,
0069  * NUMA node and memory flags to the collection of available memory regions.
0070  * Expect to create a new entry. The region counter and total memory get
0071  * updated.
0072  */
0073 static int memblock_add_node_simple_check(void)
0074 {
0075     struct memblock_region *rgn;
0076 
0077     rgn = &memblock.memory.regions[0];
0078 
0079     struct region r = {
0080         .base = SZ_1M,
0081         .size = SZ_16M
0082     };
0083 
0084     PREFIX_PUSH();
0085 
0086     reset_memblock_regions();
0087     memblock_add_node(r.base, r.size, 1, MEMBLOCK_HOTPLUG);
0088 
0089     ASSERT_EQ(rgn->base, r.base);
0090     ASSERT_EQ(rgn->size, r.size);
0091 #ifdef CONFIG_NUMA
0092     ASSERT_EQ(rgn->nid, 1);
0093 #endif
0094     ASSERT_EQ(rgn->flags, MEMBLOCK_HOTPLUG);
0095 
0096     ASSERT_EQ(memblock.memory.cnt, 1);
0097     ASSERT_EQ(memblock.memory.total_size, r.size);
0098 
0099     test_pass_pop();
0100 
0101     return 0;
0102 }
0103 
0104 /*
0105  * A test that tries to add two memory blocks that don't overlap with one
0106  * another:
0107  *
0108  *  |        +--------+        +--------+  |
0109  *  |        |   r1   |        |   r2   |  |
0110  *  +--------+--------+--------+--------+--+
0111  *
0112  * Expect to add two correctly initialized entries to the collection of
0113  * available memory regions (memblock.memory). The total size and
0114  * region counter fields get updated.
0115  */
0116 static int memblock_add_disjoint_check(void)
0117 {
0118     struct memblock_region *rgn1, *rgn2;
0119 
0120     rgn1 = &memblock.memory.regions[0];
0121     rgn2 = &memblock.memory.regions[1];
0122 
0123     struct region r1 = {
0124         .base = SZ_1G,
0125         .size = SZ_8K
0126     };
0127     struct region r2 = {
0128         .base = SZ_1G + SZ_16K,
0129         .size = SZ_8K
0130     };
0131 
0132     PREFIX_PUSH();
0133 
0134     reset_memblock_regions();
0135     memblock_add(r1.base, r1.size);
0136     memblock_add(r2.base, r2.size);
0137 
0138     ASSERT_EQ(rgn1->base, r1.base);
0139     ASSERT_EQ(rgn1->size, r1.size);
0140 
0141     ASSERT_EQ(rgn2->base, r2.base);
0142     ASSERT_EQ(rgn2->size, r2.size);
0143 
0144     ASSERT_EQ(memblock.memory.cnt, 2);
0145     ASSERT_EQ(memblock.memory.total_size, r1.size + r2.size);
0146 
0147     test_pass_pop();
0148 
0149     return 0;
0150 }
0151 
0152 /*
0153  * A test that tries to add two memory blocks r1 and r2, where r2 overlaps
0154  * with the beginning of r1 (that is r1.base < r2.base + r2.size):
0155  *
0156  *  |    +----+----+------------+          |
0157  *  |    |    |r2  |   r1       |          |
0158  *  +----+----+----+------------+----------+
0159  *       ^    ^
0160  *       |    |
0161  *       |    r1.base
0162  *       |
0163  *       r2.base
0164  *
0165  * Expect to merge the two entries into one region that starts at r2.base
0166  * and has size of two regions minus their intersection. The total size of
0167  * the available memory is updated, and the region counter stays the same.
0168  */
0169 static int memblock_add_overlap_top_check(void)
0170 {
0171     struct memblock_region *rgn;
0172     phys_addr_t total_size;
0173 
0174     rgn = &memblock.memory.regions[0];
0175 
0176     struct region r1 = {
0177         .base = SZ_512M,
0178         .size = SZ_1G
0179     };
0180     struct region r2 = {
0181         .base = SZ_256M,
0182         .size = SZ_512M
0183     };
0184 
0185     PREFIX_PUSH();
0186 
0187     total_size = (r1.base - r2.base) + r1.size;
0188 
0189     reset_memblock_regions();
0190     memblock_add(r1.base, r1.size);
0191     memblock_add(r2.base, r2.size);
0192 
0193     ASSERT_EQ(rgn->base, r2.base);
0194     ASSERT_EQ(rgn->size, total_size);
0195 
0196     ASSERT_EQ(memblock.memory.cnt, 1);
0197     ASSERT_EQ(memblock.memory.total_size, total_size);
0198 
0199     test_pass_pop();
0200 
0201     return 0;
0202 }
0203 
0204 /*
0205  * A test that tries to add two memory blocks r1 and r2, where r2 overlaps
0206  * with the end of r1 (that is r2.base < r1.base + r1.size):
0207  *
0208  *  |  +--+------+----------+              |
0209  *  |  |  | r1   | r2       |              |
0210  *  +--+--+------+----------+--------------+
0211  *     ^  ^
0212  *     |  |
0213  *     |  r2.base
0214  *     |
0215  *     r1.base
0216  *
0217  * Expect to merge the two entries into one region that starts at r1.base
0218  * and has size of two regions minus their intersection. The total size of
0219  * the available memory is updated, and the region counter stays the same.
0220  */
0221 static int memblock_add_overlap_bottom_check(void)
0222 {
0223     struct memblock_region *rgn;
0224     phys_addr_t total_size;
0225 
0226     rgn = &memblock.memory.regions[0];
0227 
0228     struct region r1 = {
0229         .base = SZ_128M,
0230         .size = SZ_512M
0231     };
0232     struct region r2 = {
0233         .base = SZ_256M,
0234         .size = SZ_1G
0235     };
0236 
0237     PREFIX_PUSH();
0238 
0239     total_size = (r2.base - r1.base) + r2.size;
0240 
0241     reset_memblock_regions();
0242     memblock_add(r1.base, r1.size);
0243     memblock_add(r2.base, r2.size);
0244 
0245     ASSERT_EQ(rgn->base, r1.base);
0246     ASSERT_EQ(rgn->size, total_size);
0247 
0248     ASSERT_EQ(memblock.memory.cnt, 1);
0249     ASSERT_EQ(memblock.memory.total_size, total_size);
0250 
0251     test_pass_pop();
0252 
0253     return 0;
0254 }
0255 
0256 /*
0257  * A test that tries to add two memory blocks r1 and r2, where r2 is
0258  * within the range of r1 (that is r1.base < r2.base &&
0259  * r2.base + r2.size < r1.base + r1.size):
0260  *
0261  *  |   +-------+--+-----------------------+
0262  *  |   |       |r2|      r1               |
0263  *  +---+-------+--+-----------------------+
0264  *      ^
0265  *      |
0266  *      r1.base
0267  *
0268  * Expect to merge two entries into one region that stays the same.
0269  * The counter and total size of available memory are not updated.
0270  */
0271 static int memblock_add_within_check(void)
0272 {
0273     struct memblock_region *rgn;
0274 
0275     rgn = &memblock.memory.regions[0];
0276 
0277     struct region r1 = {
0278         .base = SZ_8M,
0279         .size = SZ_32M
0280     };
0281     struct region r2 = {
0282         .base = SZ_16M,
0283         .size = SZ_1M
0284     };
0285 
0286     PREFIX_PUSH();
0287 
0288     reset_memblock_regions();
0289     memblock_add(r1.base, r1.size);
0290     memblock_add(r2.base, r2.size);
0291 
0292     ASSERT_EQ(rgn->base, r1.base);
0293     ASSERT_EQ(rgn->size, r1.size);
0294 
0295     ASSERT_EQ(memblock.memory.cnt, 1);
0296     ASSERT_EQ(memblock.memory.total_size, r1.size);
0297 
0298     test_pass_pop();
0299 
0300     return 0;
0301 }
0302 
0303 /*
0304  * A simple test that tries to add the same memory block twice. Expect
0305  * the counter and total size of available memory to not be updated.
0306  */
0307 static int memblock_add_twice_check(void)
0308 {
0309     struct region r = {
0310         .base = SZ_16K,
0311         .size = SZ_2M
0312     };
0313 
0314     PREFIX_PUSH();
0315 
0316     reset_memblock_regions();
0317 
0318     memblock_add(r.base, r.size);
0319     memblock_add(r.base, r.size);
0320 
0321     ASSERT_EQ(memblock.memory.cnt, 1);
0322     ASSERT_EQ(memblock.memory.total_size, r.size);
0323 
0324     test_pass_pop();
0325 
0326     return 0;
0327 }
0328 
0329 static int memblock_add_checks(void)
0330 {
0331     prefix_reset();
0332     prefix_push(FUNC_ADD);
0333     test_print("Running %s tests...\n", FUNC_ADD);
0334 
0335     memblock_add_simple_check();
0336     memblock_add_node_simple_check();
0337     memblock_add_disjoint_check();
0338     memblock_add_overlap_top_check();
0339     memblock_add_overlap_bottom_check();
0340     memblock_add_within_check();
0341     memblock_add_twice_check();
0342 
0343     prefix_pop();
0344 
0345     return 0;
0346 }
0347 
0348 /*
0349  * A simple test that marks a memory block of a specified base address
0350  * and size as reserved and to the collection of reserved memory regions
0351  * (memblock.reserved). Expect to create a new entry. The region counter
0352  * and total memory size are updated.
0353  */
0354 static int memblock_reserve_simple_check(void)
0355 {
0356     struct memblock_region *rgn;
0357 
0358     rgn =  &memblock.reserved.regions[0];
0359 
0360     struct region r = {
0361         .base = SZ_2G,
0362         .size = SZ_128M
0363     };
0364 
0365     PREFIX_PUSH();
0366 
0367     reset_memblock_regions();
0368     memblock_reserve(r.base, r.size);
0369 
0370     ASSERT_EQ(rgn->base, r.base);
0371     ASSERT_EQ(rgn->size, r.size);
0372 
0373     test_pass_pop();
0374 
0375     return 0;
0376 }
0377 
0378 /*
0379  * A test that tries to mark two memory blocks that don't overlap as reserved:
0380  *
0381  *  |        +--+      +----------------+  |
0382  *  |        |r1|      |       r2       |  |
0383  *  +--------+--+------+----------------+--+
0384  *
0385  * Expect to add two entries to the collection of reserved memory regions
0386  * (memblock.reserved). The total size and region counter for
0387  * memblock.reserved are updated.
0388  */
0389 static int memblock_reserve_disjoint_check(void)
0390 {
0391     struct memblock_region *rgn1, *rgn2;
0392 
0393     rgn1 = &memblock.reserved.regions[0];
0394     rgn2 = &memblock.reserved.regions[1];
0395 
0396     struct region r1 = {
0397         .base = SZ_256M,
0398         .size = SZ_16M
0399     };
0400     struct region r2 = {
0401         .base = SZ_512M,
0402         .size = SZ_512M
0403     };
0404 
0405     PREFIX_PUSH();
0406 
0407     reset_memblock_regions();
0408     memblock_reserve(r1.base, r1.size);
0409     memblock_reserve(r2.base, r2.size);
0410 
0411     ASSERT_EQ(rgn1->base, r1.base);
0412     ASSERT_EQ(rgn1->size, r1.size);
0413 
0414     ASSERT_EQ(rgn2->base, r2.base);
0415     ASSERT_EQ(rgn2->size, r2.size);
0416 
0417     ASSERT_EQ(memblock.reserved.cnt, 2);
0418     ASSERT_EQ(memblock.reserved.total_size, r1.size + r2.size);
0419 
0420     test_pass_pop();
0421 
0422     return 0;
0423 }
0424 
0425 /*
0426  * A test that tries to mark two memory blocks r1 and r2 as reserved,
0427  * where r2 overlaps with the beginning of r1 (that is
0428  * r1.base < r2.base + r2.size):
0429  *
0430  *  |  +--------------+--+--------------+  |
0431  *  |  |       r2     |  |     r1       |  |
0432  *  +--+--------------+--+--------------+--+
0433  *     ^              ^
0434  *     |              |
0435  *     |              r1.base
0436  *     |
0437  *     r2.base
0438  *
0439  * Expect to merge two entries into one region that starts at r2.base and
0440  * has size of two regions minus their intersection. The total size of the
0441  * reserved memory is updated, and the region counter is not updated.
0442  */
0443 static int memblock_reserve_overlap_top_check(void)
0444 {
0445     struct memblock_region *rgn;
0446     phys_addr_t total_size;
0447 
0448     rgn = &memblock.reserved.regions[0];
0449 
0450     struct region r1 = {
0451         .base = SZ_1G,
0452         .size = SZ_1G
0453     };
0454     struct region r2 = {
0455         .base = SZ_128M,
0456         .size = SZ_1G
0457     };
0458 
0459     PREFIX_PUSH();
0460 
0461     total_size = (r1.base - r2.base) + r1.size;
0462 
0463     reset_memblock_regions();
0464     memblock_reserve(r1.base, r1.size);
0465     memblock_reserve(r2.base, r2.size);
0466 
0467     ASSERT_EQ(rgn->base, r2.base);
0468     ASSERT_EQ(rgn->size, total_size);
0469 
0470     ASSERT_EQ(memblock.reserved.cnt, 1);
0471     ASSERT_EQ(memblock.reserved.total_size, total_size);
0472 
0473     test_pass_pop();
0474 
0475     return 0;
0476 }
0477 
0478 /*
0479  * A test that tries to mark two memory blocks r1 and r2 as reserved,
0480  * where r2 overlaps with the end of r1 (that is
0481  * r2.base < r1.base + r1.size):
0482  *
0483  *  |  +--------------+--+--------------+  |
0484  *  |  |       r1     |  |     r2       |  |
0485  *  +--+--------------+--+--------------+--+
0486  *     ^              ^
0487  *     |              |
0488  *     |              r2.base
0489  *     |
0490  *     r1.base
0491  *
0492  * Expect to merge two entries into one region that starts at r1.base and
0493  * has size of two regions minus their intersection. The total size of the
0494  * reserved memory is updated, and the region counter is not updated.
0495  */
0496 static int memblock_reserve_overlap_bottom_check(void)
0497 {
0498     struct memblock_region *rgn;
0499     phys_addr_t total_size;
0500 
0501     rgn = &memblock.reserved.regions[0];
0502 
0503     struct region r1 = {
0504         .base = SZ_2K,
0505         .size = SZ_128K
0506     };
0507     struct region r2 = {
0508         .base = SZ_128K,
0509         .size = SZ_128K
0510     };
0511 
0512     PREFIX_PUSH();
0513 
0514     total_size = (r2.base - r1.base) + r2.size;
0515 
0516     reset_memblock_regions();
0517     memblock_reserve(r1.base, r1.size);
0518     memblock_reserve(r2.base, r2.size);
0519 
0520     ASSERT_EQ(rgn->base, r1.base);
0521     ASSERT_EQ(rgn->size, total_size);
0522 
0523     ASSERT_EQ(memblock.reserved.cnt, 1);
0524     ASSERT_EQ(memblock.reserved.total_size, total_size);
0525 
0526     test_pass_pop();
0527 
0528     return 0;
0529 }
0530 
0531 /*
0532  * A test that tries to mark two memory blocks r1 and r2 as reserved,
0533  * where r2 is within the range of r1 (that is
0534  * (r1.base < r2.base) && (r2.base + r2.size < r1.base + r1.size)):
0535  *
0536  *  | +-----+--+---------------------------|
0537  *  | |     |r2|          r1               |
0538  *  +-+-----+--+---------------------------+
0539  *    ^     ^
0540  *    |     |
0541  *    |     r2.base
0542  *    |
0543  *    r1.base
0544  *
0545  * Expect to merge two entries into one region that stays the same. The
0546  * counter and total size of available memory are not updated.
0547  */
0548 static int memblock_reserve_within_check(void)
0549 {
0550     struct memblock_region *rgn;
0551 
0552     rgn = &memblock.reserved.regions[0];
0553 
0554     struct region r1 = {
0555         .base = SZ_1M,
0556         .size = SZ_8M
0557     };
0558     struct region r2 = {
0559         .base = SZ_2M,
0560         .size = SZ_64K
0561     };
0562 
0563     PREFIX_PUSH();
0564 
0565     reset_memblock_regions();
0566     memblock_reserve(r1.base, r1.size);
0567     memblock_reserve(r2.base, r2.size);
0568 
0569     ASSERT_EQ(rgn->base, r1.base);
0570     ASSERT_EQ(rgn->size, r1.size);
0571 
0572     ASSERT_EQ(memblock.reserved.cnt, 1);
0573     ASSERT_EQ(memblock.reserved.total_size, r1.size);
0574 
0575     test_pass_pop();
0576 
0577     return 0;
0578 }
0579 
0580 /*
0581  * A simple test that tries to reserve the same memory block twice.
0582  * Expect the region counter and total size of reserved memory to not
0583  * be updated.
0584  */
0585 static int memblock_reserve_twice_check(void)
0586 {
0587     struct region r = {
0588         .base = SZ_16K,
0589         .size = SZ_2M
0590     };
0591 
0592     PREFIX_PUSH();
0593 
0594     reset_memblock_regions();
0595 
0596     memblock_reserve(r.base, r.size);
0597     memblock_reserve(r.base, r.size);
0598 
0599     ASSERT_EQ(memblock.reserved.cnt, 1);
0600     ASSERT_EQ(memblock.reserved.total_size, r.size);
0601 
0602     test_pass_pop();
0603 
0604     return 0;
0605 }
0606 
0607 static int memblock_reserve_checks(void)
0608 {
0609     prefix_reset();
0610     prefix_push(FUNC_RESERVE);
0611     test_print("Running %s tests...\n", FUNC_RESERVE);
0612 
0613     memblock_reserve_simple_check();
0614     memblock_reserve_disjoint_check();
0615     memblock_reserve_overlap_top_check();
0616     memblock_reserve_overlap_bottom_check();
0617     memblock_reserve_within_check();
0618     memblock_reserve_twice_check();
0619 
0620     prefix_pop();
0621 
0622     return 0;
0623 }
0624 
0625 /*
0626  * A simple test that tries to remove a region r1 from the array of
0627  * available memory regions. By "removing" a region we mean overwriting it
0628  * with the next region r2 in memblock.memory:
0629  *
0630  *  |  ......          +----------------+  |
0631  *  |  : r1 :          |       r2       |  |
0632  *  +--+----+----------+----------------+--+
0633  *                     ^
0634  *                     |
0635  *                     rgn.base
0636  *
0637  * Expect to add two memory blocks r1 and r2 and then remove r1 so that
0638  * r2 is the first available region. The region counter and total size
0639  * are updated.
0640  */
0641 static int memblock_remove_simple_check(void)
0642 {
0643     struct memblock_region *rgn;
0644 
0645     rgn = &memblock.memory.regions[0];
0646 
0647     struct region r1 = {
0648         .base = SZ_2K,
0649         .size = SZ_4K
0650     };
0651     struct region r2 = {
0652         .base = SZ_128K,
0653         .size = SZ_4M
0654     };
0655 
0656     PREFIX_PUSH();
0657 
0658     reset_memblock_regions();
0659     memblock_add(r1.base, r1.size);
0660     memblock_add(r2.base, r2.size);
0661     memblock_remove(r1.base, r1.size);
0662 
0663     ASSERT_EQ(rgn->base, r2.base);
0664     ASSERT_EQ(rgn->size, r2.size);
0665 
0666     ASSERT_EQ(memblock.memory.cnt, 1);
0667     ASSERT_EQ(memblock.memory.total_size, r2.size);
0668 
0669     test_pass_pop();
0670 
0671     return 0;
0672 }
0673 
0674 /*
0675  * A test that tries to remove a region r2 that was not registered as
0676  * available memory (i.e. has no corresponding entry in memblock.memory):
0677  *
0678  *                     +----------------+
0679  *                     |       r2       |
0680  *                     +----------------+
0681  *  |  +----+                              |
0682  *  |  | r1 |                              |
0683  *  +--+----+------------------------------+
0684  *     ^
0685  *     |
0686  *     rgn.base
0687  *
0688  * Expect the array, regions counter and total size to not be modified.
0689  */
0690 static int memblock_remove_absent_check(void)
0691 {
0692     struct memblock_region *rgn;
0693 
0694     rgn = &memblock.memory.regions[0];
0695 
0696     struct region r1 = {
0697         .base = SZ_512K,
0698         .size = SZ_4M
0699     };
0700     struct region r2 = {
0701         .base = SZ_64M,
0702         .size = SZ_1G
0703     };
0704 
0705     PREFIX_PUSH();
0706 
0707     reset_memblock_regions();
0708     memblock_add(r1.base, r1.size);
0709     memblock_remove(r2.base, r2.size);
0710 
0711     ASSERT_EQ(rgn->base, r1.base);
0712     ASSERT_EQ(rgn->size, r1.size);
0713 
0714     ASSERT_EQ(memblock.memory.cnt, 1);
0715     ASSERT_EQ(memblock.memory.total_size, r1.size);
0716 
0717     test_pass_pop();
0718 
0719     return 0;
0720 }
0721 
0722 /*
0723  * A test that tries to remove a region r2 that overlaps with the
0724  * beginning of the already existing entry r1
0725  * (that is r1.base < r2.base + r2.size):
0726  *
0727  *           +-----------------+
0728  *           |       r2        |
0729  *           +-----------------+
0730  *  |                 .........+--------+  |
0731  *  |                 :     r1 |  rgn   |  |
0732  *  +-----------------+--------+--------+--+
0733  *                    ^        ^
0734  *                    |        |
0735  *                    |        rgn.base
0736  *                    r1.base
0737  *
0738  * Expect that only the intersection of both regions is removed from the
0739  * available memory pool. The regions counter and total size are updated.
0740  */
0741 static int memblock_remove_overlap_top_check(void)
0742 {
0743     struct memblock_region *rgn;
0744     phys_addr_t r1_end, r2_end, total_size;
0745 
0746     rgn = &memblock.memory.regions[0];
0747 
0748     struct region r1 = {
0749         .base = SZ_32M,
0750         .size = SZ_32M
0751     };
0752     struct region r2 = {
0753         .base = SZ_16M,
0754         .size = SZ_32M
0755     };
0756 
0757     PREFIX_PUSH();
0758 
0759     r1_end = r1.base + r1.size;
0760     r2_end = r2.base + r2.size;
0761     total_size = r1_end - r2_end;
0762 
0763     reset_memblock_regions();
0764     memblock_add(r1.base, r1.size);
0765     memblock_remove(r2.base, r2.size);
0766 
0767     ASSERT_EQ(rgn->base, r1.base + r2.base);
0768     ASSERT_EQ(rgn->size, total_size);
0769 
0770     ASSERT_EQ(memblock.memory.cnt, 1);
0771     ASSERT_EQ(memblock.memory.total_size, total_size);
0772 
0773     test_pass_pop();
0774 
0775     return 0;
0776 }
0777 
0778 /*
0779  * A test that tries to remove a region r2 that overlaps with the end of
0780  * the already existing region r1 (that is r2.base < r1.base + r1.size):
0781  *
0782  *        +--------------------------------+
0783  *        |               r2               |
0784  *        +--------------------------------+
0785  *  | +---+.....                           |
0786  *  | |rgn| r1 :                           |
0787  *  +-+---+----+---------------------------+
0788  *    ^
0789  *    |
0790  *    r1.base
0791  *
0792  * Expect that only the intersection of both regions is removed from the
0793  * available memory pool. The regions counter and total size are updated.
0794  */
0795 static int memblock_remove_overlap_bottom_check(void)
0796 {
0797     struct memblock_region *rgn;
0798     phys_addr_t total_size;
0799 
0800     rgn = &memblock.memory.regions[0];
0801 
0802     struct region r1 = {
0803         .base = SZ_2M,
0804         .size = SZ_64M
0805     };
0806     struct region r2 = {
0807         .base = SZ_32M,
0808         .size = SZ_256M
0809     };
0810 
0811     PREFIX_PUSH();
0812 
0813     total_size = r2.base - r1.base;
0814 
0815     reset_memblock_regions();
0816     memblock_add(r1.base, r1.size);
0817     memblock_remove(r2.base, r2.size);
0818 
0819     ASSERT_EQ(rgn->base, r1.base);
0820     ASSERT_EQ(rgn->size, total_size);
0821 
0822     ASSERT_EQ(memblock.memory.cnt, 1);
0823     ASSERT_EQ(memblock.memory.total_size, total_size);
0824 
0825     test_pass_pop();
0826 
0827     return 0;
0828 }
0829 
0830 /*
0831  * A test that tries to remove a region r2 that is within the range of
0832  * the already existing entry r1 (that is
0833  * (r1.base < r2.base) && (r2.base + r2.size < r1.base + r1.size)):
0834  *
0835  *                  +----+
0836  *                  | r2 |
0837  *                  +----+
0838  *  | +-------------+....+---------------+ |
0839  *  | |     rgn1    | r1 |     rgn2      | |
0840  *  +-+-------------+----+---------------+-+
0841  *    ^
0842  *    |
0843  *    r1.base
0844  *
0845  * Expect that the region is split into two - one that ends at r2.base and
0846  * another that starts at r2.base + r2.size, with appropriate sizes. The
0847  * region counter and total size are updated.
0848  */
0849 static int memblock_remove_within_check(void)
0850 {
0851     struct memblock_region *rgn1, *rgn2;
0852     phys_addr_t r1_size, r2_size, total_size;
0853 
0854     rgn1 = &memblock.memory.regions[0];
0855     rgn2 = &memblock.memory.regions[1];
0856 
0857     struct region r1 = {
0858         .base = SZ_1M,
0859         .size = SZ_32M
0860     };
0861     struct region r2 = {
0862         .base = SZ_16M,
0863         .size = SZ_1M
0864     };
0865 
0866     PREFIX_PUSH();
0867 
0868     r1_size = r2.base - r1.base;
0869     r2_size = (r1.base + r1.size) - (r2.base + r2.size);
0870     total_size = r1_size + r2_size;
0871 
0872     reset_memblock_regions();
0873     memblock_add(r1.base, r1.size);
0874     memblock_remove(r2.base, r2.size);
0875 
0876     ASSERT_EQ(rgn1->base, r1.base);
0877     ASSERT_EQ(rgn1->size, r1_size);
0878 
0879     ASSERT_EQ(rgn2->base, r2.base + r2.size);
0880     ASSERT_EQ(rgn2->size, r2_size);
0881 
0882     ASSERT_EQ(memblock.memory.cnt, 2);
0883     ASSERT_EQ(memblock.memory.total_size, total_size);
0884 
0885     test_pass_pop();
0886 
0887     return 0;
0888 }
0889 
0890 static int memblock_remove_checks(void)
0891 {
0892     prefix_reset();
0893     prefix_push(FUNC_REMOVE);
0894     test_print("Running %s tests...\n", FUNC_REMOVE);
0895 
0896     memblock_remove_simple_check();
0897     memblock_remove_absent_check();
0898     memblock_remove_overlap_top_check();
0899     memblock_remove_overlap_bottom_check();
0900     memblock_remove_within_check();
0901 
0902     prefix_pop();
0903 
0904     return 0;
0905 }
0906 
0907 /*
0908  * A simple test that tries to free a memory block r1 that was marked
0909  * earlier as reserved. By "freeing" a region we mean overwriting it with
0910  * the next entry r2 in memblock.reserved:
0911  *
0912  *  |              ......           +----+ |
0913  *  |              : r1 :           | r2 | |
0914  *  +--------------+----+-----------+----+-+
0915  *                                  ^
0916  *                                  |
0917  *                                  rgn.base
0918  *
0919  * Expect to reserve two memory regions and then erase r1 region with the
0920  * value of r2. The region counter and total size are updated.
0921  */
0922 static int memblock_free_simple_check(void)
0923 {
0924     struct memblock_region *rgn;
0925 
0926     rgn = &memblock.reserved.regions[0];
0927 
0928     struct region r1 = {
0929         .base = SZ_4M,
0930         .size = SZ_1M
0931     };
0932     struct region r2 = {
0933         .base = SZ_8M,
0934         .size = SZ_1M
0935     };
0936 
0937     PREFIX_PUSH();
0938 
0939     reset_memblock_regions();
0940     memblock_reserve(r1.base, r1.size);
0941     memblock_reserve(r2.base, r2.size);
0942     memblock_free((void *)r1.base, r1.size);
0943 
0944     ASSERT_EQ(rgn->base, r2.base);
0945     ASSERT_EQ(rgn->size, r2.size);
0946 
0947     ASSERT_EQ(memblock.reserved.cnt, 1);
0948     ASSERT_EQ(memblock.reserved.total_size, r2.size);
0949 
0950     test_pass_pop();
0951 
0952     return 0;
0953 }
0954 
0955 /*
0956  * A test that tries to free a region r2 that was not marked as reserved
0957  * (i.e. has no corresponding entry in memblock.reserved):
0958  *
0959  *                     +----------------+
0960  *                     |       r2       |
0961  *                     +----------------+
0962  *  |  +----+                              |
0963  *  |  | r1 |                              |
0964  *  +--+----+------------------------------+
0965  *     ^
0966  *     |
0967  *     rgn.base
0968  *
0969  * The array, regions counter and total size are not modified.
0970  */
0971 static int memblock_free_absent_check(void)
0972 {
0973     struct memblock_region *rgn;
0974 
0975     rgn = &memblock.reserved.regions[0];
0976 
0977     struct region r1 = {
0978         .base = SZ_2M,
0979         .size = SZ_8K
0980     };
0981     struct region r2 = {
0982         .base = SZ_16M,
0983         .size = SZ_128M
0984     };
0985 
0986     PREFIX_PUSH();
0987 
0988     reset_memblock_regions();
0989     memblock_reserve(r1.base, r1.size);
0990     memblock_free((void *)r2.base, r2.size);
0991 
0992     ASSERT_EQ(rgn->base, r1.base);
0993     ASSERT_EQ(rgn->size, r1.size);
0994 
0995     ASSERT_EQ(memblock.reserved.cnt, 1);
0996     ASSERT_EQ(memblock.reserved.total_size, r1.size);
0997 
0998     test_pass_pop();
0999 
1000     return 0;
1001 }
1002 
1003 /*
1004  * A test that tries to free a region r2 that overlaps with the beginning
1005  * of the already existing entry r1 (that is r1.base < r2.base + r2.size):
1006  *
1007  *     +----+
1008  *     | r2 |
1009  *     +----+
1010  *  |    ...+--------------+               |
1011  *  |    :  |    r1        |               |
1012  *  +----+--+--------------+---------------+
1013  *       ^  ^
1014  *       |  |
1015  *       |  rgn.base
1016  *       |
1017  *       r1.base
1018  *
1019  * Expect that only the intersection of both regions is freed. The
1020  * regions counter and total size are updated.
1021  */
1022 static int memblock_free_overlap_top_check(void)
1023 {
1024     struct memblock_region *rgn;
1025     phys_addr_t total_size;
1026 
1027     rgn = &memblock.reserved.regions[0];
1028 
1029     struct region r1 = {
1030         .base = SZ_8M,
1031         .size = SZ_32M
1032     };
1033     struct region r2 = {
1034         .base = SZ_1M,
1035         .size = SZ_8M
1036     };
1037 
1038     PREFIX_PUSH();
1039 
1040     total_size = (r1.size + r1.base) - (r2.base + r2.size);
1041 
1042     reset_memblock_regions();
1043     memblock_reserve(r1.base, r1.size);
1044     memblock_free((void *)r2.base, r2.size);
1045 
1046     ASSERT_EQ(rgn->base, r2.base + r2.size);
1047     ASSERT_EQ(rgn->size, total_size);
1048 
1049     ASSERT_EQ(memblock.reserved.cnt, 1);
1050     ASSERT_EQ(memblock.reserved.total_size, total_size);
1051 
1052     test_pass_pop();
1053 
1054     return 0;
1055 }
1056 
1057 /*
1058  * A test that tries to free a region r2 that overlaps with the end of
1059  * the already existing entry r1 (that is r2.base < r1.base + r1.size):
1060  *
1061  *                   +----------------+
1062  *                   |       r2       |
1063  *                   +----------------+
1064  *  |    +-----------+.....                |
1065  *  |    |       r1  |    :                |
1066  *  +----+-----------+----+----------------+
1067  *
1068  * Expect that only the intersection of both regions is freed. The
1069  * regions counter and total size are updated.
1070  */
1071 static int memblock_free_overlap_bottom_check(void)
1072 {
1073     struct memblock_region *rgn;
1074     phys_addr_t total_size;
1075 
1076     rgn = &memblock.reserved.regions[0];
1077 
1078     struct region r1 = {
1079         .base = SZ_8M,
1080         .size = SZ_32M
1081     };
1082     struct region r2 = {
1083         .base = SZ_32M,
1084         .size = SZ_32M
1085     };
1086 
1087     PREFIX_PUSH();
1088 
1089     total_size = r2.base - r1.base;
1090 
1091     reset_memblock_regions();
1092     memblock_reserve(r1.base, r1.size);
1093     memblock_free((void *)r2.base, r2.size);
1094 
1095     ASSERT_EQ(rgn->base, r1.base);
1096     ASSERT_EQ(rgn->size, total_size);
1097 
1098     ASSERT_EQ(memblock.reserved.cnt, 1);
1099     ASSERT_EQ(memblock.reserved.total_size, total_size);
1100 
1101     test_pass_pop();
1102 
1103     return 0;
1104 }
1105 
1106 /*
1107  * A test that tries to free a region r2 that is within the range of the
1108  * already existing entry r1 (that is
1109  * (r1.base < r2.base) && (r2.base + r2.size < r1.base + r1.size)):
1110  *
1111  *                    +----+
1112  *                    | r2 |
1113  *                    +----+
1114  *  |    +------------+....+---------------+
1115  *  |    |    rgn1    | r1 |     rgn2      |
1116  *  +----+------------+----+---------------+
1117  *       ^
1118  *       |
1119  *       r1.base
1120  *
1121  * Expect that the region is split into two - one that ends at r2.base and
1122  * another that starts at r2.base + r2.size, with appropriate sizes. The
1123  * region counter and total size fields are updated.
1124  */
1125 static int memblock_free_within_check(void)
1126 {
1127     struct memblock_region *rgn1, *rgn2;
1128     phys_addr_t r1_size, r2_size, total_size;
1129 
1130     rgn1 = &memblock.reserved.regions[0];
1131     rgn2 = &memblock.reserved.regions[1];
1132 
1133     struct region r1 = {
1134         .base = SZ_1M,
1135         .size = SZ_8M
1136     };
1137     struct region r2 = {
1138         .base = SZ_4M,
1139         .size = SZ_1M
1140     };
1141 
1142     PREFIX_PUSH();
1143 
1144     r1_size = r2.base - r1.base;
1145     r2_size = (r1.base + r1.size) - (r2.base + r2.size);
1146     total_size = r1_size + r2_size;
1147 
1148     reset_memblock_regions();
1149     memblock_reserve(r1.base, r1.size);
1150     memblock_free((void *)r2.base, r2.size);
1151 
1152     ASSERT_EQ(rgn1->base, r1.base);
1153     ASSERT_EQ(rgn1->size, r1_size);
1154 
1155     ASSERT_EQ(rgn2->base, r2.base + r2.size);
1156     ASSERT_EQ(rgn2->size, r2_size);
1157 
1158     ASSERT_EQ(memblock.reserved.cnt, 2);
1159     ASSERT_EQ(memblock.reserved.total_size, total_size);
1160 
1161     test_pass_pop();
1162 
1163     return 0;
1164 }
1165 
1166 static int memblock_free_checks(void)
1167 {
1168     prefix_reset();
1169     prefix_push(FUNC_FREE);
1170     test_print("Running %s tests...\n", FUNC_FREE);
1171 
1172     memblock_free_simple_check();
1173     memblock_free_absent_check();
1174     memblock_free_overlap_top_check();
1175     memblock_free_overlap_bottom_check();
1176     memblock_free_within_check();
1177 
1178     prefix_pop();
1179 
1180     return 0;
1181 }
1182 
1183 int memblock_basic_checks(void)
1184 {
1185     memblock_initialization_check();
1186     memblock_add_checks();
1187     memblock_reserve_checks();
1188     memblock_remove_checks();
1189     memblock_free_checks();
1190 
1191     return 0;
1192 }