summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/testing/memblock/tests/basic_api.c203
1 files changed, 203 insertions, 0 deletions
diff --git a/tools/testing/memblock/tests/basic_api.c b/tools/testing/memblock/tests/basic_api.c
index 2194a141cfe6..fbb989f6ddbf 100644
--- a/tools/testing/memblock/tests/basic_api.c
+++ b/tools/testing/memblock/tests/basic_api.c
@@ -692,12 +692,215 @@ static int memblock_remove_checks(void)
return 0;
}
+/*
+ * A simple test that tries to free a memory block that was marked earlier
+ * as reserved. By "freeing" a region we mean overwriting it with the next
+ * entry in memblock.reserved. To check this is the case, the test reserves
+ * two memory regions and verifies that the value of the latter was used to
+ * erase r1 region.
+ * The test also checks if the region counter and total size were updated.
+ */
+static int memblock_free_simple_check(void)
+{
+ struct memblock_region *rgn;
+
+ rgn = &memblock.reserved.regions[0];
+
+ struct region r1 = {
+ .base = SZ_4M,
+ .size = SZ_1M
+ };
+ struct region r2 = {
+ .base = SZ_8M,
+ .size = SZ_1M
+ };
+
+ reset_memblock();
+ memblock_reserve(r1.base, r1.size);
+ memblock_reserve(r2.base, r2.size);
+ memblock_free((void *)r1.base, r1.size);
+
+ assert(rgn->base == r2.base);
+ assert(rgn->size == r2.size);
+
+ assert(memblock.reserved.cnt == 1);
+ assert(memblock.reserved.total_size == r2.size);
+
+ return 0;
+}
+
+ /*
+ * A test that tries to free a region that was not marked as reserved
+ * (i.e. has no corresponding entry in memblock.reserved). It verifies
+ * that array, regions counter and total size were not modified.
+ */
+static int memblock_free_absent_check(void)
+{
+ struct memblock_region *rgn;
+
+ rgn = &memblock.reserved.regions[0];
+
+ struct region r1 = {
+ .base = SZ_2M,
+ .size = SZ_8K
+ };
+ struct region r2 = {
+ .base = SZ_16M,
+ .size = SZ_128M
+ };
+
+ reset_memblock();
+ memblock_reserve(r1.base, r1.size);
+ memblock_free((void *)r2.base, r2.size);
+
+ assert(rgn->base == r1.base);
+ assert(rgn->size == r1.size);
+
+ assert(memblock.reserved.cnt == 1);
+ assert(memblock.reserved.total_size == r1.size);
+
+ return 0;
+}
+
+/*
+ * A test that tries to free a region which overlaps with the beginning of
+ * the already existing entry r1 (that is r1.base < r2.base + r2.size). It
+ * checks if only the intersection of both regions is freed. The test also
+ * checks if the regions counter and total size are updated to expected
+ * values.
+ */
+static int memblock_free_overlap_top_check(void)
+{
+ struct memblock_region *rgn;
+ phys_addr_t total_size;
+
+ rgn = &memblock.reserved.regions[0];
+
+ struct region r1 = {
+ .base = SZ_8M,
+ .size = SZ_32M
+ };
+ struct region r2 = {
+ .base = SZ_1M,
+ .size = SZ_8M
+ };
+
+ total_size = (r1.size + r1.base) - (r2.base + r2.size);
+
+ reset_memblock();
+ memblock_reserve(r1.base, r1.size);
+ memblock_free((void *)r2.base, r2.size);
+
+ assert(rgn->base == r2.base + r2.size);
+ assert(rgn->size == total_size);
+
+ assert(memblock.reserved.cnt == 1);
+ assert(memblock.reserved.total_size == total_size);
+
+ return 0;
+}
+
+/*
+ * A test that tries to free a region which overlaps with the end of the
+ * first entry (that is r2.base < r1.base + r1.size). It checks if only the
+ * intersection of both regions is freed. The test also checks if the
+ * regions counter and total size are updated to expected values.
+ */
+static int memblock_free_overlap_bottom_check(void)
+{
+ struct memblock_region *rgn;
+ phys_addr_t total_size;
+
+ rgn = &memblock.reserved.regions[0];
+
+ struct region r1 = {
+ .base = SZ_8M,
+ .size = SZ_32M
+ };
+ struct region r2 = {
+ .base = SZ_32M,
+ .size = SZ_32M
+ };
+
+ total_size = r2.base - r1.base;
+
+ reset_memblock();
+ memblock_reserve(r1.base, r1.size);
+ memblock_free((void *)r2.base, r2.size);
+
+ assert(rgn->base == r1.base);
+ assert(rgn->size == total_size);
+
+ assert(memblock.reserved.cnt == 1);
+ assert(memblock.reserved.total_size == total_size);
+
+ return 0;
+}
+
+/*
+ * A test that tries to free a region which is within the range of the
+ * already existing entry (that is
+ * (r1.base < r2.base) && (r2.base + r2.size < r1.base + r1.size)).
+ * It checks if the region is split into two - one that ends at r2.base and
+ * second that starts at r2.base + size, with appropriate sizes. It is
+ * expected that the region counter and total size fields were updated t
+ * reflect that change.
+ */
+static int memblock_free_within_check(void)
+{
+ struct memblock_region *rgn1, *rgn2;
+ phys_addr_t r1_size, r2_size, total_size;
+
+ rgn1 = &memblock.reserved.regions[0];
+ rgn2 = &memblock.reserved.regions[1];
+
+ struct region r1 = {
+ .base = SZ_1M,
+ .size = SZ_8M
+ };
+ struct region r2 = {
+ .base = SZ_4M,
+ .size = SZ_1M
+ };
+
+ r1_size = r2.base - r1.base;
+ r2_size = (r1.base + r1.size) - (r2.base + r2.size);
+ total_size = r1_size + r2_size;
+
+ reset_memblock();
+ memblock_reserve(r1.base, r1.size);
+ memblock_free((void *)r2.base, r2.size);
+
+ assert(rgn1->base == r1.base);
+ assert(rgn1->size == r1_size);
+
+ assert(rgn2->base == r2.base + r2.size);
+ assert(rgn2->size == r2_size);
+
+ assert(memblock.reserved.cnt == 2);
+ assert(memblock.reserved.total_size == total_size);
+
+ return 0;
+}
+
+static int memblock_free_checks(void)
+{
+ memblock_free_simple_check();
+ memblock_free_absent_check();
+ memblock_free_overlap_top_check();
+ memblock_free_overlap_bottom_check();
+ memblock_free_within_check();
+
+ return 0;
+}
+
int memblock_basic_checks(void)
{
memblock_initialization_check();
memblock_add_checks();
memblock_reserve_checks();
memblock_remove_checks();
+ memblock_free_checks();
return 0;
}