1f3252a22SKarolina Drobnik // SPDX-License-Identifier: GPL-2.0-or-later
255122e01SMike Rapoport (IBM) #include "basic_api.h"
3f3252a22SKarolina Drobnik #include <string.h>
4f3252a22SKarolina Drobnik #include <linux/memblock.h>
5f3252a22SKarolina Drobnik
6f3252a22SKarolina Drobnik #define EXPECTED_MEMBLOCK_REGIONS 128
776586c00SRebecca Mckeever #define FUNC_ADD "memblock_add"
876586c00SRebecca Mckeever #define FUNC_RESERVE "memblock_reserve"
976586c00SRebecca Mckeever #define FUNC_REMOVE "memblock_remove"
1076586c00SRebecca Mckeever #define FUNC_FREE "memblock_free"
11dcd45ad2SRebecca Mckeever #define FUNC_TRIM "memblock_trim_memory"
12f3252a22SKarolina Drobnik
memblock_initialization_check(void)13f3252a22SKarolina Drobnik static int memblock_initialization_check(void)
14f3252a22SKarolina Drobnik {
1576586c00SRebecca Mckeever PREFIX_PUSH();
16f3252a22SKarolina Drobnik
1776586c00SRebecca Mckeever ASSERT_NE(memblock.memory.regions, NULL);
18721f4a65SWei Yang ASSERT_EQ(memblock.memory.cnt, 0);
1976586c00SRebecca Mckeever ASSERT_EQ(memblock.memory.max, EXPECTED_MEMBLOCK_REGIONS);
2076586c00SRebecca Mckeever ASSERT_EQ(strcmp(memblock.memory.name, "memory"), 0);
21f3252a22SKarolina Drobnik
2276586c00SRebecca Mckeever ASSERT_NE(memblock.reserved.regions, NULL);
23721f4a65SWei Yang ASSERT_EQ(memblock.reserved.cnt, 0);
2476586c00SRebecca Mckeever ASSERT_EQ(memblock.memory.max, EXPECTED_MEMBLOCK_REGIONS);
2576586c00SRebecca Mckeever ASSERT_EQ(strcmp(memblock.reserved.name, "reserved"), 0);
2676586c00SRebecca Mckeever
2776586c00SRebecca Mckeever ASSERT_EQ(memblock.bottom_up, false);
2876586c00SRebecca Mckeever ASSERT_EQ(memblock.current_limit, MEMBLOCK_ALLOC_ANYWHERE);
2976586c00SRebecca Mckeever
3076586c00SRebecca Mckeever test_pass_pop();
31f3252a22SKarolina Drobnik
32f3252a22SKarolina Drobnik return 0;
33f3252a22SKarolina Drobnik }
34f3252a22SKarolina Drobnik
351f1180d4SKarolina Drobnik /*
361f1180d4SKarolina Drobnik * A simple test that adds a memory block of a specified base address
371f1180d4SKarolina Drobnik * and size to the collection of available memory regions (memblock.memory).
3823b5c796SRebecca Mckeever * Expect to create a new entry. The region counter and total memory get
3923b5c796SRebecca Mckeever * updated.
401f1180d4SKarolina Drobnik */
memblock_add_simple_check(void)411f1180d4SKarolina Drobnik static int memblock_add_simple_check(void)
421f1180d4SKarolina Drobnik {
431f1180d4SKarolina Drobnik struct memblock_region *rgn;
441f1180d4SKarolina Drobnik
451f1180d4SKarolina Drobnik rgn = &memblock.memory.regions[0];
461f1180d4SKarolina Drobnik
471f1180d4SKarolina Drobnik struct region r = {
481f1180d4SKarolina Drobnik .base = SZ_1G,
491f1180d4SKarolina Drobnik .size = SZ_4M
501f1180d4SKarolina Drobnik };
511f1180d4SKarolina Drobnik
5276586c00SRebecca Mckeever PREFIX_PUSH();
5376586c00SRebecca Mckeever
542c3dacbaSKarolina Drobnik reset_memblock_regions();
551f1180d4SKarolina Drobnik memblock_add(r.base, r.size);
561f1180d4SKarolina Drobnik
5776586c00SRebecca Mckeever ASSERT_EQ(rgn->base, r.base);
5876586c00SRebecca Mckeever ASSERT_EQ(rgn->size, r.size);
591f1180d4SKarolina Drobnik
6076586c00SRebecca Mckeever ASSERT_EQ(memblock.memory.cnt, 1);
6176586c00SRebecca Mckeever ASSERT_EQ(memblock.memory.total_size, r.size);
6276586c00SRebecca Mckeever
6376586c00SRebecca Mckeever test_pass_pop();
641f1180d4SKarolina Drobnik
651f1180d4SKarolina Drobnik return 0;
661f1180d4SKarolina Drobnik }
671f1180d4SKarolina Drobnik
681f1180d4SKarolina Drobnik /*
6923b5c796SRebecca Mckeever * A simple test that adds a memory block of a specified base address, size,
70e393c093SKarolina Drobnik * NUMA node and memory flags to the collection of available memory regions.
7123b5c796SRebecca Mckeever * Expect to create a new entry. The region counter and total memory get
7223b5c796SRebecca Mckeever * updated.
73e393c093SKarolina Drobnik */
memblock_add_node_simple_check(void)74e393c093SKarolina Drobnik static int memblock_add_node_simple_check(void)
75e393c093SKarolina Drobnik {
76e393c093SKarolina Drobnik struct memblock_region *rgn;
77e393c093SKarolina Drobnik
78e393c093SKarolina Drobnik rgn = &memblock.memory.regions[0];
79e393c093SKarolina Drobnik
80e393c093SKarolina Drobnik struct region r = {
81e393c093SKarolina Drobnik .base = SZ_1M,
82e393c093SKarolina Drobnik .size = SZ_16M
83e393c093SKarolina Drobnik };
84e393c093SKarolina Drobnik
8576586c00SRebecca Mckeever PREFIX_PUSH();
8676586c00SRebecca Mckeever
872c3dacbaSKarolina Drobnik reset_memblock_regions();
88e393c093SKarolina Drobnik memblock_add_node(r.base, r.size, 1, MEMBLOCK_HOTPLUG);
89e393c093SKarolina Drobnik
9076586c00SRebecca Mckeever ASSERT_EQ(rgn->base, r.base);
9176586c00SRebecca Mckeever ASSERT_EQ(rgn->size, r.size);
92e393c093SKarolina Drobnik #ifdef CONFIG_NUMA
9376586c00SRebecca Mckeever ASSERT_EQ(rgn->nid, 1);
94e393c093SKarolina Drobnik #endif
9576586c00SRebecca Mckeever ASSERT_EQ(rgn->flags, MEMBLOCK_HOTPLUG);
96e393c093SKarolina Drobnik
9776586c00SRebecca Mckeever ASSERT_EQ(memblock.memory.cnt, 1);
9876586c00SRebecca Mckeever ASSERT_EQ(memblock.memory.total_size, r.size);
9976586c00SRebecca Mckeever
10076586c00SRebecca Mckeever test_pass_pop();
101e393c093SKarolina Drobnik
102e393c093SKarolina Drobnik return 0;
103e393c093SKarolina Drobnik }
104e393c093SKarolina Drobnik
105e393c093SKarolina Drobnik /*
1061f1180d4SKarolina Drobnik * A test that tries to add two memory blocks that don't overlap with one
10723b5c796SRebecca Mckeever * another:
10823b5c796SRebecca Mckeever *
10923b5c796SRebecca Mckeever * | +--------+ +--------+ |
11023b5c796SRebecca Mckeever * | | r1 | | r2 | |
11123b5c796SRebecca Mckeever * +--------+--------+--------+--------+--+
11223b5c796SRebecca Mckeever *
11323b5c796SRebecca Mckeever * Expect to add two correctly initialized entries to the collection of
11423b5c796SRebecca Mckeever * available memory regions (memblock.memory). The total size and
11523b5c796SRebecca Mckeever * region counter fields get updated.
1161f1180d4SKarolina Drobnik */
memblock_add_disjoint_check(void)1171f1180d4SKarolina Drobnik static int memblock_add_disjoint_check(void)
1181f1180d4SKarolina Drobnik {
1191f1180d4SKarolina Drobnik struct memblock_region *rgn1, *rgn2;
1201f1180d4SKarolina Drobnik
1211f1180d4SKarolina Drobnik rgn1 = &memblock.memory.regions[0];
1221f1180d4SKarolina Drobnik rgn2 = &memblock.memory.regions[1];
1231f1180d4SKarolina Drobnik
1241f1180d4SKarolina Drobnik struct region r1 = {
1251f1180d4SKarolina Drobnik .base = SZ_1G,
1261f1180d4SKarolina Drobnik .size = SZ_8K
1271f1180d4SKarolina Drobnik };
1281f1180d4SKarolina Drobnik struct region r2 = {
1291f1180d4SKarolina Drobnik .base = SZ_1G + SZ_16K,
1301f1180d4SKarolina Drobnik .size = SZ_8K
1311f1180d4SKarolina Drobnik };
1321f1180d4SKarolina Drobnik
13376586c00SRebecca Mckeever PREFIX_PUSH();
13476586c00SRebecca Mckeever
1352c3dacbaSKarolina Drobnik reset_memblock_regions();
1361f1180d4SKarolina Drobnik memblock_add(r1.base, r1.size);
1371f1180d4SKarolina Drobnik memblock_add(r2.base, r2.size);
1381f1180d4SKarolina Drobnik
13976586c00SRebecca Mckeever ASSERT_EQ(rgn1->base, r1.base);
14076586c00SRebecca Mckeever ASSERT_EQ(rgn1->size, r1.size);
1411f1180d4SKarolina Drobnik
14276586c00SRebecca Mckeever ASSERT_EQ(rgn2->base, r2.base);
14376586c00SRebecca Mckeever ASSERT_EQ(rgn2->size, r2.size);
1441f1180d4SKarolina Drobnik
14576586c00SRebecca Mckeever ASSERT_EQ(memblock.memory.cnt, 2);
14676586c00SRebecca Mckeever ASSERT_EQ(memblock.memory.total_size, r1.size + r2.size);
14776586c00SRebecca Mckeever
14876586c00SRebecca Mckeever test_pass_pop();
1491f1180d4SKarolina Drobnik
1501f1180d4SKarolina Drobnik return 0;
1511f1180d4SKarolina Drobnik }
1521f1180d4SKarolina Drobnik
1531f1180d4SKarolina Drobnik /*
15423b5c796SRebecca Mckeever * A test that tries to add two memory blocks r1 and r2, where r2 overlaps
15523b5c796SRebecca Mckeever * with the beginning of r1 (that is r1.base < r2.base + r2.size):
15623b5c796SRebecca Mckeever *
15723b5c796SRebecca Mckeever * | +----+----+------------+ |
15823b5c796SRebecca Mckeever * | | |r2 | r1 | |
15923b5c796SRebecca Mckeever * +----+----+----+------------+----------+
16023b5c796SRebecca Mckeever * ^ ^
16123b5c796SRebecca Mckeever * | |
16223b5c796SRebecca Mckeever * | r1.base
16323b5c796SRebecca Mckeever * |
16423b5c796SRebecca Mckeever * r2.base
16523b5c796SRebecca Mckeever *
16623b5c796SRebecca Mckeever * Expect to merge the two entries into one region that starts at r2.base
16723b5c796SRebecca Mckeever * and has size of two regions minus their intersection. The total size of
16823b5c796SRebecca Mckeever * the available memory is updated, and the region counter stays the same.
1691f1180d4SKarolina Drobnik */
memblock_add_overlap_top_check(void)1701f1180d4SKarolina Drobnik static int memblock_add_overlap_top_check(void)
1711f1180d4SKarolina Drobnik {
1721f1180d4SKarolina Drobnik struct memblock_region *rgn;
1731f1180d4SKarolina Drobnik phys_addr_t total_size;
1741f1180d4SKarolina Drobnik
1751f1180d4SKarolina Drobnik rgn = &memblock.memory.regions[0];
1761f1180d4SKarolina Drobnik
1771f1180d4SKarolina Drobnik struct region r1 = {
1781f1180d4SKarolina Drobnik .base = SZ_512M,
1791f1180d4SKarolina Drobnik .size = SZ_1G
1801f1180d4SKarolina Drobnik };
1811f1180d4SKarolina Drobnik struct region r2 = {
1821f1180d4SKarolina Drobnik .base = SZ_256M,
1831f1180d4SKarolina Drobnik .size = SZ_512M
1841f1180d4SKarolina Drobnik };
1851f1180d4SKarolina Drobnik
18676586c00SRebecca Mckeever PREFIX_PUSH();
18776586c00SRebecca Mckeever
1881f1180d4SKarolina Drobnik total_size = (r1.base - r2.base) + r1.size;
1891f1180d4SKarolina Drobnik
1902c3dacbaSKarolina Drobnik reset_memblock_regions();
1911f1180d4SKarolina Drobnik memblock_add(r1.base, r1.size);
1921f1180d4SKarolina Drobnik memblock_add(r2.base, r2.size);
1931f1180d4SKarolina Drobnik
19476586c00SRebecca Mckeever ASSERT_EQ(rgn->base, r2.base);
19576586c00SRebecca Mckeever ASSERT_EQ(rgn->size, total_size);
1961f1180d4SKarolina Drobnik
19776586c00SRebecca Mckeever ASSERT_EQ(memblock.memory.cnt, 1);
19876586c00SRebecca Mckeever ASSERT_EQ(memblock.memory.total_size, total_size);
19976586c00SRebecca Mckeever
20076586c00SRebecca Mckeever test_pass_pop();
2011f1180d4SKarolina Drobnik
2021f1180d4SKarolina Drobnik return 0;
2031f1180d4SKarolina Drobnik }
2041f1180d4SKarolina Drobnik
2051f1180d4SKarolina Drobnik /*
20623b5c796SRebecca Mckeever * A test that tries to add two memory blocks r1 and r2, where r2 overlaps
20723b5c796SRebecca Mckeever * with the end of r1 (that is r2.base < r1.base + r1.size):
20823b5c796SRebecca Mckeever *
20923b5c796SRebecca Mckeever * | +--+------+----------+ |
21023b5c796SRebecca Mckeever * | | | r1 | r2 | |
21123b5c796SRebecca Mckeever * +--+--+------+----------+--------------+
21223b5c796SRebecca Mckeever * ^ ^
21323b5c796SRebecca Mckeever * | |
21423b5c796SRebecca Mckeever * | r2.base
21523b5c796SRebecca Mckeever * |
21623b5c796SRebecca Mckeever * r1.base
21723b5c796SRebecca Mckeever *
21823b5c796SRebecca Mckeever * Expect to merge the two entries into one region that starts at r1.base
21923b5c796SRebecca Mckeever * and has size of two regions minus their intersection. The total size of
22023b5c796SRebecca Mckeever * the available memory is updated, and the region counter stays the same.
2211f1180d4SKarolina Drobnik */
memblock_add_overlap_bottom_check(void)2221f1180d4SKarolina Drobnik static int memblock_add_overlap_bottom_check(void)
2231f1180d4SKarolina Drobnik {
2241f1180d4SKarolina Drobnik struct memblock_region *rgn;
2251f1180d4SKarolina Drobnik phys_addr_t total_size;
2261f1180d4SKarolina Drobnik
2271f1180d4SKarolina Drobnik rgn = &memblock.memory.regions[0];
2281f1180d4SKarolina Drobnik
2291f1180d4SKarolina Drobnik struct region r1 = {
2301f1180d4SKarolina Drobnik .base = SZ_128M,
2311f1180d4SKarolina Drobnik .size = SZ_512M
2321f1180d4SKarolina Drobnik };
2331f1180d4SKarolina Drobnik struct region r2 = {
2341f1180d4SKarolina Drobnik .base = SZ_256M,
2351f1180d4SKarolina Drobnik .size = SZ_1G
2361f1180d4SKarolina Drobnik };
2371f1180d4SKarolina Drobnik
23876586c00SRebecca Mckeever PREFIX_PUSH();
23976586c00SRebecca Mckeever
2401f1180d4SKarolina Drobnik total_size = (r2.base - r1.base) + r2.size;
2411f1180d4SKarolina Drobnik
2422c3dacbaSKarolina Drobnik reset_memblock_regions();
2431f1180d4SKarolina Drobnik memblock_add(r1.base, r1.size);
2441f1180d4SKarolina Drobnik memblock_add(r2.base, r2.size);
2451f1180d4SKarolina Drobnik
24676586c00SRebecca Mckeever ASSERT_EQ(rgn->base, r1.base);
24776586c00SRebecca Mckeever ASSERT_EQ(rgn->size, total_size);
2481f1180d4SKarolina Drobnik
24976586c00SRebecca Mckeever ASSERT_EQ(memblock.memory.cnt, 1);
25076586c00SRebecca Mckeever ASSERT_EQ(memblock.memory.total_size, total_size);
25176586c00SRebecca Mckeever
25276586c00SRebecca Mckeever test_pass_pop();
2531f1180d4SKarolina Drobnik
2541f1180d4SKarolina Drobnik return 0;
2551f1180d4SKarolina Drobnik }
2561f1180d4SKarolina Drobnik
2571f1180d4SKarolina Drobnik /*
25823b5c796SRebecca Mckeever * A test that tries to add two memory blocks r1 and r2, where r2 is
25923b5c796SRebecca Mckeever * within the range of r1 (that is r1.base < r2.base &&
26023b5c796SRebecca Mckeever * r2.base + r2.size < r1.base + r1.size):
26123b5c796SRebecca Mckeever *
26223b5c796SRebecca Mckeever * | +-------+--+-----------------------+
26323b5c796SRebecca Mckeever * | | |r2| r1 |
26423b5c796SRebecca Mckeever * +---+-------+--+-----------------------+
26523b5c796SRebecca Mckeever * ^
26623b5c796SRebecca Mckeever * |
26723b5c796SRebecca Mckeever * r1.base
26823b5c796SRebecca Mckeever *
26923b5c796SRebecca Mckeever * Expect to merge two entries into one region that stays the same.
27023b5c796SRebecca Mckeever * The counter and total size of available memory are not updated.
2711f1180d4SKarolina Drobnik */
memblock_add_within_check(void)2721f1180d4SKarolina Drobnik static int memblock_add_within_check(void)
2731f1180d4SKarolina Drobnik {
2741f1180d4SKarolina Drobnik struct memblock_region *rgn;
2751f1180d4SKarolina Drobnik
2761f1180d4SKarolina Drobnik rgn = &memblock.memory.regions[0];
2771f1180d4SKarolina Drobnik
2781f1180d4SKarolina Drobnik struct region r1 = {
2791f1180d4SKarolina Drobnik .base = SZ_8M,
2801f1180d4SKarolina Drobnik .size = SZ_32M
2811f1180d4SKarolina Drobnik };
2821f1180d4SKarolina Drobnik struct region r2 = {
2831f1180d4SKarolina Drobnik .base = SZ_16M,
2841f1180d4SKarolina Drobnik .size = SZ_1M
2851f1180d4SKarolina Drobnik };
2861f1180d4SKarolina Drobnik
28776586c00SRebecca Mckeever PREFIX_PUSH();
28876586c00SRebecca Mckeever
2892c3dacbaSKarolina Drobnik reset_memblock_regions();
2901f1180d4SKarolina Drobnik memblock_add(r1.base, r1.size);
2911f1180d4SKarolina Drobnik memblock_add(r2.base, r2.size);
2921f1180d4SKarolina Drobnik
29376586c00SRebecca Mckeever ASSERT_EQ(rgn->base, r1.base);
29476586c00SRebecca Mckeever ASSERT_EQ(rgn->size, r1.size);
2951f1180d4SKarolina Drobnik
29676586c00SRebecca Mckeever ASSERT_EQ(memblock.memory.cnt, 1);
29776586c00SRebecca Mckeever ASSERT_EQ(memblock.memory.total_size, r1.size);
29876586c00SRebecca Mckeever
29976586c00SRebecca Mckeever test_pass_pop();
3001f1180d4SKarolina Drobnik
3011f1180d4SKarolina Drobnik return 0;
3021f1180d4SKarolina Drobnik }
3031f1180d4SKarolina Drobnik
3041f1180d4SKarolina Drobnik /*
30523b5c796SRebecca Mckeever * A simple test that tries to add the same memory block twice. Expect
30623b5c796SRebecca Mckeever * the counter and total size of available memory to not be updated.
3071f1180d4SKarolina Drobnik */
memblock_add_twice_check(void)3081f1180d4SKarolina Drobnik static int memblock_add_twice_check(void)
3091f1180d4SKarolina Drobnik {
3101f1180d4SKarolina Drobnik struct region r = {
3111f1180d4SKarolina Drobnik .base = SZ_16K,
3121f1180d4SKarolina Drobnik .size = SZ_2M
3131f1180d4SKarolina Drobnik };
3141f1180d4SKarolina Drobnik
31576586c00SRebecca Mckeever PREFIX_PUSH();
31676586c00SRebecca Mckeever
3172c3dacbaSKarolina Drobnik reset_memblock_regions();
3181f1180d4SKarolina Drobnik
3191f1180d4SKarolina Drobnik memblock_add(r.base, r.size);
3201f1180d4SKarolina Drobnik memblock_add(r.base, r.size);
3211f1180d4SKarolina Drobnik
32276586c00SRebecca Mckeever ASSERT_EQ(memblock.memory.cnt, 1);
32376586c00SRebecca Mckeever ASSERT_EQ(memblock.memory.total_size, r.size);
32476586c00SRebecca Mckeever
32576586c00SRebecca Mckeever test_pass_pop();
3261f1180d4SKarolina Drobnik
3271f1180d4SKarolina Drobnik return 0;
3281f1180d4SKarolina Drobnik }
3291f1180d4SKarolina Drobnik
33021a233f6SRebecca Mckeever /*
33121a233f6SRebecca Mckeever * A test that tries to add two memory blocks that don't overlap with one
33221a233f6SRebecca Mckeever * another and then add a third memory block in the space between the first two:
33321a233f6SRebecca Mckeever *
33421a233f6SRebecca Mckeever * | +--------+--------+--------+ |
33521a233f6SRebecca Mckeever * | | r1 | r3 | r2 | |
33621a233f6SRebecca Mckeever * +--------+--------+--------+--------+--+
33721a233f6SRebecca Mckeever *
33821a233f6SRebecca Mckeever * Expect to merge the three entries into one region that starts at r1.base
33921a233f6SRebecca Mckeever * and has size of r1.size + r2.size + r3.size. The region counter and total
34021a233f6SRebecca Mckeever * size of the available memory are updated.
34121a233f6SRebecca Mckeever */
memblock_add_between_check(void)34221a233f6SRebecca Mckeever static int memblock_add_between_check(void)
34321a233f6SRebecca Mckeever {
34421a233f6SRebecca Mckeever struct memblock_region *rgn;
34521a233f6SRebecca Mckeever phys_addr_t total_size;
34621a233f6SRebecca Mckeever
34721a233f6SRebecca Mckeever rgn = &memblock.memory.regions[0];
34821a233f6SRebecca Mckeever
34921a233f6SRebecca Mckeever struct region r1 = {
35021a233f6SRebecca Mckeever .base = SZ_1G,
35121a233f6SRebecca Mckeever .size = SZ_8K
35221a233f6SRebecca Mckeever };
35321a233f6SRebecca Mckeever struct region r2 = {
35421a233f6SRebecca Mckeever .base = SZ_1G + SZ_16K,
35521a233f6SRebecca Mckeever .size = SZ_8K
35621a233f6SRebecca Mckeever };
35721a233f6SRebecca Mckeever struct region r3 = {
35821a233f6SRebecca Mckeever .base = SZ_1G + SZ_8K,
35921a233f6SRebecca Mckeever .size = SZ_8K
36021a233f6SRebecca Mckeever };
36121a233f6SRebecca Mckeever
36221a233f6SRebecca Mckeever PREFIX_PUSH();
36321a233f6SRebecca Mckeever
36421a233f6SRebecca Mckeever total_size = r1.size + r2.size + r3.size;
36521a233f6SRebecca Mckeever
36621a233f6SRebecca Mckeever reset_memblock_regions();
36721a233f6SRebecca Mckeever memblock_add(r1.base, r1.size);
36821a233f6SRebecca Mckeever memblock_add(r2.base, r2.size);
36921a233f6SRebecca Mckeever memblock_add(r3.base, r3.size);
37021a233f6SRebecca Mckeever
37121a233f6SRebecca Mckeever ASSERT_EQ(rgn->base, r1.base);
37221a233f6SRebecca Mckeever ASSERT_EQ(rgn->size, total_size);
37321a233f6SRebecca Mckeever
37421a233f6SRebecca Mckeever ASSERT_EQ(memblock.memory.cnt, 1);
37521a233f6SRebecca Mckeever ASSERT_EQ(memblock.memory.total_size, total_size);
37621a233f6SRebecca Mckeever
37721a233f6SRebecca Mckeever test_pass_pop();
37821a233f6SRebecca Mckeever
37921a233f6SRebecca Mckeever return 0;
38021a233f6SRebecca Mckeever }
38121a233f6SRebecca Mckeever
38221a233f6SRebecca Mckeever /*
38321a233f6SRebecca Mckeever * A simple test that tries to add a memory block r when r extends past
38421a233f6SRebecca Mckeever * PHYS_ADDR_MAX:
38521a233f6SRebecca Mckeever *
38621a233f6SRebecca Mckeever * +--------+
38721a233f6SRebecca Mckeever * | r |
38821a233f6SRebecca Mckeever * +--------+
38921a233f6SRebecca Mckeever * | +----+
39021a233f6SRebecca Mckeever * | | rgn|
39121a233f6SRebecca Mckeever * +----------------------------+----+
39221a233f6SRebecca Mckeever *
39321a233f6SRebecca Mckeever * Expect to add a memory block of size PHYS_ADDR_MAX - r.base. Expect the
39421a233f6SRebecca Mckeever * total size of available memory and the counter to be updated.
39521a233f6SRebecca Mckeever */
memblock_add_near_max_check(void)39621a233f6SRebecca Mckeever static int memblock_add_near_max_check(void)
39721a233f6SRebecca Mckeever {
39821a233f6SRebecca Mckeever struct memblock_region *rgn;
39921a233f6SRebecca Mckeever phys_addr_t total_size;
40021a233f6SRebecca Mckeever
40121a233f6SRebecca Mckeever rgn = &memblock.memory.regions[0];
40221a233f6SRebecca Mckeever
40321a233f6SRebecca Mckeever struct region r = {
40421a233f6SRebecca Mckeever .base = PHYS_ADDR_MAX - SZ_1M,
40521a233f6SRebecca Mckeever .size = SZ_2M
40621a233f6SRebecca Mckeever };
40721a233f6SRebecca Mckeever
40821a233f6SRebecca Mckeever PREFIX_PUSH();
40921a233f6SRebecca Mckeever
41021a233f6SRebecca Mckeever total_size = PHYS_ADDR_MAX - r.base;
41121a233f6SRebecca Mckeever
41221a233f6SRebecca Mckeever reset_memblock_regions();
41321a233f6SRebecca Mckeever memblock_add(r.base, r.size);
41421a233f6SRebecca Mckeever
41521a233f6SRebecca Mckeever ASSERT_EQ(rgn->base, r.base);
41621a233f6SRebecca Mckeever ASSERT_EQ(rgn->size, total_size);
41721a233f6SRebecca Mckeever
41821a233f6SRebecca Mckeever ASSERT_EQ(memblock.memory.cnt, 1);
41921a233f6SRebecca Mckeever ASSERT_EQ(memblock.memory.total_size, total_size);
42021a233f6SRebecca Mckeever
42121a233f6SRebecca Mckeever test_pass_pop();
42221a233f6SRebecca Mckeever
42321a233f6SRebecca Mckeever return 0;
42421a233f6SRebecca Mckeever }
42521a233f6SRebecca Mckeever
426085bdaa6SShaoqin Huang /*
427085bdaa6SShaoqin Huang * A test that trying to add the 129th memory block.
428085bdaa6SShaoqin Huang * Expect to trigger memblock_double_array() to double the
429085bdaa6SShaoqin Huang * memblock.memory.max, find a new valid memory as
430085bdaa6SShaoqin Huang * memory.regions.
431085bdaa6SShaoqin Huang */
memblock_add_many_check(void)432085bdaa6SShaoqin Huang static int memblock_add_many_check(void)
433085bdaa6SShaoqin Huang {
434085bdaa6SShaoqin Huang int i;
435085bdaa6SShaoqin Huang void *orig_region;
436085bdaa6SShaoqin Huang struct region r = {
437085bdaa6SShaoqin Huang .base = SZ_16K,
438085bdaa6SShaoqin Huang .size = SZ_16K,
439085bdaa6SShaoqin Huang };
440085bdaa6SShaoqin Huang phys_addr_t new_memory_regions_size;
441085bdaa6SShaoqin Huang phys_addr_t base, size = SZ_64;
442085bdaa6SShaoqin Huang phys_addr_t gap_size = SZ_64;
443085bdaa6SShaoqin Huang
444085bdaa6SShaoqin Huang PREFIX_PUSH();
445085bdaa6SShaoqin Huang
446085bdaa6SShaoqin Huang reset_memblock_regions();
447085bdaa6SShaoqin Huang memblock_allow_resize();
448085bdaa6SShaoqin Huang
449085bdaa6SShaoqin Huang dummy_physical_memory_init();
450085bdaa6SShaoqin Huang /*
451085bdaa6SShaoqin Huang * We allocated enough memory by using dummy_physical_memory_init(), and
452085bdaa6SShaoqin Huang * split it into small block. First we split a large enough memory block
453085bdaa6SShaoqin Huang * as the memory region which will be choosed by memblock_double_array().
454085bdaa6SShaoqin Huang */
455085bdaa6SShaoqin Huang base = PAGE_ALIGN(dummy_physical_memory_base());
456085bdaa6SShaoqin Huang new_memory_regions_size = PAGE_ALIGN(INIT_MEMBLOCK_REGIONS * 2 *
457085bdaa6SShaoqin Huang sizeof(struct memblock_region));
458085bdaa6SShaoqin Huang memblock_add(base, new_memory_regions_size);
459085bdaa6SShaoqin Huang
460085bdaa6SShaoqin Huang /* This is the base of small memory block. */
461085bdaa6SShaoqin Huang base += new_memory_regions_size + gap_size;
462085bdaa6SShaoqin Huang
463085bdaa6SShaoqin Huang orig_region = memblock.memory.regions;
464085bdaa6SShaoqin Huang
465085bdaa6SShaoqin Huang for (i = 0; i < INIT_MEMBLOCK_REGIONS; i++) {
466085bdaa6SShaoqin Huang /*
467085bdaa6SShaoqin Huang * Add these small block to fulfill the memblock. We keep a
468085bdaa6SShaoqin Huang * gap between the nearby memory to avoid being merged.
469085bdaa6SShaoqin Huang */
470085bdaa6SShaoqin Huang memblock_add(base, size);
471085bdaa6SShaoqin Huang base += size + gap_size;
472085bdaa6SShaoqin Huang
473085bdaa6SShaoqin Huang ASSERT_EQ(memblock.memory.cnt, i + 2);
474085bdaa6SShaoqin Huang ASSERT_EQ(memblock.memory.total_size, new_memory_regions_size +
475085bdaa6SShaoqin Huang (i + 1) * size);
476085bdaa6SShaoqin Huang }
477085bdaa6SShaoqin Huang
478085bdaa6SShaoqin Huang /*
479085bdaa6SShaoqin Huang * At there, memblock_double_array() has been succeed, check if it
480085bdaa6SShaoqin Huang * update the memory.max.
481085bdaa6SShaoqin Huang */
482085bdaa6SShaoqin Huang ASSERT_EQ(memblock.memory.max, INIT_MEMBLOCK_REGIONS * 2);
483085bdaa6SShaoqin Huang
484085bdaa6SShaoqin Huang /* memblock_double_array() will reserve the memory it used. Check it. */
485085bdaa6SShaoqin Huang ASSERT_EQ(memblock.reserved.cnt, 1);
486085bdaa6SShaoqin Huang ASSERT_EQ(memblock.reserved.total_size, new_memory_regions_size);
487085bdaa6SShaoqin Huang
488085bdaa6SShaoqin Huang /*
489085bdaa6SShaoqin Huang * Now memblock_double_array() works fine. Let's check after the
490085bdaa6SShaoqin Huang * double_array(), the memblock_add() still works as normal.
491085bdaa6SShaoqin Huang */
492085bdaa6SShaoqin Huang memblock_add(r.base, r.size);
493085bdaa6SShaoqin Huang ASSERT_EQ(memblock.memory.regions[0].base, r.base);
494085bdaa6SShaoqin Huang ASSERT_EQ(memblock.memory.regions[0].size, r.size);
495085bdaa6SShaoqin Huang
496085bdaa6SShaoqin Huang ASSERT_EQ(memblock.memory.cnt, INIT_MEMBLOCK_REGIONS + 2);
497085bdaa6SShaoqin Huang ASSERT_EQ(memblock.memory.total_size, INIT_MEMBLOCK_REGIONS * size +
498085bdaa6SShaoqin Huang new_memory_regions_size +
499085bdaa6SShaoqin Huang r.size);
500085bdaa6SShaoqin Huang ASSERT_EQ(memblock.memory.max, INIT_MEMBLOCK_REGIONS * 2);
501085bdaa6SShaoqin Huang
502085bdaa6SShaoqin Huang dummy_physical_memory_cleanup();
503085bdaa6SShaoqin Huang
504085bdaa6SShaoqin Huang /*
505085bdaa6SShaoqin Huang * The current memory.regions is occupying a range of memory that
506085bdaa6SShaoqin Huang * allocated from dummy_physical_memory_init(). After free the memory,
507085bdaa6SShaoqin Huang * we must not use it. So restore the origin memory region to make sure
508085bdaa6SShaoqin Huang * the tests can run as normal and not affected by the double array.
509085bdaa6SShaoqin Huang */
510085bdaa6SShaoqin Huang memblock.memory.regions = orig_region;
511085bdaa6SShaoqin Huang memblock.memory.cnt = INIT_MEMBLOCK_REGIONS;
512085bdaa6SShaoqin Huang
513085bdaa6SShaoqin Huang test_pass_pop();
514085bdaa6SShaoqin Huang
515085bdaa6SShaoqin Huang return 0;
516085bdaa6SShaoqin Huang }
517085bdaa6SShaoqin Huang
memblock_add_checks(void)5181f1180d4SKarolina Drobnik static int memblock_add_checks(void)
5191f1180d4SKarolina Drobnik {
52076586c00SRebecca Mckeever prefix_reset();
52176586c00SRebecca Mckeever prefix_push(FUNC_ADD);
52276586c00SRebecca Mckeever test_print("Running %s tests...\n", FUNC_ADD);
52376586c00SRebecca Mckeever
5241f1180d4SKarolina Drobnik memblock_add_simple_check();
525e393c093SKarolina Drobnik memblock_add_node_simple_check();
5261f1180d4SKarolina Drobnik memblock_add_disjoint_check();
5271f1180d4SKarolina Drobnik memblock_add_overlap_top_check();
5281f1180d4SKarolina Drobnik memblock_add_overlap_bottom_check();
5291f1180d4SKarolina Drobnik memblock_add_within_check();
5301f1180d4SKarolina Drobnik memblock_add_twice_check();
53121a233f6SRebecca Mckeever memblock_add_between_check();
53221a233f6SRebecca Mckeever memblock_add_near_max_check();
533085bdaa6SShaoqin Huang memblock_add_many_check();
5341f1180d4SKarolina Drobnik
53576586c00SRebecca Mckeever prefix_pop();
53676586c00SRebecca Mckeever
5371f1180d4SKarolina Drobnik return 0;
5381f1180d4SKarolina Drobnik }
5391f1180d4SKarolina Drobnik
54083787a80SKarolina Drobnik /*
54183787a80SKarolina Drobnik * A simple test that marks a memory block of a specified base address
54283787a80SKarolina Drobnik * and size as reserved and to the collection of reserved memory regions
543e4f76c8dSRebecca Mckeever * (memblock.reserved). Expect to create a new entry. The region counter
544e4f76c8dSRebecca Mckeever * and total memory size are updated.
54583787a80SKarolina Drobnik */
memblock_reserve_simple_check(void)54683787a80SKarolina Drobnik static int memblock_reserve_simple_check(void)
54783787a80SKarolina Drobnik {
54883787a80SKarolina Drobnik struct memblock_region *rgn;
54983787a80SKarolina Drobnik
55083787a80SKarolina Drobnik rgn = &memblock.reserved.regions[0];
55183787a80SKarolina Drobnik
55283787a80SKarolina Drobnik struct region r = {
55383787a80SKarolina Drobnik .base = SZ_2G,
55483787a80SKarolina Drobnik .size = SZ_128M
55583787a80SKarolina Drobnik };
55683787a80SKarolina Drobnik
55776586c00SRebecca Mckeever PREFIX_PUSH();
55876586c00SRebecca Mckeever
5592c3dacbaSKarolina Drobnik reset_memblock_regions();
56083787a80SKarolina Drobnik memblock_reserve(r.base, r.size);
56183787a80SKarolina Drobnik
56276586c00SRebecca Mckeever ASSERT_EQ(rgn->base, r.base);
56376586c00SRebecca Mckeever ASSERT_EQ(rgn->size, r.size);
56476586c00SRebecca Mckeever
56576586c00SRebecca Mckeever test_pass_pop();
56683787a80SKarolina Drobnik
56783787a80SKarolina Drobnik return 0;
56883787a80SKarolina Drobnik }
56983787a80SKarolina Drobnik
57083787a80SKarolina Drobnik /*
571e4f76c8dSRebecca Mckeever * A test that tries to mark two memory blocks that don't overlap as reserved:
572e4f76c8dSRebecca Mckeever *
573e4f76c8dSRebecca Mckeever * | +--+ +----------------+ |
574e4f76c8dSRebecca Mckeever * | |r1| | r2 | |
575e4f76c8dSRebecca Mckeever * +--------+--+------+----------------+--+
576e4f76c8dSRebecca Mckeever *
577e4f76c8dSRebecca Mckeever * Expect to add two entries to the collection of reserved memory regions
578e4f76c8dSRebecca Mckeever * (memblock.reserved). The total size and region counter for
579e4f76c8dSRebecca Mckeever * memblock.reserved are updated.
58083787a80SKarolina Drobnik */
memblock_reserve_disjoint_check(void)58183787a80SKarolina Drobnik static int memblock_reserve_disjoint_check(void)
58283787a80SKarolina Drobnik {
58383787a80SKarolina Drobnik struct memblock_region *rgn1, *rgn2;
58483787a80SKarolina Drobnik
58583787a80SKarolina Drobnik rgn1 = &memblock.reserved.regions[0];
58683787a80SKarolina Drobnik rgn2 = &memblock.reserved.regions[1];
58783787a80SKarolina Drobnik
58883787a80SKarolina Drobnik struct region r1 = {
58983787a80SKarolina Drobnik .base = SZ_256M,
59083787a80SKarolina Drobnik .size = SZ_16M
59183787a80SKarolina Drobnik };
59283787a80SKarolina Drobnik struct region r2 = {
59383787a80SKarolina Drobnik .base = SZ_512M,
59483787a80SKarolina Drobnik .size = SZ_512M
59583787a80SKarolina Drobnik };
59683787a80SKarolina Drobnik
59776586c00SRebecca Mckeever PREFIX_PUSH();
59876586c00SRebecca Mckeever
5992c3dacbaSKarolina Drobnik reset_memblock_regions();
60083787a80SKarolina Drobnik memblock_reserve(r1.base, r1.size);
60183787a80SKarolina Drobnik memblock_reserve(r2.base, r2.size);
60283787a80SKarolina Drobnik
60376586c00SRebecca Mckeever ASSERT_EQ(rgn1->base, r1.base);
60476586c00SRebecca Mckeever ASSERT_EQ(rgn1->size, r1.size);
60583787a80SKarolina Drobnik
60676586c00SRebecca Mckeever ASSERT_EQ(rgn2->base, r2.base);
60776586c00SRebecca Mckeever ASSERT_EQ(rgn2->size, r2.size);
60883787a80SKarolina Drobnik
60976586c00SRebecca Mckeever ASSERT_EQ(memblock.reserved.cnt, 2);
61076586c00SRebecca Mckeever ASSERT_EQ(memblock.reserved.total_size, r1.size + r2.size);
61176586c00SRebecca Mckeever
61276586c00SRebecca Mckeever test_pass_pop();
61383787a80SKarolina Drobnik
61483787a80SKarolina Drobnik return 0;
61583787a80SKarolina Drobnik }
61683787a80SKarolina Drobnik
61783787a80SKarolina Drobnik /*
618e4f76c8dSRebecca Mckeever * A test that tries to mark two memory blocks r1 and r2 as reserved,
619e4f76c8dSRebecca Mckeever * where r2 overlaps with the beginning of r1 (that is
620e4f76c8dSRebecca Mckeever * r1.base < r2.base + r2.size):
621e4f76c8dSRebecca Mckeever *
622e4f76c8dSRebecca Mckeever * | +--------------+--+--------------+ |
623e4f76c8dSRebecca Mckeever * | | r2 | | r1 | |
624e4f76c8dSRebecca Mckeever * +--+--------------+--+--------------+--+
625e4f76c8dSRebecca Mckeever * ^ ^
626e4f76c8dSRebecca Mckeever * | |
627e4f76c8dSRebecca Mckeever * | r1.base
628e4f76c8dSRebecca Mckeever * |
629e4f76c8dSRebecca Mckeever * r2.base
630e4f76c8dSRebecca Mckeever *
631e4f76c8dSRebecca Mckeever * Expect to merge two entries into one region that starts at r2.base and
632e4f76c8dSRebecca Mckeever * has size of two regions minus their intersection. The total size of the
633e4f76c8dSRebecca Mckeever * reserved memory is updated, and the region counter is not updated.
63483787a80SKarolina Drobnik */
memblock_reserve_overlap_top_check(void)63583787a80SKarolina Drobnik static int memblock_reserve_overlap_top_check(void)
63683787a80SKarolina Drobnik {
63783787a80SKarolina Drobnik struct memblock_region *rgn;
63883787a80SKarolina Drobnik phys_addr_t total_size;
63983787a80SKarolina Drobnik
64083787a80SKarolina Drobnik rgn = &memblock.reserved.regions[0];
64183787a80SKarolina Drobnik
64283787a80SKarolina Drobnik struct region r1 = {
64383787a80SKarolina Drobnik .base = SZ_1G,
64483787a80SKarolina Drobnik .size = SZ_1G
64583787a80SKarolina Drobnik };
64683787a80SKarolina Drobnik struct region r2 = {
64783787a80SKarolina Drobnik .base = SZ_128M,
64883787a80SKarolina Drobnik .size = SZ_1G
64983787a80SKarolina Drobnik };
65083787a80SKarolina Drobnik
65176586c00SRebecca Mckeever PREFIX_PUSH();
65276586c00SRebecca Mckeever
65383787a80SKarolina Drobnik total_size = (r1.base - r2.base) + r1.size;
65483787a80SKarolina Drobnik
6552c3dacbaSKarolina Drobnik reset_memblock_regions();
65683787a80SKarolina Drobnik memblock_reserve(r1.base, r1.size);
65783787a80SKarolina Drobnik memblock_reserve(r2.base, r2.size);
65883787a80SKarolina Drobnik
65976586c00SRebecca Mckeever ASSERT_EQ(rgn->base, r2.base);
66076586c00SRebecca Mckeever ASSERT_EQ(rgn->size, total_size);
66183787a80SKarolina Drobnik
66276586c00SRebecca Mckeever ASSERT_EQ(memblock.reserved.cnt, 1);
66376586c00SRebecca Mckeever ASSERT_EQ(memblock.reserved.total_size, total_size);
66476586c00SRebecca Mckeever
66576586c00SRebecca Mckeever test_pass_pop();
66683787a80SKarolina Drobnik
66783787a80SKarolina Drobnik return 0;
66883787a80SKarolina Drobnik }
66983787a80SKarolina Drobnik
67083787a80SKarolina Drobnik /*
671e4f76c8dSRebecca Mckeever * A test that tries to mark two memory blocks r1 and r2 as reserved,
672e4f76c8dSRebecca Mckeever * where r2 overlaps with the end of r1 (that is
673e4f76c8dSRebecca Mckeever * r2.base < r1.base + r1.size):
674e4f76c8dSRebecca Mckeever *
675e4f76c8dSRebecca Mckeever * | +--------------+--+--------------+ |
676e4f76c8dSRebecca Mckeever * | | r1 | | r2 | |
677e4f76c8dSRebecca Mckeever * +--+--------------+--+--------------+--+
678e4f76c8dSRebecca Mckeever * ^ ^
679e4f76c8dSRebecca Mckeever * | |
680e4f76c8dSRebecca Mckeever * | r2.base
681e4f76c8dSRebecca Mckeever * |
682e4f76c8dSRebecca Mckeever * r1.base
683e4f76c8dSRebecca Mckeever *
684e4f76c8dSRebecca Mckeever * Expect to merge two entries into one region that starts at r1.base and
685e4f76c8dSRebecca Mckeever * has size of two regions minus their intersection. The total size of the
686e4f76c8dSRebecca Mckeever * reserved memory is updated, and the region counter is not updated.
68783787a80SKarolina Drobnik */
memblock_reserve_overlap_bottom_check(void)68883787a80SKarolina Drobnik static int memblock_reserve_overlap_bottom_check(void)
68983787a80SKarolina Drobnik {
69083787a80SKarolina Drobnik struct memblock_region *rgn;
69183787a80SKarolina Drobnik phys_addr_t total_size;
69283787a80SKarolina Drobnik
69383787a80SKarolina Drobnik rgn = &memblock.reserved.regions[0];
69483787a80SKarolina Drobnik
69583787a80SKarolina Drobnik struct region r1 = {
69683787a80SKarolina Drobnik .base = SZ_2K,
69783787a80SKarolina Drobnik .size = SZ_128K
69883787a80SKarolina Drobnik };
69983787a80SKarolina Drobnik struct region r2 = {
70083787a80SKarolina Drobnik .base = SZ_128K,
70183787a80SKarolina Drobnik .size = SZ_128K
70283787a80SKarolina Drobnik };
70383787a80SKarolina Drobnik
70476586c00SRebecca Mckeever PREFIX_PUSH();
70576586c00SRebecca Mckeever
70683787a80SKarolina Drobnik total_size = (r2.base - r1.base) + r2.size;
70783787a80SKarolina Drobnik
7082c3dacbaSKarolina Drobnik reset_memblock_regions();
70983787a80SKarolina Drobnik memblock_reserve(r1.base, r1.size);
71083787a80SKarolina Drobnik memblock_reserve(r2.base, r2.size);
71183787a80SKarolina Drobnik
71276586c00SRebecca Mckeever ASSERT_EQ(rgn->base, r1.base);
71376586c00SRebecca Mckeever ASSERT_EQ(rgn->size, total_size);
71483787a80SKarolina Drobnik
71576586c00SRebecca Mckeever ASSERT_EQ(memblock.reserved.cnt, 1);
71676586c00SRebecca Mckeever ASSERT_EQ(memblock.reserved.total_size, total_size);
71776586c00SRebecca Mckeever
71876586c00SRebecca Mckeever test_pass_pop();
71983787a80SKarolina Drobnik
72083787a80SKarolina Drobnik return 0;
72183787a80SKarolina Drobnik }
72283787a80SKarolina Drobnik
72383787a80SKarolina Drobnik /*
724e4f76c8dSRebecca Mckeever * A test that tries to mark two memory blocks r1 and r2 as reserved,
725e4f76c8dSRebecca Mckeever * where r2 is within the range of r1 (that is
726e4f76c8dSRebecca Mckeever * (r1.base < r2.base) && (r2.base + r2.size < r1.base + r1.size)):
727e4f76c8dSRebecca Mckeever *
728e4f76c8dSRebecca Mckeever * | +-----+--+---------------------------|
729e4f76c8dSRebecca Mckeever * | | |r2| r1 |
730e4f76c8dSRebecca Mckeever * +-+-----+--+---------------------------+
731e4f76c8dSRebecca Mckeever * ^ ^
732e4f76c8dSRebecca Mckeever * | |
733e4f76c8dSRebecca Mckeever * | r2.base
734e4f76c8dSRebecca Mckeever * |
735e4f76c8dSRebecca Mckeever * r1.base
736e4f76c8dSRebecca Mckeever *
737e4f76c8dSRebecca Mckeever * Expect to merge two entries into one region that stays the same. The
738e4f76c8dSRebecca Mckeever * counter and total size of available memory are not updated.
73983787a80SKarolina Drobnik */
memblock_reserve_within_check(void)74083787a80SKarolina Drobnik static int memblock_reserve_within_check(void)
74183787a80SKarolina Drobnik {
74283787a80SKarolina Drobnik struct memblock_region *rgn;
74383787a80SKarolina Drobnik
74483787a80SKarolina Drobnik rgn = &memblock.reserved.regions[0];
74583787a80SKarolina Drobnik
74683787a80SKarolina Drobnik struct region r1 = {
74783787a80SKarolina Drobnik .base = SZ_1M,
74883787a80SKarolina Drobnik .size = SZ_8M
74983787a80SKarolina Drobnik };
75083787a80SKarolina Drobnik struct region r2 = {
75183787a80SKarolina Drobnik .base = SZ_2M,
75283787a80SKarolina Drobnik .size = SZ_64K
75383787a80SKarolina Drobnik };
75483787a80SKarolina Drobnik
75576586c00SRebecca Mckeever PREFIX_PUSH();
75676586c00SRebecca Mckeever
7572c3dacbaSKarolina Drobnik reset_memblock_regions();
75883787a80SKarolina Drobnik memblock_reserve(r1.base, r1.size);
75983787a80SKarolina Drobnik memblock_reserve(r2.base, r2.size);
76083787a80SKarolina Drobnik
76176586c00SRebecca Mckeever ASSERT_EQ(rgn->base, r1.base);
76276586c00SRebecca Mckeever ASSERT_EQ(rgn->size, r1.size);
76383787a80SKarolina Drobnik
76476586c00SRebecca Mckeever ASSERT_EQ(memblock.reserved.cnt, 1);
76576586c00SRebecca Mckeever ASSERT_EQ(memblock.reserved.total_size, r1.size);
76676586c00SRebecca Mckeever
76776586c00SRebecca Mckeever test_pass_pop();
76883787a80SKarolina Drobnik
76983787a80SKarolina Drobnik return 0;
77083787a80SKarolina Drobnik }
77183787a80SKarolina Drobnik
77283787a80SKarolina Drobnik /*
77383787a80SKarolina Drobnik * A simple test that tries to reserve the same memory block twice.
774e4f76c8dSRebecca Mckeever * Expect the region counter and total size of reserved memory to not
77583787a80SKarolina Drobnik * be updated.
77683787a80SKarolina Drobnik */
memblock_reserve_twice_check(void)77783787a80SKarolina Drobnik static int memblock_reserve_twice_check(void)
77883787a80SKarolina Drobnik {
77983787a80SKarolina Drobnik struct region r = {
78083787a80SKarolina Drobnik .base = SZ_16K,
78183787a80SKarolina Drobnik .size = SZ_2M
78283787a80SKarolina Drobnik };
78383787a80SKarolina Drobnik
78476586c00SRebecca Mckeever PREFIX_PUSH();
78576586c00SRebecca Mckeever
7862c3dacbaSKarolina Drobnik reset_memblock_regions();
78783787a80SKarolina Drobnik
78883787a80SKarolina Drobnik memblock_reserve(r.base, r.size);
78983787a80SKarolina Drobnik memblock_reserve(r.base, r.size);
79083787a80SKarolina Drobnik
79176586c00SRebecca Mckeever ASSERT_EQ(memblock.reserved.cnt, 1);
79276586c00SRebecca Mckeever ASSERT_EQ(memblock.reserved.total_size, r.size);
79376586c00SRebecca Mckeever
79476586c00SRebecca Mckeever test_pass_pop();
79583787a80SKarolina Drobnik
79683787a80SKarolina Drobnik return 0;
79783787a80SKarolina Drobnik }
79883787a80SKarolina Drobnik
79921a233f6SRebecca Mckeever /*
80021a233f6SRebecca Mckeever * A test that tries to mark two memory blocks that don't overlap as reserved
80121a233f6SRebecca Mckeever * and then reserve a third memory block in the space between the first two:
80221a233f6SRebecca Mckeever *
80321a233f6SRebecca Mckeever * | +--------+--------+--------+ |
80421a233f6SRebecca Mckeever * | | r1 | r3 | r2 | |
80521a233f6SRebecca Mckeever * +--------+--------+--------+--------+--+
80621a233f6SRebecca Mckeever *
80721a233f6SRebecca Mckeever * Expect to merge the three entries into one reserved region that starts at
80821a233f6SRebecca Mckeever * r1.base and has size of r1.size + r2.size + r3.size. The region counter and
80921a233f6SRebecca Mckeever * total for memblock.reserved are updated.
81021a233f6SRebecca Mckeever */
memblock_reserve_between_check(void)81121a233f6SRebecca Mckeever static int memblock_reserve_between_check(void)
81221a233f6SRebecca Mckeever {
81321a233f6SRebecca Mckeever struct memblock_region *rgn;
81421a233f6SRebecca Mckeever phys_addr_t total_size;
81521a233f6SRebecca Mckeever
81621a233f6SRebecca Mckeever rgn = &memblock.reserved.regions[0];
81721a233f6SRebecca Mckeever
81821a233f6SRebecca Mckeever struct region r1 = {
81921a233f6SRebecca Mckeever .base = SZ_1G,
82021a233f6SRebecca Mckeever .size = SZ_8K
82121a233f6SRebecca Mckeever };
82221a233f6SRebecca Mckeever struct region r2 = {
82321a233f6SRebecca Mckeever .base = SZ_1G + SZ_16K,
82421a233f6SRebecca Mckeever .size = SZ_8K
82521a233f6SRebecca Mckeever };
82621a233f6SRebecca Mckeever struct region r3 = {
82721a233f6SRebecca Mckeever .base = SZ_1G + SZ_8K,
82821a233f6SRebecca Mckeever .size = SZ_8K
82921a233f6SRebecca Mckeever };
83021a233f6SRebecca Mckeever
83121a233f6SRebecca Mckeever PREFIX_PUSH();
83221a233f6SRebecca Mckeever
83321a233f6SRebecca Mckeever total_size = r1.size + r2.size + r3.size;
83421a233f6SRebecca Mckeever
83521a233f6SRebecca Mckeever reset_memblock_regions();
83621a233f6SRebecca Mckeever memblock_reserve(r1.base, r1.size);
83721a233f6SRebecca Mckeever memblock_reserve(r2.base, r2.size);
83821a233f6SRebecca Mckeever memblock_reserve(r3.base, r3.size);
83921a233f6SRebecca Mckeever
84021a233f6SRebecca Mckeever ASSERT_EQ(rgn->base, r1.base);
84121a233f6SRebecca Mckeever ASSERT_EQ(rgn->size, total_size);
84221a233f6SRebecca Mckeever
84321a233f6SRebecca Mckeever ASSERT_EQ(memblock.reserved.cnt, 1);
84421a233f6SRebecca Mckeever ASSERT_EQ(memblock.reserved.total_size, total_size);
84521a233f6SRebecca Mckeever
84621a233f6SRebecca Mckeever test_pass_pop();
84721a233f6SRebecca Mckeever
84821a233f6SRebecca Mckeever return 0;
84921a233f6SRebecca Mckeever }
85021a233f6SRebecca Mckeever
85121a233f6SRebecca Mckeever /*
85221a233f6SRebecca Mckeever * A simple test that tries to reserve a memory block r when r extends past
85321a233f6SRebecca Mckeever * PHYS_ADDR_MAX:
85421a233f6SRebecca Mckeever *
85521a233f6SRebecca Mckeever * +--------+
85621a233f6SRebecca Mckeever * | r |
85721a233f6SRebecca Mckeever * +--------+
85821a233f6SRebecca Mckeever * | +----+
85921a233f6SRebecca Mckeever * | | rgn|
86021a233f6SRebecca Mckeever * +----------------------------+----+
86121a233f6SRebecca Mckeever *
86221a233f6SRebecca Mckeever * Expect to reserve a memory block of size PHYS_ADDR_MAX - r.base. Expect the
86321a233f6SRebecca Mckeever * total size of reserved memory and the counter to be updated.
86421a233f6SRebecca Mckeever */
memblock_reserve_near_max_check(void)86521a233f6SRebecca Mckeever static int memblock_reserve_near_max_check(void)
86621a233f6SRebecca Mckeever {
86721a233f6SRebecca Mckeever struct memblock_region *rgn;
86821a233f6SRebecca Mckeever phys_addr_t total_size;
86921a233f6SRebecca Mckeever
87021a233f6SRebecca Mckeever rgn = &memblock.reserved.regions[0];
87121a233f6SRebecca Mckeever
87221a233f6SRebecca Mckeever struct region r = {
87321a233f6SRebecca Mckeever .base = PHYS_ADDR_MAX - SZ_1M,
87421a233f6SRebecca Mckeever .size = SZ_2M
87521a233f6SRebecca Mckeever };
87621a233f6SRebecca Mckeever
87721a233f6SRebecca Mckeever PREFIX_PUSH();
87821a233f6SRebecca Mckeever
87921a233f6SRebecca Mckeever total_size = PHYS_ADDR_MAX - r.base;
88021a233f6SRebecca Mckeever
88121a233f6SRebecca Mckeever reset_memblock_regions();
88221a233f6SRebecca Mckeever memblock_reserve(r.base, r.size);
88321a233f6SRebecca Mckeever
88421a233f6SRebecca Mckeever ASSERT_EQ(rgn->base, r.base);
88521a233f6SRebecca Mckeever ASSERT_EQ(rgn->size, total_size);
88621a233f6SRebecca Mckeever
88721a233f6SRebecca Mckeever ASSERT_EQ(memblock.reserved.cnt, 1);
88821a233f6SRebecca Mckeever ASSERT_EQ(memblock.reserved.total_size, total_size);
88921a233f6SRebecca Mckeever
89021a233f6SRebecca Mckeever test_pass_pop();
89121a233f6SRebecca Mckeever
89221a233f6SRebecca Mckeever return 0;
89321a233f6SRebecca Mckeever }
89421a233f6SRebecca Mckeever
8955b27dd79SShaoqin Huang /*
8965b27dd79SShaoqin Huang * A test that trying to reserve the 129th memory block.
8975b27dd79SShaoqin Huang * Expect to trigger memblock_double_array() to double the
8985b27dd79SShaoqin Huang * memblock.memory.max, find a new valid memory as
8995b27dd79SShaoqin Huang * reserved.regions.
9005b27dd79SShaoqin Huang */
memblock_reserve_many_check(void)9015b27dd79SShaoqin Huang static int memblock_reserve_many_check(void)
9025b27dd79SShaoqin Huang {
9035b27dd79SShaoqin Huang int i;
9045b27dd79SShaoqin Huang void *orig_region;
9055b27dd79SShaoqin Huang struct region r = {
9065b27dd79SShaoqin Huang .base = SZ_16K,
9075b27dd79SShaoqin Huang .size = SZ_16K,
9085b27dd79SShaoqin Huang };
9095b27dd79SShaoqin Huang phys_addr_t memory_base = SZ_128K;
9105b27dd79SShaoqin Huang phys_addr_t new_reserved_regions_size;
9115b27dd79SShaoqin Huang
9125b27dd79SShaoqin Huang PREFIX_PUSH();
9135b27dd79SShaoqin Huang
9145b27dd79SShaoqin Huang reset_memblock_regions();
9155b27dd79SShaoqin Huang memblock_allow_resize();
9165b27dd79SShaoqin Huang
9175b27dd79SShaoqin Huang /* Add a valid memory region used by double_array(). */
9185b27dd79SShaoqin Huang dummy_physical_memory_init();
9195b27dd79SShaoqin Huang memblock_add(dummy_physical_memory_base(), MEM_SIZE);
9205b27dd79SShaoqin Huang
9215b27dd79SShaoqin Huang for (i = 0; i < INIT_MEMBLOCK_REGIONS; i++) {
9225b27dd79SShaoqin Huang /* Reserve some fakes memory region to fulfill the memblock. */
9235b27dd79SShaoqin Huang memblock_reserve(memory_base, MEM_SIZE);
9245b27dd79SShaoqin Huang
9255b27dd79SShaoqin Huang ASSERT_EQ(memblock.reserved.cnt, i + 1);
9265b27dd79SShaoqin Huang ASSERT_EQ(memblock.reserved.total_size, (i + 1) * MEM_SIZE);
9275b27dd79SShaoqin Huang
9285b27dd79SShaoqin Huang /* Keep the gap so these memory region will not be merged. */
9295b27dd79SShaoqin Huang memory_base += MEM_SIZE * 2;
9305b27dd79SShaoqin Huang }
9315b27dd79SShaoqin Huang
9325b27dd79SShaoqin Huang orig_region = memblock.reserved.regions;
9335b27dd79SShaoqin Huang
9345b27dd79SShaoqin Huang /* This reserve the 129 memory_region, and makes it double array. */
9355b27dd79SShaoqin Huang memblock_reserve(memory_base, MEM_SIZE);
9365b27dd79SShaoqin Huang
9375b27dd79SShaoqin Huang /*
9385b27dd79SShaoqin Huang * This is the memory region size used by the doubled reserved.regions,
9395b27dd79SShaoqin Huang * and it has been reserved due to it has been used. The size is used to
9405b27dd79SShaoqin Huang * calculate the total_size that the memblock.reserved have now.
9415b27dd79SShaoqin Huang */
9425b27dd79SShaoqin Huang new_reserved_regions_size = PAGE_ALIGN((INIT_MEMBLOCK_REGIONS * 2) *
9435b27dd79SShaoqin Huang sizeof(struct memblock_region));
9445b27dd79SShaoqin Huang /*
9455b27dd79SShaoqin Huang * The double_array() will find a free memory region as the new
9465b27dd79SShaoqin Huang * reserved.regions, and the used memory region will be reserved, so
9475b27dd79SShaoqin Huang * there will be one more region exist in the reserved memblock. And the
9485b27dd79SShaoqin Huang * one more reserved region's size is new_reserved_regions_size.
9495b27dd79SShaoqin Huang */
9505b27dd79SShaoqin Huang ASSERT_EQ(memblock.reserved.cnt, INIT_MEMBLOCK_REGIONS + 2);
9515b27dd79SShaoqin Huang ASSERT_EQ(memblock.reserved.total_size, (INIT_MEMBLOCK_REGIONS + 1) * MEM_SIZE +
9525b27dd79SShaoqin Huang new_reserved_regions_size);
9535b27dd79SShaoqin Huang ASSERT_EQ(memblock.reserved.max, INIT_MEMBLOCK_REGIONS * 2);
9545b27dd79SShaoqin Huang
9555b27dd79SShaoqin Huang /*
9565b27dd79SShaoqin Huang * Now memblock_double_array() works fine. Let's check after the
9575b27dd79SShaoqin Huang * double_array(), the memblock_reserve() still works as normal.
9585b27dd79SShaoqin Huang */
9595b27dd79SShaoqin Huang memblock_reserve(r.base, r.size);
9605b27dd79SShaoqin Huang ASSERT_EQ(memblock.reserved.regions[0].base, r.base);
9615b27dd79SShaoqin Huang ASSERT_EQ(memblock.reserved.regions[0].size, r.size);
9625b27dd79SShaoqin Huang
9635b27dd79SShaoqin Huang ASSERT_EQ(memblock.reserved.cnt, INIT_MEMBLOCK_REGIONS + 3);
9645b27dd79SShaoqin Huang ASSERT_EQ(memblock.reserved.total_size, (INIT_MEMBLOCK_REGIONS + 1) * MEM_SIZE +
9655b27dd79SShaoqin Huang new_reserved_regions_size +
9665b27dd79SShaoqin Huang r.size);
9675b27dd79SShaoqin Huang ASSERT_EQ(memblock.reserved.max, INIT_MEMBLOCK_REGIONS * 2);
9685b27dd79SShaoqin Huang
9695b27dd79SShaoqin Huang dummy_physical_memory_cleanup();
9705b27dd79SShaoqin Huang
9715b27dd79SShaoqin Huang /*
9725b27dd79SShaoqin Huang * The current reserved.regions is occupying a range of memory that
9735b27dd79SShaoqin Huang * allocated from dummy_physical_memory_init(). After free the memory,
9745b27dd79SShaoqin Huang * we must not use it. So restore the origin memory region to make sure
9755b27dd79SShaoqin Huang * the tests can run as normal and not affected by the double array.
9765b27dd79SShaoqin Huang */
9775b27dd79SShaoqin Huang memblock.reserved.regions = orig_region;
9785b27dd79SShaoqin Huang memblock.reserved.cnt = INIT_MEMBLOCK_RESERVED_REGIONS;
9795b27dd79SShaoqin Huang
9805b27dd79SShaoqin Huang test_pass_pop();
9815b27dd79SShaoqin Huang
9825b27dd79SShaoqin Huang return 0;
9835b27dd79SShaoqin Huang }
9845b27dd79SShaoqin Huang
9853d316519SWei Yang
9863d316519SWei Yang /*
9873d316519SWei Yang * A test that trying to reserve the 129th memory block at all locations.
9883d316519SWei Yang * Expect to trigger memblock_double_array() to double the
9893d316519SWei Yang * memblock.memory.max, find a new valid memory as reserved.regions.
9903d316519SWei Yang *
9913d316519SWei Yang * 0 1 2 128
9923d316519SWei Yang * +-------+ +-------+ +-------+ +-------+
9933d316519SWei Yang * | 32K | | 32K | | 32K | ... | 32K |
9943d316519SWei Yang * +-------+-------+-------+-------+-------+ +-------+
9953d316519SWei Yang * |<-32K->| |<-32K->|
9963d316519SWei Yang *
9973d316519SWei Yang */
9983d316519SWei Yang /* Keep the gap so these memory region will not be merged. */
9993d316519SWei Yang #define MEMORY_BASE(idx) (SZ_128K + (MEM_SIZE * 2) * (idx))
memblock_reserve_all_locations_check(void)10003d316519SWei Yang static int memblock_reserve_all_locations_check(void)
10013d316519SWei Yang {
10023d316519SWei Yang int i, skip;
10033d316519SWei Yang void *orig_region;
10043d316519SWei Yang struct region r = {
10053d316519SWei Yang .base = SZ_16K,
10063d316519SWei Yang .size = SZ_16K,
10073d316519SWei Yang };
10083d316519SWei Yang phys_addr_t new_reserved_regions_size;
10093d316519SWei Yang
10103d316519SWei Yang PREFIX_PUSH();
10113d316519SWei Yang
10123d316519SWei Yang /* Reserve the 129th memory block for all possible positions*/
10133d316519SWei Yang for (skip = 0; skip < INIT_MEMBLOCK_REGIONS + 1; skip++) {
10143d316519SWei Yang reset_memblock_regions();
10153d316519SWei Yang memblock_allow_resize();
10163d316519SWei Yang
10173d316519SWei Yang /* Add a valid memory region used by double_array(). */
10183d316519SWei Yang dummy_physical_memory_init();
10193d316519SWei Yang memblock_add(dummy_physical_memory_base(), MEM_SIZE);
10203d316519SWei Yang
10213d316519SWei Yang for (i = 0; i < INIT_MEMBLOCK_REGIONS + 1; i++) {
10223d316519SWei Yang if (i == skip)
10233d316519SWei Yang continue;
10243d316519SWei Yang
10253d316519SWei Yang /* Reserve some fakes memory region to fulfill the memblock. */
10263d316519SWei Yang memblock_reserve(MEMORY_BASE(i), MEM_SIZE);
10273d316519SWei Yang
10283d316519SWei Yang if (i < skip) {
10293d316519SWei Yang ASSERT_EQ(memblock.reserved.cnt, i + 1);
10303d316519SWei Yang ASSERT_EQ(memblock.reserved.total_size, (i + 1) * MEM_SIZE);
10313d316519SWei Yang } else {
10323d316519SWei Yang ASSERT_EQ(memblock.reserved.cnt, i);
10333d316519SWei Yang ASSERT_EQ(memblock.reserved.total_size, i * MEM_SIZE);
10343d316519SWei Yang }
10353d316519SWei Yang }
10363d316519SWei Yang
10373d316519SWei Yang orig_region = memblock.reserved.regions;
10383d316519SWei Yang
10393d316519SWei Yang /* This reserve the 129 memory_region, and makes it double array. */
10403d316519SWei Yang memblock_reserve(MEMORY_BASE(skip), MEM_SIZE);
10413d316519SWei Yang
10423d316519SWei Yang /*
10433d316519SWei Yang * This is the memory region size used by the doubled reserved.regions,
10443d316519SWei Yang * and it has been reserved due to it has been used. The size is used to
10453d316519SWei Yang * calculate the total_size that the memblock.reserved have now.
10463d316519SWei Yang */
10473d316519SWei Yang new_reserved_regions_size = PAGE_ALIGN((INIT_MEMBLOCK_REGIONS * 2) *
10483d316519SWei Yang sizeof(struct memblock_region));
10493d316519SWei Yang /*
10503d316519SWei Yang * The double_array() will find a free memory region as the new
10513d316519SWei Yang * reserved.regions, and the used memory region will be reserved, so
10523d316519SWei Yang * there will be one more region exist in the reserved memblock. And the
10533d316519SWei Yang * one more reserved region's size is new_reserved_regions_size.
10543d316519SWei Yang */
10553d316519SWei Yang ASSERT_EQ(memblock.reserved.cnt, INIT_MEMBLOCK_REGIONS + 2);
10563d316519SWei Yang ASSERT_EQ(memblock.reserved.total_size, (INIT_MEMBLOCK_REGIONS + 1) * MEM_SIZE +
10573d316519SWei Yang new_reserved_regions_size);
10583d316519SWei Yang ASSERT_EQ(memblock.reserved.max, INIT_MEMBLOCK_REGIONS * 2);
10593d316519SWei Yang
10603d316519SWei Yang /*
10613d316519SWei Yang * Now memblock_double_array() works fine. Let's check after the
10623d316519SWei Yang * double_array(), the memblock_reserve() still works as normal.
10633d316519SWei Yang */
10643d316519SWei Yang memblock_reserve(r.base, r.size);
10653d316519SWei Yang ASSERT_EQ(memblock.reserved.regions[0].base, r.base);
10663d316519SWei Yang ASSERT_EQ(memblock.reserved.regions[0].size, r.size);
10673d316519SWei Yang
10683d316519SWei Yang ASSERT_EQ(memblock.reserved.cnt, INIT_MEMBLOCK_REGIONS + 3);
10693d316519SWei Yang ASSERT_EQ(memblock.reserved.total_size, (INIT_MEMBLOCK_REGIONS + 1) * MEM_SIZE +
10703d316519SWei Yang new_reserved_regions_size +
10713d316519SWei Yang r.size);
10723d316519SWei Yang ASSERT_EQ(memblock.reserved.max, INIT_MEMBLOCK_REGIONS * 2);
10733d316519SWei Yang
10743d316519SWei Yang dummy_physical_memory_cleanup();
10753d316519SWei Yang
10763d316519SWei Yang /*
10773d316519SWei Yang * The current reserved.regions is occupying a range of memory that
10783d316519SWei Yang * allocated from dummy_physical_memory_init(). After free the memory,
10793d316519SWei Yang * we must not use it. So restore the origin memory region to make sure
10803d316519SWei Yang * the tests can run as normal and not affected by the double array.
10813d316519SWei Yang */
10823d316519SWei Yang memblock.reserved.regions = orig_region;
10833d316519SWei Yang memblock.reserved.cnt = INIT_MEMBLOCK_RESERVED_REGIONS;
10843d316519SWei Yang }
10853d316519SWei Yang
10863d316519SWei Yang test_pass_pop();
10873d316519SWei Yang
10883d316519SWei Yang return 0;
10893d316519SWei Yang }
10903d316519SWei Yang
1091f6df89c3SWei Yang /*
1092f6df89c3SWei Yang * A test that trying to reserve the 129th memory block at all locations.
1093f6df89c3SWei Yang * Expect to trigger memblock_double_array() to double the
1094f6df89c3SWei Yang * memblock.memory.max, find a new valid memory as reserved.regions. And make
1095f6df89c3SWei Yang * sure it doesn't conflict with the range we want to reserve.
1096f6df89c3SWei Yang *
1097f6df89c3SWei Yang * For example, we have 128 regions in reserved and now want to reserve
1098f6df89c3SWei Yang * the skipped one. Since reserved is full, memblock_double_array() would find
1099f6df89c3SWei Yang * an available range in memory for the new array. We intended to put two
1100f6df89c3SWei Yang * ranges in memory with one is the exact range of the skipped one. Before
1101f6df89c3SWei Yang * commit 48c3b583bbdd ("mm/memblock: fix overlapping allocation when doubling
1102f6df89c3SWei Yang * reserved array"), the new array would sits in the skipped range which is a
1103f6df89c3SWei Yang * conflict. The expected new array should be allocated from memory.regions[0].
1104f6df89c3SWei Yang *
1105f6df89c3SWei Yang * 0 1
1106f6df89c3SWei Yang * memory +-------+ +-------+
1107f6df89c3SWei Yang * | 32K | | 32K |
1108f6df89c3SWei Yang * +-------+ ------+-------+-------+-------+
1109f6df89c3SWei Yang * |<-32K->|<-32K->|<-32K->|
1110f6df89c3SWei Yang *
1111f6df89c3SWei Yang * 0 skipped 127
1112f6df89c3SWei Yang * reserved +-------+ ......... +-------+
1113f6df89c3SWei Yang * | 32K | . 32K . ... | 32K |
1114f6df89c3SWei Yang * +-------+-------+-------+ +-------+
1115f6df89c3SWei Yang * |<-32K->|
1116f6df89c3SWei Yang * ^
1117f6df89c3SWei Yang * |
1118f6df89c3SWei Yang * |
1119f6df89c3SWei Yang * skipped one
1120f6df89c3SWei Yang */
1121f6df89c3SWei Yang /* Keep the gap so these memory region will not be merged. */
1122f6df89c3SWei Yang #define MEMORY_BASE_OFFSET(idx, offset) ((offset) + (MEM_SIZE * 2) * (idx))
memblock_reserve_many_may_conflict_check(void)1123f6df89c3SWei Yang static int memblock_reserve_many_may_conflict_check(void)
1124f6df89c3SWei Yang {
1125f6df89c3SWei Yang int i, skip;
1126f6df89c3SWei Yang void *orig_region;
1127f6df89c3SWei Yang struct region r = {
1128f6df89c3SWei Yang .base = SZ_16K,
1129f6df89c3SWei Yang .size = SZ_16K,
1130f6df89c3SWei Yang };
1131f6df89c3SWei Yang phys_addr_t new_reserved_regions_size;
1132f6df89c3SWei Yang
1133f6df89c3SWei Yang /*
1134f6df89c3SWei Yang * 0 1 129
1135f6df89c3SWei Yang * +---+ +---+ +---+
1136f6df89c3SWei Yang * |32K| |32K| .. |32K|
1137f6df89c3SWei Yang * +---+ +---+ +---+
1138f6df89c3SWei Yang *
1139f6df89c3SWei Yang * Pre-allocate the range for 129 memory block + one range for double
1140f6df89c3SWei Yang * memblock.reserved.regions at idx 0.
1141f6df89c3SWei Yang */
1142f6df89c3SWei Yang dummy_physical_memory_init();
1143f6df89c3SWei Yang phys_addr_t memory_base = dummy_physical_memory_base();
1144f6df89c3SWei Yang phys_addr_t offset = PAGE_ALIGN(memory_base);
1145f6df89c3SWei Yang
1146f6df89c3SWei Yang PREFIX_PUSH();
1147f6df89c3SWei Yang
1148f6df89c3SWei Yang /* Reserve the 129th memory block for all possible positions*/
1149f6df89c3SWei Yang for (skip = 1; skip <= INIT_MEMBLOCK_REGIONS + 1; skip++) {
1150f6df89c3SWei Yang reset_memblock_regions();
1151f6df89c3SWei Yang memblock_allow_resize();
1152f6df89c3SWei Yang
1153f6df89c3SWei Yang reset_memblock_attributes();
1154f6df89c3SWei Yang /* Add a valid memory region used by double_array(). */
1155f6df89c3SWei Yang memblock_add(MEMORY_BASE_OFFSET(0, offset), MEM_SIZE);
1156f6df89c3SWei Yang /*
1157f6df89c3SWei Yang * Add a memory region which will be reserved as 129th memory
1158f6df89c3SWei Yang * region. This is not expected to be used by double_array().
1159f6df89c3SWei Yang */
1160f6df89c3SWei Yang memblock_add(MEMORY_BASE_OFFSET(skip, offset), MEM_SIZE);
1161f6df89c3SWei Yang
1162f6df89c3SWei Yang for (i = 1; i <= INIT_MEMBLOCK_REGIONS + 1; i++) {
1163f6df89c3SWei Yang if (i == skip)
1164f6df89c3SWei Yang continue;
1165f6df89c3SWei Yang
1166f6df89c3SWei Yang /* Reserve some fakes memory region to fulfill the memblock. */
1167f6df89c3SWei Yang memblock_reserve(MEMORY_BASE_OFFSET(i, offset), MEM_SIZE);
1168f6df89c3SWei Yang
1169f6df89c3SWei Yang if (i < skip) {
1170f6df89c3SWei Yang ASSERT_EQ(memblock.reserved.cnt, i);
1171f6df89c3SWei Yang ASSERT_EQ(memblock.reserved.total_size, i * MEM_SIZE);
1172f6df89c3SWei Yang } else {
1173f6df89c3SWei Yang ASSERT_EQ(memblock.reserved.cnt, i - 1);
1174f6df89c3SWei Yang ASSERT_EQ(memblock.reserved.total_size, (i - 1) * MEM_SIZE);
1175f6df89c3SWei Yang }
1176f6df89c3SWei Yang }
1177f6df89c3SWei Yang
1178f6df89c3SWei Yang orig_region = memblock.reserved.regions;
1179f6df89c3SWei Yang
1180f6df89c3SWei Yang /* This reserve the 129 memory_region, and makes it double array. */
1181f6df89c3SWei Yang memblock_reserve(MEMORY_BASE_OFFSET(skip, offset), MEM_SIZE);
1182f6df89c3SWei Yang
1183f6df89c3SWei Yang /*
1184f6df89c3SWei Yang * This is the memory region size used by the doubled reserved.regions,
1185f6df89c3SWei Yang * and it has been reserved due to it has been used. The size is used to
1186f6df89c3SWei Yang * calculate the total_size that the memblock.reserved have now.
1187f6df89c3SWei Yang */
1188f6df89c3SWei Yang new_reserved_regions_size = PAGE_ALIGN((INIT_MEMBLOCK_REGIONS * 2) *
1189f6df89c3SWei Yang sizeof(struct memblock_region));
1190f6df89c3SWei Yang /*
1191f6df89c3SWei Yang * The double_array() will find a free memory region as the new
1192f6df89c3SWei Yang * reserved.regions, and the used memory region will be reserved, so
1193f6df89c3SWei Yang * there will be one more region exist in the reserved memblock. And the
1194f6df89c3SWei Yang * one more reserved region's size is new_reserved_regions_size.
1195f6df89c3SWei Yang */
1196f6df89c3SWei Yang ASSERT_EQ(memblock.reserved.cnt, INIT_MEMBLOCK_REGIONS + 2);
1197f6df89c3SWei Yang ASSERT_EQ(memblock.reserved.total_size, (INIT_MEMBLOCK_REGIONS + 1) * MEM_SIZE +
1198f6df89c3SWei Yang new_reserved_regions_size);
1199f6df89c3SWei Yang ASSERT_EQ(memblock.reserved.max, INIT_MEMBLOCK_REGIONS * 2);
1200f6df89c3SWei Yang
1201f6df89c3SWei Yang /*
1202f6df89c3SWei Yang * The first reserved region is allocated for double array
1203f6df89c3SWei Yang * with the size of new_reserved_regions_size and the base to be
1204f6df89c3SWei Yang * MEMORY_BASE_OFFSET(0, offset) + SZ_32K - new_reserved_regions_size
1205f6df89c3SWei Yang */
1206f6df89c3SWei Yang ASSERT_EQ(memblock.reserved.regions[0].base + memblock.reserved.regions[0].size,
1207f6df89c3SWei Yang MEMORY_BASE_OFFSET(0, offset) + SZ_32K);
1208f6df89c3SWei Yang ASSERT_EQ(memblock.reserved.regions[0].size, new_reserved_regions_size);
1209f6df89c3SWei Yang
1210f6df89c3SWei Yang /*
1211f6df89c3SWei Yang * Now memblock_double_array() works fine. Let's check after the
1212f6df89c3SWei Yang * double_array(), the memblock_reserve() still works as normal.
1213f6df89c3SWei Yang */
1214f6df89c3SWei Yang memblock_reserve(r.base, r.size);
1215f6df89c3SWei Yang ASSERT_EQ(memblock.reserved.regions[0].base, r.base);
1216f6df89c3SWei Yang ASSERT_EQ(memblock.reserved.regions[0].size, r.size);
1217f6df89c3SWei Yang
1218f6df89c3SWei Yang ASSERT_EQ(memblock.reserved.cnt, INIT_MEMBLOCK_REGIONS + 3);
1219f6df89c3SWei Yang ASSERT_EQ(memblock.reserved.total_size, (INIT_MEMBLOCK_REGIONS + 1) * MEM_SIZE +
1220f6df89c3SWei Yang new_reserved_regions_size +
1221f6df89c3SWei Yang r.size);
1222f6df89c3SWei Yang ASSERT_EQ(memblock.reserved.max, INIT_MEMBLOCK_REGIONS * 2);
1223f6df89c3SWei Yang
1224f6df89c3SWei Yang /*
1225f6df89c3SWei Yang * The current reserved.regions is occupying a range of memory that
1226f6df89c3SWei Yang * allocated from dummy_physical_memory_init(). After free the memory,
1227f6df89c3SWei Yang * we must not use it. So restore the origin memory region to make sure
1228f6df89c3SWei Yang * the tests can run as normal and not affected by the double array.
1229f6df89c3SWei Yang */
1230f6df89c3SWei Yang memblock.reserved.regions = orig_region;
1231f6df89c3SWei Yang memblock.reserved.cnt = INIT_MEMBLOCK_RESERVED_REGIONS;
1232f6df89c3SWei Yang }
1233f6df89c3SWei Yang
1234f6df89c3SWei Yang dummy_physical_memory_cleanup();
1235f6df89c3SWei Yang
1236f6df89c3SWei Yang test_pass_pop();
1237f6df89c3SWei Yang
1238f6df89c3SWei Yang return 0;
1239f6df89c3SWei Yang }
1240f6df89c3SWei Yang
memblock_reserve_checks(void)124183787a80SKarolina Drobnik static int memblock_reserve_checks(void)
124283787a80SKarolina Drobnik {
124376586c00SRebecca Mckeever prefix_reset();
124476586c00SRebecca Mckeever prefix_push(FUNC_RESERVE);
124576586c00SRebecca Mckeever test_print("Running %s tests...\n", FUNC_RESERVE);
124676586c00SRebecca Mckeever
124783787a80SKarolina Drobnik memblock_reserve_simple_check();
124883787a80SKarolina Drobnik memblock_reserve_disjoint_check();
124983787a80SKarolina Drobnik memblock_reserve_overlap_top_check();
125083787a80SKarolina Drobnik memblock_reserve_overlap_bottom_check();
125183787a80SKarolina Drobnik memblock_reserve_within_check();
125283787a80SKarolina Drobnik memblock_reserve_twice_check();
125321a233f6SRebecca Mckeever memblock_reserve_between_check();
125421a233f6SRebecca Mckeever memblock_reserve_near_max_check();
12555b27dd79SShaoqin Huang memblock_reserve_many_check();
12563d316519SWei Yang memblock_reserve_all_locations_check();
1257f6df89c3SWei Yang memblock_reserve_many_may_conflict_check();
125883787a80SKarolina Drobnik
125976586c00SRebecca Mckeever prefix_pop();
126076586c00SRebecca Mckeever
126183787a80SKarolina Drobnik return 0;
126283787a80SKarolina Drobnik }
126383787a80SKarolina Drobnik
1264b4d96893SKarolina Drobnik /*
126560bba7b1SRebecca Mckeever * A simple test that tries to remove a region r1 from the array of
1266b4d96893SKarolina Drobnik * available memory regions. By "removing" a region we mean overwriting it
126760bba7b1SRebecca Mckeever * with the next region r2 in memblock.memory:
126860bba7b1SRebecca Mckeever *
126960bba7b1SRebecca Mckeever * | ...... +----------------+ |
127060bba7b1SRebecca Mckeever * | : r1 : | r2 | |
127160bba7b1SRebecca Mckeever * +--+----+----------+----------------+--+
127260bba7b1SRebecca Mckeever * ^
127360bba7b1SRebecca Mckeever * |
127460bba7b1SRebecca Mckeever * rgn.base
127560bba7b1SRebecca Mckeever *
127660bba7b1SRebecca Mckeever * Expect to add two memory blocks r1 and r2 and then remove r1 so that
127760bba7b1SRebecca Mckeever * r2 is the first available region. The region counter and total size
127860bba7b1SRebecca Mckeever * are updated.
1279b4d96893SKarolina Drobnik */
memblock_remove_simple_check(void)1280b4d96893SKarolina Drobnik static int memblock_remove_simple_check(void)
1281b4d96893SKarolina Drobnik {
1282b4d96893SKarolina Drobnik struct memblock_region *rgn;
1283b4d96893SKarolina Drobnik
1284b4d96893SKarolina Drobnik rgn = &memblock.memory.regions[0];
1285b4d96893SKarolina Drobnik
1286b4d96893SKarolina Drobnik struct region r1 = {
1287b4d96893SKarolina Drobnik .base = SZ_2K,
1288b4d96893SKarolina Drobnik .size = SZ_4K
1289b4d96893SKarolina Drobnik };
1290b4d96893SKarolina Drobnik struct region r2 = {
1291b4d96893SKarolina Drobnik .base = SZ_128K,
1292b4d96893SKarolina Drobnik .size = SZ_4M
1293b4d96893SKarolina Drobnik };
1294b4d96893SKarolina Drobnik
129576586c00SRebecca Mckeever PREFIX_PUSH();
129676586c00SRebecca Mckeever
12972c3dacbaSKarolina Drobnik reset_memblock_regions();
1298b4d96893SKarolina Drobnik memblock_add(r1.base, r1.size);
1299b4d96893SKarolina Drobnik memblock_add(r2.base, r2.size);
1300b4d96893SKarolina Drobnik memblock_remove(r1.base, r1.size);
1301b4d96893SKarolina Drobnik
130276586c00SRebecca Mckeever ASSERT_EQ(rgn->base, r2.base);
130376586c00SRebecca Mckeever ASSERT_EQ(rgn->size, r2.size);
1304b4d96893SKarolina Drobnik
130576586c00SRebecca Mckeever ASSERT_EQ(memblock.memory.cnt, 1);
130676586c00SRebecca Mckeever ASSERT_EQ(memblock.memory.total_size, r2.size);
130776586c00SRebecca Mckeever
130876586c00SRebecca Mckeever test_pass_pop();
1309b4d96893SKarolina Drobnik
1310b4d96893SKarolina Drobnik return 0;
1311b4d96893SKarolina Drobnik }
1312b4d96893SKarolina Drobnik
1313b4d96893SKarolina Drobnik /*
131460bba7b1SRebecca Mckeever * A test that tries to remove a region r2 that was not registered as
131560bba7b1SRebecca Mckeever * available memory (i.e. has no corresponding entry in memblock.memory):
131660bba7b1SRebecca Mckeever *
131760bba7b1SRebecca Mckeever * +----------------+
131860bba7b1SRebecca Mckeever * | r2 |
131960bba7b1SRebecca Mckeever * +----------------+
132060bba7b1SRebecca Mckeever * | +----+ |
132160bba7b1SRebecca Mckeever * | | r1 | |
132260bba7b1SRebecca Mckeever * +--+----+------------------------------+
132360bba7b1SRebecca Mckeever * ^
132460bba7b1SRebecca Mckeever * |
132560bba7b1SRebecca Mckeever * rgn.base
132660bba7b1SRebecca Mckeever *
132760bba7b1SRebecca Mckeever * Expect the array, regions counter and total size to not be modified.
1328b4d96893SKarolina Drobnik */
memblock_remove_absent_check(void)1329b4d96893SKarolina Drobnik static int memblock_remove_absent_check(void)
1330b4d96893SKarolina Drobnik {
1331b4d96893SKarolina Drobnik struct memblock_region *rgn;
1332b4d96893SKarolina Drobnik
1333b4d96893SKarolina Drobnik rgn = &memblock.memory.regions[0];
1334b4d96893SKarolina Drobnik
1335b4d96893SKarolina Drobnik struct region r1 = {
1336b4d96893SKarolina Drobnik .base = SZ_512K,
1337b4d96893SKarolina Drobnik .size = SZ_4M
1338b4d96893SKarolina Drobnik };
1339b4d96893SKarolina Drobnik struct region r2 = {
1340b4d96893SKarolina Drobnik .base = SZ_64M,
1341b4d96893SKarolina Drobnik .size = SZ_1G
1342b4d96893SKarolina Drobnik };
1343b4d96893SKarolina Drobnik
134476586c00SRebecca Mckeever PREFIX_PUSH();
134576586c00SRebecca Mckeever
13462c3dacbaSKarolina Drobnik reset_memblock_regions();
1347b4d96893SKarolina Drobnik memblock_add(r1.base, r1.size);
1348b4d96893SKarolina Drobnik memblock_remove(r2.base, r2.size);
1349b4d96893SKarolina Drobnik
135076586c00SRebecca Mckeever ASSERT_EQ(rgn->base, r1.base);
135176586c00SRebecca Mckeever ASSERT_EQ(rgn->size, r1.size);
1352b4d96893SKarolina Drobnik
135376586c00SRebecca Mckeever ASSERT_EQ(memblock.memory.cnt, 1);
135476586c00SRebecca Mckeever ASSERT_EQ(memblock.memory.total_size, r1.size);
135576586c00SRebecca Mckeever
135676586c00SRebecca Mckeever test_pass_pop();
1357b4d96893SKarolina Drobnik
1358b4d96893SKarolina Drobnik return 0;
1359b4d96893SKarolina Drobnik }
1360b4d96893SKarolina Drobnik
1361b4d96893SKarolina Drobnik /*
136260bba7b1SRebecca Mckeever * A test that tries to remove a region r2 that overlaps with the
136360bba7b1SRebecca Mckeever * beginning of the already existing entry r1
136460bba7b1SRebecca Mckeever * (that is r1.base < r2.base + r2.size):
136560bba7b1SRebecca Mckeever *
136660bba7b1SRebecca Mckeever * +-----------------+
136760bba7b1SRebecca Mckeever * | r2 |
136860bba7b1SRebecca Mckeever * +-----------------+
136960bba7b1SRebecca Mckeever * | .........+--------+ |
137060bba7b1SRebecca Mckeever * | : r1 | rgn | |
137160bba7b1SRebecca Mckeever * +-----------------+--------+--------+--+
137260bba7b1SRebecca Mckeever * ^ ^
137360bba7b1SRebecca Mckeever * | |
137460bba7b1SRebecca Mckeever * | rgn.base
137560bba7b1SRebecca Mckeever * r1.base
137660bba7b1SRebecca Mckeever *
137760bba7b1SRebecca Mckeever * Expect that only the intersection of both regions is removed from the
137860bba7b1SRebecca Mckeever * available memory pool. The regions counter and total size are updated.
1379b4d96893SKarolina Drobnik */
memblock_remove_overlap_top_check(void)1380b4d96893SKarolina Drobnik static int memblock_remove_overlap_top_check(void)
1381b4d96893SKarolina Drobnik {
1382b4d96893SKarolina Drobnik struct memblock_region *rgn;
1383b4d96893SKarolina Drobnik phys_addr_t r1_end, r2_end, total_size;
1384b4d96893SKarolina Drobnik
1385b4d96893SKarolina Drobnik rgn = &memblock.memory.regions[0];
1386b4d96893SKarolina Drobnik
1387b4d96893SKarolina Drobnik struct region r1 = {
1388b4d96893SKarolina Drobnik .base = SZ_32M,
1389b4d96893SKarolina Drobnik .size = SZ_32M
1390b4d96893SKarolina Drobnik };
1391b4d96893SKarolina Drobnik struct region r2 = {
1392b4d96893SKarolina Drobnik .base = SZ_16M,
1393b4d96893SKarolina Drobnik .size = SZ_32M
1394b4d96893SKarolina Drobnik };
1395b4d96893SKarolina Drobnik
139676586c00SRebecca Mckeever PREFIX_PUSH();
139776586c00SRebecca Mckeever
1398b4d96893SKarolina Drobnik r1_end = r1.base + r1.size;
1399b4d96893SKarolina Drobnik r2_end = r2.base + r2.size;
1400b4d96893SKarolina Drobnik total_size = r1_end - r2_end;
1401b4d96893SKarolina Drobnik
14022c3dacbaSKarolina Drobnik reset_memblock_regions();
1403b4d96893SKarolina Drobnik memblock_add(r1.base, r1.size);
1404b4d96893SKarolina Drobnik memblock_remove(r2.base, r2.size);
1405b4d96893SKarolina Drobnik
140676586c00SRebecca Mckeever ASSERT_EQ(rgn->base, r1.base + r2.base);
140776586c00SRebecca Mckeever ASSERT_EQ(rgn->size, total_size);
1408b4d96893SKarolina Drobnik
140976586c00SRebecca Mckeever ASSERT_EQ(memblock.memory.cnt, 1);
141076586c00SRebecca Mckeever ASSERT_EQ(memblock.memory.total_size, total_size);
141176586c00SRebecca Mckeever
141276586c00SRebecca Mckeever test_pass_pop();
1413b4d96893SKarolina Drobnik
1414b4d96893SKarolina Drobnik return 0;
1415b4d96893SKarolina Drobnik }
1416b4d96893SKarolina Drobnik
1417b4d96893SKarolina Drobnik /*
141860bba7b1SRebecca Mckeever * A test that tries to remove a region r2 that overlaps with the end of
141960bba7b1SRebecca Mckeever * the already existing region r1 (that is r2.base < r1.base + r1.size):
142060bba7b1SRebecca Mckeever *
142160bba7b1SRebecca Mckeever * +--------------------------------+
142260bba7b1SRebecca Mckeever * | r2 |
142360bba7b1SRebecca Mckeever * +--------------------------------+
142460bba7b1SRebecca Mckeever * | +---+..... |
142560bba7b1SRebecca Mckeever * | |rgn| r1 : |
142660bba7b1SRebecca Mckeever * +-+---+----+---------------------------+
142760bba7b1SRebecca Mckeever * ^
142860bba7b1SRebecca Mckeever * |
142960bba7b1SRebecca Mckeever * r1.base
143060bba7b1SRebecca Mckeever *
143160bba7b1SRebecca Mckeever * Expect that only the intersection of both regions is removed from the
143260bba7b1SRebecca Mckeever * available memory pool. The regions counter and total size are updated.
1433b4d96893SKarolina Drobnik */
memblock_remove_overlap_bottom_check(void)1434b4d96893SKarolina Drobnik static int memblock_remove_overlap_bottom_check(void)
1435b4d96893SKarolina Drobnik {
1436b4d96893SKarolina Drobnik struct memblock_region *rgn;
1437b4d96893SKarolina Drobnik phys_addr_t total_size;
1438b4d96893SKarolina Drobnik
1439b4d96893SKarolina Drobnik rgn = &memblock.memory.regions[0];
1440b4d96893SKarolina Drobnik
1441b4d96893SKarolina Drobnik struct region r1 = {
1442b4d96893SKarolina Drobnik .base = SZ_2M,
1443b4d96893SKarolina Drobnik .size = SZ_64M
1444b4d96893SKarolina Drobnik };
1445b4d96893SKarolina Drobnik struct region r2 = {
1446b4d96893SKarolina Drobnik .base = SZ_32M,
1447b4d96893SKarolina Drobnik .size = SZ_256M
1448b4d96893SKarolina Drobnik };
1449b4d96893SKarolina Drobnik
145076586c00SRebecca Mckeever PREFIX_PUSH();
145176586c00SRebecca Mckeever
1452b4d96893SKarolina Drobnik total_size = r2.base - r1.base;
1453b4d96893SKarolina Drobnik
14542c3dacbaSKarolina Drobnik reset_memblock_regions();
1455b4d96893SKarolina Drobnik memblock_add(r1.base, r1.size);
1456b4d96893SKarolina Drobnik memblock_remove(r2.base, r2.size);
1457b4d96893SKarolina Drobnik
145876586c00SRebecca Mckeever ASSERT_EQ(rgn->base, r1.base);
145976586c00SRebecca Mckeever ASSERT_EQ(rgn->size, total_size);
1460b4d96893SKarolina Drobnik
146176586c00SRebecca Mckeever ASSERT_EQ(memblock.memory.cnt, 1);
146276586c00SRebecca Mckeever ASSERT_EQ(memblock.memory.total_size, total_size);
146376586c00SRebecca Mckeever
146476586c00SRebecca Mckeever test_pass_pop();
146576586c00SRebecca Mckeever
1466b4d96893SKarolina Drobnik return 0;
1467b4d96893SKarolina Drobnik }
1468b4d96893SKarolina Drobnik
1469b4d96893SKarolina Drobnik /*
147060bba7b1SRebecca Mckeever * A test that tries to remove a region r2 that is within the range of
147160bba7b1SRebecca Mckeever * the already existing entry r1 (that is
147260bba7b1SRebecca Mckeever * (r1.base < r2.base) && (r2.base + r2.size < r1.base + r1.size)):
147360bba7b1SRebecca Mckeever *
147460bba7b1SRebecca Mckeever * +----+
147560bba7b1SRebecca Mckeever * | r2 |
147660bba7b1SRebecca Mckeever * +----+
147760bba7b1SRebecca Mckeever * | +-------------+....+---------------+ |
147860bba7b1SRebecca Mckeever * | | rgn1 | r1 | rgn2 | |
147960bba7b1SRebecca Mckeever * +-+-------------+----+---------------+-+
148060bba7b1SRebecca Mckeever * ^
148160bba7b1SRebecca Mckeever * |
148260bba7b1SRebecca Mckeever * r1.base
148360bba7b1SRebecca Mckeever *
148460bba7b1SRebecca Mckeever * Expect that the region is split into two - one that ends at r2.base and
148560bba7b1SRebecca Mckeever * another that starts at r2.base + r2.size, with appropriate sizes. The
148660bba7b1SRebecca Mckeever * region counter and total size are updated.
1487b4d96893SKarolina Drobnik */
memblock_remove_within_check(void)1488b4d96893SKarolina Drobnik static int memblock_remove_within_check(void)
1489b4d96893SKarolina Drobnik {
1490b4d96893SKarolina Drobnik struct memblock_region *rgn1, *rgn2;
1491b4d96893SKarolina Drobnik phys_addr_t r1_size, r2_size, total_size;
1492b4d96893SKarolina Drobnik
1493b4d96893SKarolina Drobnik rgn1 = &memblock.memory.regions[0];
1494b4d96893SKarolina Drobnik rgn2 = &memblock.memory.regions[1];
1495b4d96893SKarolina Drobnik
1496b4d96893SKarolina Drobnik struct region r1 = {
1497b4d96893SKarolina Drobnik .base = SZ_1M,
1498b4d96893SKarolina Drobnik .size = SZ_32M
1499b4d96893SKarolina Drobnik };
1500b4d96893SKarolina Drobnik struct region r2 = {
1501b4d96893SKarolina Drobnik .base = SZ_16M,
1502b4d96893SKarolina Drobnik .size = SZ_1M
1503b4d96893SKarolina Drobnik };
1504b4d96893SKarolina Drobnik
150576586c00SRebecca Mckeever PREFIX_PUSH();
150676586c00SRebecca Mckeever
1507b4d96893SKarolina Drobnik r1_size = r2.base - r1.base;
1508b4d96893SKarolina Drobnik r2_size = (r1.base + r1.size) - (r2.base + r2.size);
1509b4d96893SKarolina Drobnik total_size = r1_size + r2_size;
1510b4d96893SKarolina Drobnik
15112c3dacbaSKarolina Drobnik reset_memblock_regions();
1512b4d96893SKarolina Drobnik memblock_add(r1.base, r1.size);
1513b4d96893SKarolina Drobnik memblock_remove(r2.base, r2.size);
1514b4d96893SKarolina Drobnik
151576586c00SRebecca Mckeever ASSERT_EQ(rgn1->base, r1.base);
151676586c00SRebecca Mckeever ASSERT_EQ(rgn1->size, r1_size);
1517b4d96893SKarolina Drobnik
151876586c00SRebecca Mckeever ASSERT_EQ(rgn2->base, r2.base + r2.size);
151976586c00SRebecca Mckeever ASSERT_EQ(rgn2->size, r2_size);
1520b4d96893SKarolina Drobnik
152176586c00SRebecca Mckeever ASSERT_EQ(memblock.memory.cnt, 2);
152276586c00SRebecca Mckeever ASSERT_EQ(memblock.memory.total_size, total_size);
152376586c00SRebecca Mckeever
152476586c00SRebecca Mckeever test_pass_pop();
1525b4d96893SKarolina Drobnik
1526b4d96893SKarolina Drobnik return 0;
1527b4d96893SKarolina Drobnik }
1528b4d96893SKarolina Drobnik
152921a233f6SRebecca Mckeever /*
153021a233f6SRebecca Mckeever * A simple test that tries to remove a region r1 from the array of
153121a233f6SRebecca Mckeever * available memory regions when r1 is the only available region.
153221a233f6SRebecca Mckeever * Expect to add a memory block r1 and then remove r1 so that a dummy
153321a233f6SRebecca Mckeever * region is added. The region counter stays the same, and the total size
153421a233f6SRebecca Mckeever * is updated.
153521a233f6SRebecca Mckeever */
memblock_remove_only_region_check(void)153621a233f6SRebecca Mckeever static int memblock_remove_only_region_check(void)
153721a233f6SRebecca Mckeever {
153821a233f6SRebecca Mckeever struct memblock_region *rgn;
153921a233f6SRebecca Mckeever
154021a233f6SRebecca Mckeever rgn = &memblock.memory.regions[0];
154121a233f6SRebecca Mckeever
154221a233f6SRebecca Mckeever struct region r1 = {
154321a233f6SRebecca Mckeever .base = SZ_2K,
154421a233f6SRebecca Mckeever .size = SZ_4K
154521a233f6SRebecca Mckeever };
154621a233f6SRebecca Mckeever
154721a233f6SRebecca Mckeever PREFIX_PUSH();
154821a233f6SRebecca Mckeever
154921a233f6SRebecca Mckeever reset_memblock_regions();
155021a233f6SRebecca Mckeever memblock_add(r1.base, r1.size);
155121a233f6SRebecca Mckeever memblock_remove(r1.base, r1.size);
155221a233f6SRebecca Mckeever
155321a233f6SRebecca Mckeever ASSERT_EQ(rgn->base, 0);
155421a233f6SRebecca Mckeever ASSERT_EQ(rgn->size, 0);
155521a233f6SRebecca Mckeever
1556721f4a65SWei Yang ASSERT_EQ(memblock.memory.cnt, 0);
155721a233f6SRebecca Mckeever ASSERT_EQ(memblock.memory.total_size, 0);
155821a233f6SRebecca Mckeever
155921a233f6SRebecca Mckeever test_pass_pop();
156021a233f6SRebecca Mckeever
156121a233f6SRebecca Mckeever return 0;
156221a233f6SRebecca Mckeever }
156321a233f6SRebecca Mckeever
156421a233f6SRebecca Mckeever /*
156521a233f6SRebecca Mckeever * A simple test that tries remove a region r2 from the array of available
156621a233f6SRebecca Mckeever * memory regions when r2 extends past PHYS_ADDR_MAX:
156721a233f6SRebecca Mckeever *
156821a233f6SRebecca Mckeever * +--------+
156921a233f6SRebecca Mckeever * | r2 |
157021a233f6SRebecca Mckeever * +--------+
157121a233f6SRebecca Mckeever * | +---+....+
157221a233f6SRebecca Mckeever * | |rgn| |
157321a233f6SRebecca Mckeever * +------------------------+---+----+
157421a233f6SRebecca Mckeever *
157521a233f6SRebecca Mckeever * Expect that only the portion between PHYS_ADDR_MAX and r2.base is removed.
157621a233f6SRebecca Mckeever * Expect the total size of available memory to be updated and the counter to
157721a233f6SRebecca Mckeever * not be updated.
157821a233f6SRebecca Mckeever */
memblock_remove_near_max_check(void)157921a233f6SRebecca Mckeever static int memblock_remove_near_max_check(void)
158021a233f6SRebecca Mckeever {
158121a233f6SRebecca Mckeever struct memblock_region *rgn;
158221a233f6SRebecca Mckeever phys_addr_t total_size;
158321a233f6SRebecca Mckeever
158421a233f6SRebecca Mckeever rgn = &memblock.memory.regions[0];
158521a233f6SRebecca Mckeever
158621a233f6SRebecca Mckeever struct region r1 = {
158721a233f6SRebecca Mckeever .base = PHYS_ADDR_MAX - SZ_2M,
158821a233f6SRebecca Mckeever .size = SZ_2M
158921a233f6SRebecca Mckeever };
159021a233f6SRebecca Mckeever
159121a233f6SRebecca Mckeever struct region r2 = {
159221a233f6SRebecca Mckeever .base = PHYS_ADDR_MAX - SZ_1M,
159321a233f6SRebecca Mckeever .size = SZ_2M
159421a233f6SRebecca Mckeever };
159521a233f6SRebecca Mckeever
159621a233f6SRebecca Mckeever PREFIX_PUSH();
159721a233f6SRebecca Mckeever
159821a233f6SRebecca Mckeever total_size = r1.size - (PHYS_ADDR_MAX - r2.base);
159921a233f6SRebecca Mckeever
160021a233f6SRebecca Mckeever reset_memblock_regions();
160121a233f6SRebecca Mckeever memblock_add(r1.base, r1.size);
160221a233f6SRebecca Mckeever memblock_remove(r2.base, r2.size);
160321a233f6SRebecca Mckeever
160421a233f6SRebecca Mckeever ASSERT_EQ(rgn->base, r1.base);
160521a233f6SRebecca Mckeever ASSERT_EQ(rgn->size, total_size);
160621a233f6SRebecca Mckeever
160721a233f6SRebecca Mckeever ASSERT_EQ(memblock.memory.cnt, 1);
160821a233f6SRebecca Mckeever ASSERT_EQ(memblock.memory.total_size, total_size);
160921a233f6SRebecca Mckeever
161021a233f6SRebecca Mckeever test_pass_pop();
161121a233f6SRebecca Mckeever
161221a233f6SRebecca Mckeever return 0;
161321a233f6SRebecca Mckeever }
161421a233f6SRebecca Mckeever
161521a233f6SRebecca Mckeever /*
161621a233f6SRebecca Mckeever * A test that tries to remove a region r3 that overlaps with two existing
161721a233f6SRebecca Mckeever * regions r1 and r2:
161821a233f6SRebecca Mckeever *
161921a233f6SRebecca Mckeever * +----------------+
162021a233f6SRebecca Mckeever * | r3 |
162121a233f6SRebecca Mckeever * +----------------+
162221a233f6SRebecca Mckeever * | +----+..... ........+--------+
162321a233f6SRebecca Mckeever * | | |r1 : : |r2 | |
162421a233f6SRebecca Mckeever * +----+----+----+---+-------+--------+-----+
162521a233f6SRebecca Mckeever *
162621a233f6SRebecca Mckeever * Expect that only the intersections of r1 with r3 and r2 with r3 are removed
162721a233f6SRebecca Mckeever * from the available memory pool. Expect the total size of available memory to
162821a233f6SRebecca Mckeever * be updated and the counter to not be updated.
162921a233f6SRebecca Mckeever */
memblock_remove_overlap_two_check(void)163021a233f6SRebecca Mckeever static int memblock_remove_overlap_two_check(void)
163121a233f6SRebecca Mckeever {
163221a233f6SRebecca Mckeever struct memblock_region *rgn1, *rgn2;
163321a233f6SRebecca Mckeever phys_addr_t new_r1_size, new_r2_size, r2_end, r3_end, total_size;
163421a233f6SRebecca Mckeever
163521a233f6SRebecca Mckeever rgn1 = &memblock.memory.regions[0];
163621a233f6SRebecca Mckeever rgn2 = &memblock.memory.regions[1];
163721a233f6SRebecca Mckeever
163821a233f6SRebecca Mckeever struct region r1 = {
163921a233f6SRebecca Mckeever .base = SZ_16M,
164021a233f6SRebecca Mckeever .size = SZ_32M
164121a233f6SRebecca Mckeever };
164221a233f6SRebecca Mckeever struct region r2 = {
164321a233f6SRebecca Mckeever .base = SZ_64M,
164421a233f6SRebecca Mckeever .size = SZ_64M
164521a233f6SRebecca Mckeever };
164621a233f6SRebecca Mckeever struct region r3 = {
164721a233f6SRebecca Mckeever .base = SZ_32M,
164821a233f6SRebecca Mckeever .size = SZ_64M
164921a233f6SRebecca Mckeever };
165021a233f6SRebecca Mckeever
165121a233f6SRebecca Mckeever PREFIX_PUSH();
165221a233f6SRebecca Mckeever
165321a233f6SRebecca Mckeever r2_end = r2.base + r2.size;
165421a233f6SRebecca Mckeever r3_end = r3.base + r3.size;
165521a233f6SRebecca Mckeever new_r1_size = r3.base - r1.base;
165621a233f6SRebecca Mckeever new_r2_size = r2_end - r3_end;
165721a233f6SRebecca Mckeever total_size = new_r1_size + new_r2_size;
165821a233f6SRebecca Mckeever
165921a233f6SRebecca Mckeever reset_memblock_regions();
166021a233f6SRebecca Mckeever memblock_add(r1.base, r1.size);
166121a233f6SRebecca Mckeever memblock_add(r2.base, r2.size);
166221a233f6SRebecca Mckeever memblock_remove(r3.base, r3.size);
166321a233f6SRebecca Mckeever
166421a233f6SRebecca Mckeever ASSERT_EQ(rgn1->base, r1.base);
166521a233f6SRebecca Mckeever ASSERT_EQ(rgn1->size, new_r1_size);
166621a233f6SRebecca Mckeever
166721a233f6SRebecca Mckeever ASSERT_EQ(rgn2->base, r3_end);
166821a233f6SRebecca Mckeever ASSERT_EQ(rgn2->size, new_r2_size);
166921a233f6SRebecca Mckeever
167021a233f6SRebecca Mckeever ASSERT_EQ(memblock.memory.cnt, 2);
167121a233f6SRebecca Mckeever ASSERT_EQ(memblock.memory.total_size, total_size);
167221a233f6SRebecca Mckeever
167321a233f6SRebecca Mckeever test_pass_pop();
167421a233f6SRebecca Mckeever
167521a233f6SRebecca Mckeever return 0;
167621a233f6SRebecca Mckeever }
167721a233f6SRebecca Mckeever
memblock_remove_checks(void)1678b4d96893SKarolina Drobnik static int memblock_remove_checks(void)
1679b4d96893SKarolina Drobnik {
168076586c00SRebecca Mckeever prefix_reset();
168176586c00SRebecca Mckeever prefix_push(FUNC_REMOVE);
168276586c00SRebecca Mckeever test_print("Running %s tests...\n", FUNC_REMOVE);
168376586c00SRebecca Mckeever
1684b4d96893SKarolina Drobnik memblock_remove_simple_check();
1685b4d96893SKarolina Drobnik memblock_remove_absent_check();
1686b4d96893SKarolina Drobnik memblock_remove_overlap_top_check();
1687b4d96893SKarolina Drobnik memblock_remove_overlap_bottom_check();
1688b4d96893SKarolina Drobnik memblock_remove_within_check();
168921a233f6SRebecca Mckeever memblock_remove_only_region_check();
169021a233f6SRebecca Mckeever memblock_remove_near_max_check();
169121a233f6SRebecca Mckeever memblock_remove_overlap_two_check();
1692b4d96893SKarolina Drobnik
169376586c00SRebecca Mckeever prefix_pop();
169476586c00SRebecca Mckeever
1695b4d96893SKarolina Drobnik return 0;
1696b4d96893SKarolina Drobnik }
1697b4d96893SKarolina Drobnik
1698dd45dc07SKarolina Drobnik /*
1699a5550c05SRebecca Mckeever * A simple test that tries to free a memory block r1 that was marked
1700a5550c05SRebecca Mckeever * earlier as reserved. By "freeing" a region we mean overwriting it with
1701a5550c05SRebecca Mckeever * the next entry r2 in memblock.reserved:
1702a5550c05SRebecca Mckeever *
1703a5550c05SRebecca Mckeever * | ...... +----+ |
1704a5550c05SRebecca Mckeever * | : r1 : | r2 | |
1705a5550c05SRebecca Mckeever * +--------------+----+-----------+----+-+
1706a5550c05SRebecca Mckeever * ^
1707a5550c05SRebecca Mckeever * |
1708a5550c05SRebecca Mckeever * rgn.base
1709a5550c05SRebecca Mckeever *
1710a5550c05SRebecca Mckeever * Expect to reserve two memory regions and then erase r1 region with the
1711a5550c05SRebecca Mckeever * value of r2. The region counter and total size are updated.
1712dd45dc07SKarolina Drobnik */
memblock_free_simple_check(void)1713dd45dc07SKarolina Drobnik static int memblock_free_simple_check(void)
1714dd45dc07SKarolina Drobnik {
1715dd45dc07SKarolina Drobnik struct memblock_region *rgn;
1716dd45dc07SKarolina Drobnik
1717dd45dc07SKarolina Drobnik rgn = &memblock.reserved.regions[0];
1718dd45dc07SKarolina Drobnik
1719dd45dc07SKarolina Drobnik struct region r1 = {
1720dd45dc07SKarolina Drobnik .base = SZ_4M,
1721dd45dc07SKarolina Drobnik .size = SZ_1M
1722dd45dc07SKarolina Drobnik };
1723dd45dc07SKarolina Drobnik struct region r2 = {
1724dd45dc07SKarolina Drobnik .base = SZ_8M,
1725dd45dc07SKarolina Drobnik .size = SZ_1M
1726dd45dc07SKarolina Drobnik };
1727dd45dc07SKarolina Drobnik
172876586c00SRebecca Mckeever PREFIX_PUSH();
172976586c00SRebecca Mckeever
17302c3dacbaSKarolina Drobnik reset_memblock_regions();
1731dd45dc07SKarolina Drobnik memblock_reserve(r1.base, r1.size);
1732dd45dc07SKarolina Drobnik memblock_reserve(r2.base, r2.size);
1733dd45dc07SKarolina Drobnik memblock_free((void *)r1.base, r1.size);
1734dd45dc07SKarolina Drobnik
173576586c00SRebecca Mckeever ASSERT_EQ(rgn->base, r2.base);
173676586c00SRebecca Mckeever ASSERT_EQ(rgn->size, r2.size);
1737dd45dc07SKarolina Drobnik
173876586c00SRebecca Mckeever ASSERT_EQ(memblock.reserved.cnt, 1);
173976586c00SRebecca Mckeever ASSERT_EQ(memblock.reserved.total_size, r2.size);
174076586c00SRebecca Mckeever
174176586c00SRebecca Mckeever test_pass_pop();
1742dd45dc07SKarolina Drobnik
1743dd45dc07SKarolina Drobnik return 0;
1744dd45dc07SKarolina Drobnik }
1745dd45dc07SKarolina Drobnik
1746dd45dc07SKarolina Drobnik /*
1747a5550c05SRebecca Mckeever * A test that tries to free a region r2 that was not marked as reserved
1748a5550c05SRebecca Mckeever * (i.e. has no corresponding entry in memblock.reserved):
1749a5550c05SRebecca Mckeever *
1750a5550c05SRebecca Mckeever * +----------------+
1751a5550c05SRebecca Mckeever * | r2 |
1752a5550c05SRebecca Mckeever * +----------------+
1753a5550c05SRebecca Mckeever * | +----+ |
1754a5550c05SRebecca Mckeever * | | r1 | |
1755a5550c05SRebecca Mckeever * +--+----+------------------------------+
1756a5550c05SRebecca Mckeever * ^
1757a5550c05SRebecca Mckeever * |
1758a5550c05SRebecca Mckeever * rgn.base
1759a5550c05SRebecca Mckeever *
1760a5550c05SRebecca Mckeever * The array, regions counter and total size are not modified.
1761dd45dc07SKarolina Drobnik */
memblock_free_absent_check(void)1762dd45dc07SKarolina Drobnik static int memblock_free_absent_check(void)
1763dd45dc07SKarolina Drobnik {
1764dd45dc07SKarolina Drobnik struct memblock_region *rgn;
1765dd45dc07SKarolina Drobnik
1766dd45dc07SKarolina Drobnik rgn = &memblock.reserved.regions[0];
1767dd45dc07SKarolina Drobnik
1768dd45dc07SKarolina Drobnik struct region r1 = {
1769dd45dc07SKarolina Drobnik .base = SZ_2M,
1770dd45dc07SKarolina Drobnik .size = SZ_8K
1771dd45dc07SKarolina Drobnik };
1772dd45dc07SKarolina Drobnik struct region r2 = {
1773dd45dc07SKarolina Drobnik .base = SZ_16M,
1774dd45dc07SKarolina Drobnik .size = SZ_128M
1775dd45dc07SKarolina Drobnik };
1776dd45dc07SKarolina Drobnik
177776586c00SRebecca Mckeever PREFIX_PUSH();
177876586c00SRebecca Mckeever
17792c3dacbaSKarolina Drobnik reset_memblock_regions();
1780dd45dc07SKarolina Drobnik memblock_reserve(r1.base, r1.size);
1781dd45dc07SKarolina Drobnik memblock_free((void *)r2.base, r2.size);
1782dd45dc07SKarolina Drobnik
178376586c00SRebecca Mckeever ASSERT_EQ(rgn->base, r1.base);
178476586c00SRebecca Mckeever ASSERT_EQ(rgn->size, r1.size);
1785dd45dc07SKarolina Drobnik
178676586c00SRebecca Mckeever ASSERT_EQ(memblock.reserved.cnt, 1);
178776586c00SRebecca Mckeever ASSERT_EQ(memblock.reserved.total_size, r1.size);
178876586c00SRebecca Mckeever
178976586c00SRebecca Mckeever test_pass_pop();
1790dd45dc07SKarolina Drobnik
1791dd45dc07SKarolina Drobnik return 0;
1792dd45dc07SKarolina Drobnik }
1793dd45dc07SKarolina Drobnik
1794dd45dc07SKarolina Drobnik /*
1795a5550c05SRebecca Mckeever * A test that tries to free a region r2 that overlaps with the beginning
1796a5550c05SRebecca Mckeever * of the already existing entry r1 (that is r1.base < r2.base + r2.size):
1797a5550c05SRebecca Mckeever *
1798a5550c05SRebecca Mckeever * +----+
1799a5550c05SRebecca Mckeever * | r2 |
1800a5550c05SRebecca Mckeever * +----+
1801a5550c05SRebecca Mckeever * | ...+--------------+ |
1802a5550c05SRebecca Mckeever * | : | r1 | |
1803a5550c05SRebecca Mckeever * +----+--+--------------+---------------+
1804a5550c05SRebecca Mckeever * ^ ^
1805a5550c05SRebecca Mckeever * | |
1806a5550c05SRebecca Mckeever * | rgn.base
1807a5550c05SRebecca Mckeever * |
1808a5550c05SRebecca Mckeever * r1.base
1809a5550c05SRebecca Mckeever *
1810a5550c05SRebecca Mckeever * Expect that only the intersection of both regions is freed. The
1811a5550c05SRebecca Mckeever * regions counter and total size are updated.
1812dd45dc07SKarolina Drobnik */
memblock_free_overlap_top_check(void)1813dd45dc07SKarolina Drobnik static int memblock_free_overlap_top_check(void)
1814dd45dc07SKarolina Drobnik {
1815dd45dc07SKarolina Drobnik struct memblock_region *rgn;
1816dd45dc07SKarolina Drobnik phys_addr_t total_size;
1817dd45dc07SKarolina Drobnik
1818dd45dc07SKarolina Drobnik rgn = &memblock.reserved.regions[0];
1819dd45dc07SKarolina Drobnik
1820dd45dc07SKarolina Drobnik struct region r1 = {
1821dd45dc07SKarolina Drobnik .base = SZ_8M,
1822dd45dc07SKarolina Drobnik .size = SZ_32M
1823dd45dc07SKarolina Drobnik };
1824dd45dc07SKarolina Drobnik struct region r2 = {
1825dd45dc07SKarolina Drobnik .base = SZ_1M,
1826dd45dc07SKarolina Drobnik .size = SZ_8M
1827dd45dc07SKarolina Drobnik };
1828dd45dc07SKarolina Drobnik
182976586c00SRebecca Mckeever PREFIX_PUSH();
183076586c00SRebecca Mckeever
1831dd45dc07SKarolina Drobnik total_size = (r1.size + r1.base) - (r2.base + r2.size);
1832dd45dc07SKarolina Drobnik
18332c3dacbaSKarolina Drobnik reset_memblock_regions();
1834dd45dc07SKarolina Drobnik memblock_reserve(r1.base, r1.size);
1835dd45dc07SKarolina Drobnik memblock_free((void *)r2.base, r2.size);
1836dd45dc07SKarolina Drobnik
183776586c00SRebecca Mckeever ASSERT_EQ(rgn->base, r2.base + r2.size);
183876586c00SRebecca Mckeever ASSERT_EQ(rgn->size, total_size);
1839dd45dc07SKarolina Drobnik
184076586c00SRebecca Mckeever ASSERT_EQ(memblock.reserved.cnt, 1);
184176586c00SRebecca Mckeever ASSERT_EQ(memblock.reserved.total_size, total_size);
184276586c00SRebecca Mckeever
184376586c00SRebecca Mckeever test_pass_pop();
1844dd45dc07SKarolina Drobnik
1845dd45dc07SKarolina Drobnik return 0;
1846dd45dc07SKarolina Drobnik }
1847dd45dc07SKarolina Drobnik
1848dd45dc07SKarolina Drobnik /*
1849a5550c05SRebecca Mckeever * A test that tries to free a region r2 that overlaps with the end of
1850a5550c05SRebecca Mckeever * the already existing entry r1 (that is r2.base < r1.base + r1.size):
1851a5550c05SRebecca Mckeever *
1852a5550c05SRebecca Mckeever * +----------------+
1853a5550c05SRebecca Mckeever * | r2 |
1854a5550c05SRebecca Mckeever * +----------------+
1855a5550c05SRebecca Mckeever * | +-----------+..... |
1856a5550c05SRebecca Mckeever * | | r1 | : |
1857a5550c05SRebecca Mckeever * +----+-----------+----+----------------+
1858a5550c05SRebecca Mckeever *
1859a5550c05SRebecca Mckeever * Expect that only the intersection of both regions is freed. The
1860a5550c05SRebecca Mckeever * regions counter and total size are updated.
1861dd45dc07SKarolina Drobnik */
memblock_free_overlap_bottom_check(void)1862dd45dc07SKarolina Drobnik static int memblock_free_overlap_bottom_check(void)
1863dd45dc07SKarolina Drobnik {
1864dd45dc07SKarolina Drobnik struct memblock_region *rgn;
1865dd45dc07SKarolina Drobnik phys_addr_t total_size;
1866dd45dc07SKarolina Drobnik
1867dd45dc07SKarolina Drobnik rgn = &memblock.reserved.regions[0];
1868dd45dc07SKarolina Drobnik
1869dd45dc07SKarolina Drobnik struct region r1 = {
1870dd45dc07SKarolina Drobnik .base = SZ_8M,
1871dd45dc07SKarolina Drobnik .size = SZ_32M
1872dd45dc07SKarolina Drobnik };
1873dd45dc07SKarolina Drobnik struct region r2 = {
1874dd45dc07SKarolina Drobnik .base = SZ_32M,
1875dd45dc07SKarolina Drobnik .size = SZ_32M
1876dd45dc07SKarolina Drobnik };
1877dd45dc07SKarolina Drobnik
187876586c00SRebecca Mckeever PREFIX_PUSH();
187976586c00SRebecca Mckeever
1880dd45dc07SKarolina Drobnik total_size = r2.base - r1.base;
1881dd45dc07SKarolina Drobnik
18822c3dacbaSKarolina Drobnik reset_memblock_regions();
1883dd45dc07SKarolina Drobnik memblock_reserve(r1.base, r1.size);
1884dd45dc07SKarolina Drobnik memblock_free((void *)r2.base, r2.size);
1885dd45dc07SKarolina Drobnik
188676586c00SRebecca Mckeever ASSERT_EQ(rgn->base, r1.base);
188776586c00SRebecca Mckeever ASSERT_EQ(rgn->size, total_size);
1888dd45dc07SKarolina Drobnik
188976586c00SRebecca Mckeever ASSERT_EQ(memblock.reserved.cnt, 1);
189076586c00SRebecca Mckeever ASSERT_EQ(memblock.reserved.total_size, total_size);
189176586c00SRebecca Mckeever
189276586c00SRebecca Mckeever test_pass_pop();
1893dd45dc07SKarolina Drobnik
1894dd45dc07SKarolina Drobnik return 0;
1895dd45dc07SKarolina Drobnik }
1896dd45dc07SKarolina Drobnik
1897dd45dc07SKarolina Drobnik /*
1898a5550c05SRebecca Mckeever * A test that tries to free a region r2 that is within the range of the
1899a5550c05SRebecca Mckeever * already existing entry r1 (that is
1900a5550c05SRebecca Mckeever * (r1.base < r2.base) && (r2.base + r2.size < r1.base + r1.size)):
1901a5550c05SRebecca Mckeever *
1902a5550c05SRebecca Mckeever * +----+
1903a5550c05SRebecca Mckeever * | r2 |
1904a5550c05SRebecca Mckeever * +----+
1905a5550c05SRebecca Mckeever * | +------------+....+---------------+
1906a5550c05SRebecca Mckeever * | | rgn1 | r1 | rgn2 |
1907a5550c05SRebecca Mckeever * +----+------------+----+---------------+
1908a5550c05SRebecca Mckeever * ^
1909a5550c05SRebecca Mckeever * |
1910a5550c05SRebecca Mckeever * r1.base
1911a5550c05SRebecca Mckeever *
1912a5550c05SRebecca Mckeever * Expect that the region is split into two - one that ends at r2.base and
1913a5550c05SRebecca Mckeever * another that starts at r2.base + r2.size, with appropriate sizes. The
1914a5550c05SRebecca Mckeever * region counter and total size fields are updated.
1915dd45dc07SKarolina Drobnik */
memblock_free_within_check(void)1916dd45dc07SKarolina Drobnik static int memblock_free_within_check(void)
1917dd45dc07SKarolina Drobnik {
1918dd45dc07SKarolina Drobnik struct memblock_region *rgn1, *rgn2;
1919dd45dc07SKarolina Drobnik phys_addr_t r1_size, r2_size, total_size;
1920dd45dc07SKarolina Drobnik
1921dd45dc07SKarolina Drobnik rgn1 = &memblock.reserved.regions[0];
1922dd45dc07SKarolina Drobnik rgn2 = &memblock.reserved.regions[1];
1923dd45dc07SKarolina Drobnik
1924dd45dc07SKarolina Drobnik struct region r1 = {
1925dd45dc07SKarolina Drobnik .base = SZ_1M,
1926dd45dc07SKarolina Drobnik .size = SZ_8M
1927dd45dc07SKarolina Drobnik };
1928dd45dc07SKarolina Drobnik struct region r2 = {
1929dd45dc07SKarolina Drobnik .base = SZ_4M,
1930dd45dc07SKarolina Drobnik .size = SZ_1M
1931dd45dc07SKarolina Drobnik };
1932dd45dc07SKarolina Drobnik
193376586c00SRebecca Mckeever PREFIX_PUSH();
193476586c00SRebecca Mckeever
1935dd45dc07SKarolina Drobnik r1_size = r2.base - r1.base;
1936dd45dc07SKarolina Drobnik r2_size = (r1.base + r1.size) - (r2.base + r2.size);
1937dd45dc07SKarolina Drobnik total_size = r1_size + r2_size;
1938dd45dc07SKarolina Drobnik
19392c3dacbaSKarolina Drobnik reset_memblock_regions();
1940dd45dc07SKarolina Drobnik memblock_reserve(r1.base, r1.size);
1941dd45dc07SKarolina Drobnik memblock_free((void *)r2.base, r2.size);
1942dd45dc07SKarolina Drobnik
194376586c00SRebecca Mckeever ASSERT_EQ(rgn1->base, r1.base);
194476586c00SRebecca Mckeever ASSERT_EQ(rgn1->size, r1_size);
1945dd45dc07SKarolina Drobnik
194676586c00SRebecca Mckeever ASSERT_EQ(rgn2->base, r2.base + r2.size);
194776586c00SRebecca Mckeever ASSERT_EQ(rgn2->size, r2_size);
1948dd45dc07SKarolina Drobnik
194976586c00SRebecca Mckeever ASSERT_EQ(memblock.reserved.cnt, 2);
195076586c00SRebecca Mckeever ASSERT_EQ(memblock.reserved.total_size, total_size);
195176586c00SRebecca Mckeever
195276586c00SRebecca Mckeever test_pass_pop();
1953dd45dc07SKarolina Drobnik
1954dd45dc07SKarolina Drobnik return 0;
1955dd45dc07SKarolina Drobnik }
1956dd45dc07SKarolina Drobnik
195721a233f6SRebecca Mckeever /*
195821a233f6SRebecca Mckeever * A simple test that tries to free a memory block r1 that was marked
195921a233f6SRebecca Mckeever * earlier as reserved when r1 is the only available region.
196021a233f6SRebecca Mckeever * Expect to reserve a memory block r1 and then free r1 so that r1 is
196121a233f6SRebecca Mckeever * overwritten with a dummy region. The region counter stays the same,
196221a233f6SRebecca Mckeever * and the total size is updated.
196321a233f6SRebecca Mckeever */
memblock_free_only_region_check(void)196421a233f6SRebecca Mckeever static int memblock_free_only_region_check(void)
196521a233f6SRebecca Mckeever {
196621a233f6SRebecca Mckeever struct memblock_region *rgn;
196721a233f6SRebecca Mckeever
196821a233f6SRebecca Mckeever rgn = &memblock.reserved.regions[0];
196921a233f6SRebecca Mckeever
197021a233f6SRebecca Mckeever struct region r1 = {
197121a233f6SRebecca Mckeever .base = SZ_2K,
197221a233f6SRebecca Mckeever .size = SZ_4K
197321a233f6SRebecca Mckeever };
197421a233f6SRebecca Mckeever
197521a233f6SRebecca Mckeever PREFIX_PUSH();
197621a233f6SRebecca Mckeever
197721a233f6SRebecca Mckeever reset_memblock_regions();
197821a233f6SRebecca Mckeever memblock_reserve(r1.base, r1.size);
197921a233f6SRebecca Mckeever memblock_free((void *)r1.base, r1.size);
198021a233f6SRebecca Mckeever
198121a233f6SRebecca Mckeever ASSERT_EQ(rgn->base, 0);
198221a233f6SRebecca Mckeever ASSERT_EQ(rgn->size, 0);
198321a233f6SRebecca Mckeever
1984721f4a65SWei Yang ASSERT_EQ(memblock.reserved.cnt, 0);
198521a233f6SRebecca Mckeever ASSERT_EQ(memblock.reserved.total_size, 0);
198621a233f6SRebecca Mckeever
198721a233f6SRebecca Mckeever test_pass_pop();
198821a233f6SRebecca Mckeever
198921a233f6SRebecca Mckeever return 0;
199021a233f6SRebecca Mckeever }
199121a233f6SRebecca Mckeever
199221a233f6SRebecca Mckeever /*
199321a233f6SRebecca Mckeever * A simple test that tries free a region r2 when r2 extends past PHYS_ADDR_MAX:
199421a233f6SRebecca Mckeever *
199521a233f6SRebecca Mckeever * +--------+
199621a233f6SRebecca Mckeever * | r2 |
199721a233f6SRebecca Mckeever * +--------+
199821a233f6SRebecca Mckeever * | +---+....+
199921a233f6SRebecca Mckeever * | |rgn| |
200021a233f6SRebecca Mckeever * +------------------------+---+----+
200121a233f6SRebecca Mckeever *
200221a233f6SRebecca Mckeever * Expect that only the portion between PHYS_ADDR_MAX and r2.base is freed.
200321a233f6SRebecca Mckeever * Expect the total size of reserved memory to be updated and the counter to
200421a233f6SRebecca Mckeever * not be updated.
200521a233f6SRebecca Mckeever */
memblock_free_near_max_check(void)200621a233f6SRebecca Mckeever static int memblock_free_near_max_check(void)
200721a233f6SRebecca Mckeever {
200821a233f6SRebecca Mckeever struct memblock_region *rgn;
200921a233f6SRebecca Mckeever phys_addr_t total_size;
201021a233f6SRebecca Mckeever
201121a233f6SRebecca Mckeever rgn = &memblock.reserved.regions[0];
201221a233f6SRebecca Mckeever
201321a233f6SRebecca Mckeever struct region r1 = {
201421a233f6SRebecca Mckeever .base = PHYS_ADDR_MAX - SZ_2M,
201521a233f6SRebecca Mckeever .size = SZ_2M
201621a233f6SRebecca Mckeever };
201721a233f6SRebecca Mckeever
201821a233f6SRebecca Mckeever struct region r2 = {
201921a233f6SRebecca Mckeever .base = PHYS_ADDR_MAX - SZ_1M,
202021a233f6SRebecca Mckeever .size = SZ_2M
202121a233f6SRebecca Mckeever };
202221a233f6SRebecca Mckeever
202321a233f6SRebecca Mckeever PREFIX_PUSH();
202421a233f6SRebecca Mckeever
202521a233f6SRebecca Mckeever total_size = r1.size - (PHYS_ADDR_MAX - r2.base);
202621a233f6SRebecca Mckeever
202721a233f6SRebecca Mckeever reset_memblock_regions();
202821a233f6SRebecca Mckeever memblock_reserve(r1.base, r1.size);
202921a233f6SRebecca Mckeever memblock_free((void *)r2.base, r2.size);
203021a233f6SRebecca Mckeever
203121a233f6SRebecca Mckeever ASSERT_EQ(rgn->base, r1.base);
203221a233f6SRebecca Mckeever ASSERT_EQ(rgn->size, total_size);
203321a233f6SRebecca Mckeever
203421a233f6SRebecca Mckeever ASSERT_EQ(memblock.reserved.cnt, 1);
203521a233f6SRebecca Mckeever ASSERT_EQ(memblock.reserved.total_size, total_size);
203621a233f6SRebecca Mckeever
203721a233f6SRebecca Mckeever test_pass_pop();
203821a233f6SRebecca Mckeever
203921a233f6SRebecca Mckeever return 0;
204021a233f6SRebecca Mckeever }
204121a233f6SRebecca Mckeever
204221a233f6SRebecca Mckeever /*
204321a233f6SRebecca Mckeever * A test that tries to free a reserved region r3 that overlaps with two
204421a233f6SRebecca Mckeever * existing reserved regions r1 and r2:
204521a233f6SRebecca Mckeever *
204621a233f6SRebecca Mckeever * +----------------+
204721a233f6SRebecca Mckeever * | r3 |
204821a233f6SRebecca Mckeever * +----------------+
204921a233f6SRebecca Mckeever * | +----+..... ........+--------+
205021a233f6SRebecca Mckeever * | | |r1 : : |r2 | |
205121a233f6SRebecca Mckeever * +----+----+----+---+-------+--------+-----+
205221a233f6SRebecca Mckeever *
205321a233f6SRebecca Mckeever * Expect that only the intersections of r1 with r3 and r2 with r3 are freed
205421a233f6SRebecca Mckeever * from the collection of reserved memory. Expect the total size of reserved
205521a233f6SRebecca Mckeever * memory to be updated and the counter to not be updated.
205621a233f6SRebecca Mckeever */
memblock_free_overlap_two_check(void)205721a233f6SRebecca Mckeever static int memblock_free_overlap_two_check(void)
205821a233f6SRebecca Mckeever {
205921a233f6SRebecca Mckeever struct memblock_region *rgn1, *rgn2;
206021a233f6SRebecca Mckeever phys_addr_t new_r1_size, new_r2_size, r2_end, r3_end, total_size;
206121a233f6SRebecca Mckeever
206221a233f6SRebecca Mckeever rgn1 = &memblock.reserved.regions[0];
206321a233f6SRebecca Mckeever rgn2 = &memblock.reserved.regions[1];
206421a233f6SRebecca Mckeever
206521a233f6SRebecca Mckeever struct region r1 = {
206621a233f6SRebecca Mckeever .base = SZ_16M,
206721a233f6SRebecca Mckeever .size = SZ_32M
206821a233f6SRebecca Mckeever };
206921a233f6SRebecca Mckeever struct region r2 = {
207021a233f6SRebecca Mckeever .base = SZ_64M,
207121a233f6SRebecca Mckeever .size = SZ_64M
207221a233f6SRebecca Mckeever };
207321a233f6SRebecca Mckeever struct region r3 = {
207421a233f6SRebecca Mckeever .base = SZ_32M,
207521a233f6SRebecca Mckeever .size = SZ_64M
207621a233f6SRebecca Mckeever };
207721a233f6SRebecca Mckeever
207821a233f6SRebecca Mckeever PREFIX_PUSH();
207921a233f6SRebecca Mckeever
208021a233f6SRebecca Mckeever r2_end = r2.base + r2.size;
208121a233f6SRebecca Mckeever r3_end = r3.base + r3.size;
208221a233f6SRebecca Mckeever new_r1_size = r3.base - r1.base;
208321a233f6SRebecca Mckeever new_r2_size = r2_end - r3_end;
208421a233f6SRebecca Mckeever total_size = new_r1_size + new_r2_size;
208521a233f6SRebecca Mckeever
208621a233f6SRebecca Mckeever reset_memblock_regions();
208721a233f6SRebecca Mckeever memblock_reserve(r1.base, r1.size);
208821a233f6SRebecca Mckeever memblock_reserve(r2.base, r2.size);
208921a233f6SRebecca Mckeever memblock_free((void *)r3.base, r3.size);
209021a233f6SRebecca Mckeever
209121a233f6SRebecca Mckeever ASSERT_EQ(rgn1->base, r1.base);
209221a233f6SRebecca Mckeever ASSERT_EQ(rgn1->size, new_r1_size);
209321a233f6SRebecca Mckeever
209421a233f6SRebecca Mckeever ASSERT_EQ(rgn2->base, r3_end);
209521a233f6SRebecca Mckeever ASSERT_EQ(rgn2->size, new_r2_size);
209621a233f6SRebecca Mckeever
209721a233f6SRebecca Mckeever ASSERT_EQ(memblock.reserved.cnt, 2);
209821a233f6SRebecca Mckeever ASSERT_EQ(memblock.reserved.total_size, total_size);
209921a233f6SRebecca Mckeever
210021a233f6SRebecca Mckeever test_pass_pop();
210121a233f6SRebecca Mckeever
210221a233f6SRebecca Mckeever return 0;
210321a233f6SRebecca Mckeever }
210421a233f6SRebecca Mckeever
memblock_free_checks(void)2105dd45dc07SKarolina Drobnik static int memblock_free_checks(void)
2106dd45dc07SKarolina Drobnik {
210776586c00SRebecca Mckeever prefix_reset();
210876586c00SRebecca Mckeever prefix_push(FUNC_FREE);
210976586c00SRebecca Mckeever test_print("Running %s tests...\n", FUNC_FREE);
211076586c00SRebecca Mckeever
2111dd45dc07SKarolina Drobnik memblock_free_simple_check();
2112dd45dc07SKarolina Drobnik memblock_free_absent_check();
2113dd45dc07SKarolina Drobnik memblock_free_overlap_top_check();
2114dd45dc07SKarolina Drobnik memblock_free_overlap_bottom_check();
2115dd45dc07SKarolina Drobnik memblock_free_within_check();
211621a233f6SRebecca Mckeever memblock_free_only_region_check();
211721a233f6SRebecca Mckeever memblock_free_near_max_check();
211821a233f6SRebecca Mckeever memblock_free_overlap_two_check();
2119dd45dc07SKarolina Drobnik
212076586c00SRebecca Mckeever prefix_pop();
212176586c00SRebecca Mckeever
2122dd45dc07SKarolina Drobnik return 0;
2123dd45dc07SKarolina Drobnik }
2124dd45dc07SKarolina Drobnik
memblock_set_bottom_up_check(void)2125a541c6d4SRebecca Mckeever static int memblock_set_bottom_up_check(void)
2126a541c6d4SRebecca Mckeever {
2127a541c6d4SRebecca Mckeever prefix_push("memblock_set_bottom_up");
2128a541c6d4SRebecca Mckeever
2129a541c6d4SRebecca Mckeever memblock_set_bottom_up(false);
2130a541c6d4SRebecca Mckeever ASSERT_EQ(memblock.bottom_up, false);
2131a541c6d4SRebecca Mckeever memblock_set_bottom_up(true);
2132a541c6d4SRebecca Mckeever ASSERT_EQ(memblock.bottom_up, true);
2133a541c6d4SRebecca Mckeever
2134a541c6d4SRebecca Mckeever reset_memblock_attributes();
2135a541c6d4SRebecca Mckeever test_pass_pop();
2136a541c6d4SRebecca Mckeever
2137a541c6d4SRebecca Mckeever return 0;
2138a541c6d4SRebecca Mckeever }
2139a541c6d4SRebecca Mckeever
memblock_bottom_up_check(void)2140a541c6d4SRebecca Mckeever static int memblock_bottom_up_check(void)
2141a541c6d4SRebecca Mckeever {
2142a541c6d4SRebecca Mckeever prefix_push("memblock_bottom_up");
2143a541c6d4SRebecca Mckeever
2144a541c6d4SRebecca Mckeever memblock_set_bottom_up(false);
2145a541c6d4SRebecca Mckeever ASSERT_EQ(memblock_bottom_up(), memblock.bottom_up);
2146a541c6d4SRebecca Mckeever ASSERT_EQ(memblock_bottom_up(), false);
2147a541c6d4SRebecca Mckeever memblock_set_bottom_up(true);
2148a541c6d4SRebecca Mckeever ASSERT_EQ(memblock_bottom_up(), memblock.bottom_up);
2149a541c6d4SRebecca Mckeever ASSERT_EQ(memblock_bottom_up(), true);
2150a541c6d4SRebecca Mckeever
2151a541c6d4SRebecca Mckeever reset_memblock_attributes();
2152a541c6d4SRebecca Mckeever test_pass_pop();
2153a541c6d4SRebecca Mckeever
2154a541c6d4SRebecca Mckeever return 0;
2155a541c6d4SRebecca Mckeever }
2156a541c6d4SRebecca Mckeever
memblock_bottom_up_checks(void)2157a541c6d4SRebecca Mckeever static int memblock_bottom_up_checks(void)
2158a541c6d4SRebecca Mckeever {
2159a541c6d4SRebecca Mckeever test_print("Running memblock_*bottom_up tests...\n");
2160a541c6d4SRebecca Mckeever
2161a541c6d4SRebecca Mckeever prefix_reset();
2162a541c6d4SRebecca Mckeever memblock_set_bottom_up_check();
2163a541c6d4SRebecca Mckeever prefix_reset();
2164a541c6d4SRebecca Mckeever memblock_bottom_up_check();
2165a541c6d4SRebecca Mckeever
2166a541c6d4SRebecca Mckeever return 0;
2167a541c6d4SRebecca Mckeever }
2168a541c6d4SRebecca Mckeever
2169dcd45ad2SRebecca Mckeever /*
2170dcd45ad2SRebecca Mckeever * A test that tries to trim memory when both ends of the memory region are
2171dcd45ad2SRebecca Mckeever * aligned. Expect that the memory will not be trimmed. Expect the counter to
2172dcd45ad2SRebecca Mckeever * not be updated.
2173dcd45ad2SRebecca Mckeever */
memblock_trim_memory_aligned_check(void)2174dcd45ad2SRebecca Mckeever static int memblock_trim_memory_aligned_check(void)
2175dcd45ad2SRebecca Mckeever {
2176dcd45ad2SRebecca Mckeever struct memblock_region *rgn;
2177dcd45ad2SRebecca Mckeever const phys_addr_t alignment = SMP_CACHE_BYTES;
2178dcd45ad2SRebecca Mckeever
2179dcd45ad2SRebecca Mckeever rgn = &memblock.memory.regions[0];
2180dcd45ad2SRebecca Mckeever
2181dcd45ad2SRebecca Mckeever struct region r = {
2182dcd45ad2SRebecca Mckeever .base = alignment,
2183dcd45ad2SRebecca Mckeever .size = alignment * 4
2184dcd45ad2SRebecca Mckeever };
2185dcd45ad2SRebecca Mckeever
2186dcd45ad2SRebecca Mckeever PREFIX_PUSH();
2187dcd45ad2SRebecca Mckeever
2188dcd45ad2SRebecca Mckeever reset_memblock_regions();
2189dcd45ad2SRebecca Mckeever memblock_add(r.base, r.size);
2190dcd45ad2SRebecca Mckeever memblock_trim_memory(alignment);
2191dcd45ad2SRebecca Mckeever
2192dcd45ad2SRebecca Mckeever ASSERT_EQ(rgn->base, r.base);
2193dcd45ad2SRebecca Mckeever ASSERT_EQ(rgn->size, r.size);
2194dcd45ad2SRebecca Mckeever
2195dcd45ad2SRebecca Mckeever ASSERT_EQ(memblock.memory.cnt, 1);
2196dcd45ad2SRebecca Mckeever
2197dcd45ad2SRebecca Mckeever test_pass_pop();
2198dcd45ad2SRebecca Mckeever
2199dcd45ad2SRebecca Mckeever return 0;
2200dcd45ad2SRebecca Mckeever }
2201dcd45ad2SRebecca Mckeever
2202dcd45ad2SRebecca Mckeever /*
2203dcd45ad2SRebecca Mckeever * A test that tries to trim memory when there are two available regions, r1 and
2204dcd45ad2SRebecca Mckeever * r2. Region r1 is aligned on both ends and region r2 is unaligned on one end
2205dcd45ad2SRebecca Mckeever * and smaller than the alignment:
2206dcd45ad2SRebecca Mckeever *
2207dcd45ad2SRebecca Mckeever * alignment
2208dcd45ad2SRebecca Mckeever * |--------|
2209dcd45ad2SRebecca Mckeever * | +-----------------+ +------+ |
2210dcd45ad2SRebecca Mckeever * | | r1 | | r2 | |
2211dcd45ad2SRebecca Mckeever * +--------+-----------------+--------+------+---+
2212dcd45ad2SRebecca Mckeever * ^ ^ ^ ^ ^
2213dcd45ad2SRebecca Mckeever * |________|________|________| |
2214dcd45ad2SRebecca Mckeever * | Unaligned address
2215dcd45ad2SRebecca Mckeever * Aligned addresses
2216dcd45ad2SRebecca Mckeever *
2217dcd45ad2SRebecca Mckeever * Expect that r1 will not be trimmed and r2 will be removed. Expect the
2218dcd45ad2SRebecca Mckeever * counter to be updated.
2219dcd45ad2SRebecca Mckeever */
memblock_trim_memory_too_small_check(void)2220dcd45ad2SRebecca Mckeever static int memblock_trim_memory_too_small_check(void)
2221dcd45ad2SRebecca Mckeever {
2222dcd45ad2SRebecca Mckeever struct memblock_region *rgn;
2223dcd45ad2SRebecca Mckeever const phys_addr_t alignment = SMP_CACHE_BYTES;
2224dcd45ad2SRebecca Mckeever
2225dcd45ad2SRebecca Mckeever rgn = &memblock.memory.regions[0];
2226dcd45ad2SRebecca Mckeever
2227dcd45ad2SRebecca Mckeever struct region r1 = {
2228dcd45ad2SRebecca Mckeever .base = alignment,
2229dcd45ad2SRebecca Mckeever .size = alignment * 2
2230dcd45ad2SRebecca Mckeever };
2231dcd45ad2SRebecca Mckeever struct region r2 = {
2232dcd45ad2SRebecca Mckeever .base = alignment * 4,
2233dcd45ad2SRebecca Mckeever .size = alignment - SZ_2
2234dcd45ad2SRebecca Mckeever };
2235dcd45ad2SRebecca Mckeever
2236dcd45ad2SRebecca Mckeever PREFIX_PUSH();
2237dcd45ad2SRebecca Mckeever
2238dcd45ad2SRebecca Mckeever reset_memblock_regions();
2239dcd45ad2SRebecca Mckeever memblock_add(r1.base, r1.size);
2240dcd45ad2SRebecca Mckeever memblock_add(r2.base, r2.size);
2241dcd45ad2SRebecca Mckeever memblock_trim_memory(alignment);
2242dcd45ad2SRebecca Mckeever
2243dcd45ad2SRebecca Mckeever ASSERT_EQ(rgn->base, r1.base);
2244dcd45ad2SRebecca Mckeever ASSERT_EQ(rgn->size, r1.size);
2245dcd45ad2SRebecca Mckeever
2246dcd45ad2SRebecca Mckeever ASSERT_EQ(memblock.memory.cnt, 1);
2247dcd45ad2SRebecca Mckeever
2248dcd45ad2SRebecca Mckeever test_pass_pop();
2249dcd45ad2SRebecca Mckeever
2250dcd45ad2SRebecca Mckeever return 0;
2251dcd45ad2SRebecca Mckeever }
2252dcd45ad2SRebecca Mckeever
2253dcd45ad2SRebecca Mckeever /*
2254dcd45ad2SRebecca Mckeever * A test that tries to trim memory when there are two available regions, r1 and
2255dcd45ad2SRebecca Mckeever * r2. Region r1 is aligned on both ends and region r2 is unaligned at the base
2256dcd45ad2SRebecca Mckeever * and aligned at the end:
2257dcd45ad2SRebecca Mckeever *
2258dcd45ad2SRebecca Mckeever * Unaligned address
2259dcd45ad2SRebecca Mckeever * |
2260dcd45ad2SRebecca Mckeever * v
2261dcd45ad2SRebecca Mckeever * | +-----------------+ +---------------+ |
2262dcd45ad2SRebecca Mckeever * | | r1 | | r2 | |
2263dcd45ad2SRebecca Mckeever * +--------+-----------------+----------+---------------+---+
2264dcd45ad2SRebecca Mckeever * ^ ^ ^ ^ ^ ^
2265dcd45ad2SRebecca Mckeever * |________|________|________|________|________|
2266dcd45ad2SRebecca Mckeever * |
2267dcd45ad2SRebecca Mckeever * Aligned addresses
2268dcd45ad2SRebecca Mckeever *
2269dcd45ad2SRebecca Mckeever * Expect that r1 will not be trimmed and r2 will be trimmed at the base.
2270dcd45ad2SRebecca Mckeever * Expect the counter to not be updated.
2271dcd45ad2SRebecca Mckeever */
memblock_trim_memory_unaligned_base_check(void)2272dcd45ad2SRebecca Mckeever static int memblock_trim_memory_unaligned_base_check(void)
2273dcd45ad2SRebecca Mckeever {
2274dcd45ad2SRebecca Mckeever struct memblock_region *rgn1, *rgn2;
2275dcd45ad2SRebecca Mckeever const phys_addr_t alignment = SMP_CACHE_BYTES;
2276dcd45ad2SRebecca Mckeever phys_addr_t offset = SZ_2;
2277dcd45ad2SRebecca Mckeever phys_addr_t new_r2_base, new_r2_size;
2278dcd45ad2SRebecca Mckeever
2279dcd45ad2SRebecca Mckeever rgn1 = &memblock.memory.regions[0];
2280dcd45ad2SRebecca Mckeever rgn2 = &memblock.memory.regions[1];
2281dcd45ad2SRebecca Mckeever
2282dcd45ad2SRebecca Mckeever struct region r1 = {
2283dcd45ad2SRebecca Mckeever .base = alignment,
2284dcd45ad2SRebecca Mckeever .size = alignment * 2
2285dcd45ad2SRebecca Mckeever };
2286dcd45ad2SRebecca Mckeever struct region r2 = {
2287dcd45ad2SRebecca Mckeever .base = alignment * 4 + offset,
2288dcd45ad2SRebecca Mckeever .size = alignment * 2 - offset
2289dcd45ad2SRebecca Mckeever };
2290dcd45ad2SRebecca Mckeever
2291dcd45ad2SRebecca Mckeever PREFIX_PUSH();
2292dcd45ad2SRebecca Mckeever
2293dcd45ad2SRebecca Mckeever new_r2_base = r2.base + (alignment - offset);
2294dcd45ad2SRebecca Mckeever new_r2_size = r2.size - (alignment - offset);
2295dcd45ad2SRebecca Mckeever
2296dcd45ad2SRebecca Mckeever reset_memblock_regions();
2297dcd45ad2SRebecca Mckeever memblock_add(r1.base, r1.size);
2298dcd45ad2SRebecca Mckeever memblock_add(r2.base, r2.size);
2299dcd45ad2SRebecca Mckeever memblock_trim_memory(alignment);
2300dcd45ad2SRebecca Mckeever
2301dcd45ad2SRebecca Mckeever ASSERT_EQ(rgn1->base, r1.base);
2302dcd45ad2SRebecca Mckeever ASSERT_EQ(rgn1->size, r1.size);
2303dcd45ad2SRebecca Mckeever
2304dcd45ad2SRebecca Mckeever ASSERT_EQ(rgn2->base, new_r2_base);
2305dcd45ad2SRebecca Mckeever ASSERT_EQ(rgn2->size, new_r2_size);
2306dcd45ad2SRebecca Mckeever
2307dcd45ad2SRebecca Mckeever ASSERT_EQ(memblock.memory.cnt, 2);
2308dcd45ad2SRebecca Mckeever
2309dcd45ad2SRebecca Mckeever test_pass_pop();
2310dcd45ad2SRebecca Mckeever
2311dcd45ad2SRebecca Mckeever return 0;
2312dcd45ad2SRebecca Mckeever }
2313dcd45ad2SRebecca Mckeever
2314dcd45ad2SRebecca Mckeever /*
2315dcd45ad2SRebecca Mckeever * A test that tries to trim memory when there are two available regions, r1 and
2316dcd45ad2SRebecca Mckeever * r2. Region r1 is aligned on both ends and region r2 is aligned at the base
2317dcd45ad2SRebecca Mckeever * and unaligned at the end:
2318dcd45ad2SRebecca Mckeever *
2319dcd45ad2SRebecca Mckeever * Unaligned address
2320dcd45ad2SRebecca Mckeever * |
2321dcd45ad2SRebecca Mckeever * v
2322dcd45ad2SRebecca Mckeever * | +-----------------+ +---------------+ |
2323dcd45ad2SRebecca Mckeever * | | r1 | | r2 | |
2324dcd45ad2SRebecca Mckeever * +--------+-----------------+--------+---------------+---+
2325dcd45ad2SRebecca Mckeever * ^ ^ ^ ^ ^ ^
2326dcd45ad2SRebecca Mckeever * |________|________|________|________|________|
2327dcd45ad2SRebecca Mckeever * |
2328dcd45ad2SRebecca Mckeever * Aligned addresses
2329dcd45ad2SRebecca Mckeever *
2330dcd45ad2SRebecca Mckeever * Expect that r1 will not be trimmed and r2 will be trimmed at the end.
2331dcd45ad2SRebecca Mckeever * Expect the counter to not be updated.
2332dcd45ad2SRebecca Mckeever */
memblock_trim_memory_unaligned_end_check(void)2333dcd45ad2SRebecca Mckeever static int memblock_trim_memory_unaligned_end_check(void)
2334dcd45ad2SRebecca Mckeever {
2335dcd45ad2SRebecca Mckeever struct memblock_region *rgn1, *rgn2;
2336dcd45ad2SRebecca Mckeever const phys_addr_t alignment = SMP_CACHE_BYTES;
2337dcd45ad2SRebecca Mckeever phys_addr_t offset = SZ_2;
2338dcd45ad2SRebecca Mckeever phys_addr_t new_r2_size;
2339dcd45ad2SRebecca Mckeever
2340dcd45ad2SRebecca Mckeever rgn1 = &memblock.memory.regions[0];
2341dcd45ad2SRebecca Mckeever rgn2 = &memblock.memory.regions[1];
2342dcd45ad2SRebecca Mckeever
2343dcd45ad2SRebecca Mckeever struct region r1 = {
2344dcd45ad2SRebecca Mckeever .base = alignment,
2345dcd45ad2SRebecca Mckeever .size = alignment * 2
2346dcd45ad2SRebecca Mckeever };
2347dcd45ad2SRebecca Mckeever struct region r2 = {
2348dcd45ad2SRebecca Mckeever .base = alignment * 4,
2349dcd45ad2SRebecca Mckeever .size = alignment * 2 - offset
2350dcd45ad2SRebecca Mckeever };
2351dcd45ad2SRebecca Mckeever
2352dcd45ad2SRebecca Mckeever PREFIX_PUSH();
2353dcd45ad2SRebecca Mckeever
2354dcd45ad2SRebecca Mckeever new_r2_size = r2.size - (alignment - offset);
2355dcd45ad2SRebecca Mckeever
2356dcd45ad2SRebecca Mckeever reset_memblock_regions();
2357dcd45ad2SRebecca Mckeever memblock_add(r1.base, r1.size);
2358dcd45ad2SRebecca Mckeever memblock_add(r2.base, r2.size);
2359dcd45ad2SRebecca Mckeever memblock_trim_memory(alignment);
2360dcd45ad2SRebecca Mckeever
2361dcd45ad2SRebecca Mckeever ASSERT_EQ(rgn1->base, r1.base);
2362dcd45ad2SRebecca Mckeever ASSERT_EQ(rgn1->size, r1.size);
2363dcd45ad2SRebecca Mckeever
2364dcd45ad2SRebecca Mckeever ASSERT_EQ(rgn2->base, r2.base);
2365dcd45ad2SRebecca Mckeever ASSERT_EQ(rgn2->size, new_r2_size);
2366dcd45ad2SRebecca Mckeever
2367dcd45ad2SRebecca Mckeever ASSERT_EQ(memblock.memory.cnt, 2);
2368dcd45ad2SRebecca Mckeever
2369dcd45ad2SRebecca Mckeever test_pass_pop();
2370dcd45ad2SRebecca Mckeever
2371dcd45ad2SRebecca Mckeever return 0;
2372dcd45ad2SRebecca Mckeever }
2373dcd45ad2SRebecca Mckeever
memblock_trim_memory_checks(void)2374dcd45ad2SRebecca Mckeever static int memblock_trim_memory_checks(void)
2375dcd45ad2SRebecca Mckeever {
2376dcd45ad2SRebecca Mckeever prefix_reset();
2377dcd45ad2SRebecca Mckeever prefix_push(FUNC_TRIM);
2378dcd45ad2SRebecca Mckeever test_print("Running %s tests...\n", FUNC_TRIM);
2379dcd45ad2SRebecca Mckeever
2380dcd45ad2SRebecca Mckeever memblock_trim_memory_aligned_check();
2381dcd45ad2SRebecca Mckeever memblock_trim_memory_too_small_check();
2382dcd45ad2SRebecca Mckeever memblock_trim_memory_unaligned_base_check();
2383dcd45ad2SRebecca Mckeever memblock_trim_memory_unaligned_end_check();
2384dcd45ad2SRebecca Mckeever
2385dcd45ad2SRebecca Mckeever prefix_pop();
2386dcd45ad2SRebecca Mckeever
2387dcd45ad2SRebecca Mckeever return 0;
2388dcd45ad2SRebecca Mckeever }
2389dcd45ad2SRebecca Mckeever
memblock_overlaps_region_check(void)2390*1a879671SWei Yang static int memblock_overlaps_region_check(void)
2391*1a879671SWei Yang {
2392*1a879671SWei Yang struct region r = {
2393*1a879671SWei Yang .base = SZ_1G,
2394*1a879671SWei Yang .size = SZ_4M
2395*1a879671SWei Yang };
2396*1a879671SWei Yang
2397*1a879671SWei Yang PREFIX_PUSH();
2398*1a879671SWei Yang
2399*1a879671SWei Yang reset_memblock_regions();
2400*1a879671SWei Yang memblock_add(r.base, r.size);
2401*1a879671SWei Yang
2402*1a879671SWei Yang /* Far Away */
2403*1a879671SWei Yang ASSERT_FALSE(memblock_overlaps_region(&memblock.memory, SZ_1M, SZ_1M));
2404*1a879671SWei Yang ASSERT_FALSE(memblock_overlaps_region(&memblock.memory, SZ_2G, SZ_1M));
2405*1a879671SWei Yang
2406*1a879671SWei Yang /* Neighbor */
2407*1a879671SWei Yang ASSERT_FALSE(memblock_overlaps_region(&memblock.memory, SZ_1G - SZ_1M, SZ_1M));
2408*1a879671SWei Yang ASSERT_FALSE(memblock_overlaps_region(&memblock.memory, SZ_1G + SZ_4M, SZ_1M));
2409*1a879671SWei Yang
2410*1a879671SWei Yang /* Partial Overlap */
2411*1a879671SWei Yang ASSERT_TRUE(memblock_overlaps_region(&memblock.memory, SZ_1G - SZ_1M, SZ_2M));
2412*1a879671SWei Yang ASSERT_TRUE(memblock_overlaps_region(&memblock.memory, SZ_1G + SZ_2M, SZ_2M));
2413*1a879671SWei Yang
2414*1a879671SWei Yang /* Totally Overlap */
2415*1a879671SWei Yang ASSERT_TRUE(memblock_overlaps_region(&memblock.memory, SZ_1G, SZ_4M));
2416*1a879671SWei Yang ASSERT_TRUE(memblock_overlaps_region(&memblock.memory, SZ_1G - SZ_2M, SZ_8M));
2417*1a879671SWei Yang ASSERT_TRUE(memblock_overlaps_region(&memblock.memory, SZ_1G + SZ_1M, SZ_1M));
2418*1a879671SWei Yang
2419*1a879671SWei Yang test_pass_pop();
2420*1a879671SWei Yang
2421*1a879671SWei Yang return 0;
2422*1a879671SWei Yang }
2423*1a879671SWei Yang
memblock_overlaps_region_checks(void)2424*1a879671SWei Yang static int memblock_overlaps_region_checks(void)
2425*1a879671SWei Yang {
2426*1a879671SWei Yang prefix_reset();
2427*1a879671SWei Yang prefix_push("memblock_overlaps_region");
2428*1a879671SWei Yang test_print("Running memblock_overlaps_region tests...\n");
2429*1a879671SWei Yang
2430*1a879671SWei Yang memblock_overlaps_region_check();
2431*1a879671SWei Yang
2432*1a879671SWei Yang prefix_pop();
2433*1a879671SWei Yang
2434*1a879671SWei Yang return 0;
2435*1a879671SWei Yang }
2436*1a879671SWei Yang
memblock_basic_checks(void)2437f3252a22SKarolina Drobnik int memblock_basic_checks(void)
2438f3252a22SKarolina Drobnik {
2439f3252a22SKarolina Drobnik memblock_initialization_check();
24401f1180d4SKarolina Drobnik memblock_add_checks();
244183787a80SKarolina Drobnik memblock_reserve_checks();
2442b4d96893SKarolina Drobnik memblock_remove_checks();
2443dd45dc07SKarolina Drobnik memblock_free_checks();
2444a541c6d4SRebecca Mckeever memblock_bottom_up_checks();
2445dcd45ad2SRebecca Mckeever memblock_trim_memory_checks();
2446*1a879671SWei Yang memblock_overlaps_region_checks();
244783787a80SKarolina Drobnik
2448f3252a22SKarolina Drobnik return 0;
2449f3252a22SKarolina Drobnik }
2450