diff options
author | Karolina Drobnik <karolinadrobnik@gmail.com> | 2022-02-02 12:03:15 +0100 |
---|---|---|
committer | Mike Rapoport <rppt@linux.ibm.com> | 2022-02-21 08:26:06 +0200 |
commit | dd45dc071101a45619cbaff0f77d07abdf25caf0 (patch) | |
tree | 91eb48715091d5c6b5ec0f2dd5a7510b2fa288e7 /tools/testing/memblock | |
parent | memblock tests: Add memblock_add_node test (diff) | |
download | wireguard-linux-dd45dc071101a45619cbaff0f77d07abdf25caf0.tar.xz wireguard-linux-dd45dc071101a45619cbaff0f77d07abdf25caf0.zip |
memblock tests: Add memblock_free tests
Add checks for removing a region from reserved memory in different
scenarios:
- The requested region matches one in the collection of reserved
memory regions
- The requested region does not exist in memblock.reserved
- The region overlaps with one of the entries: from the top (its
end address is bigger than the base of the existing region) or
from the bottom (its base address is smaller than the end address
of one of the regions)
- The region is within an already defined region
Signed-off-by: Karolina Drobnik <karolinadrobnik@gmail.com>
Signed-off-by: Mike Rapoport <rppt@kernel.org>
Link: https://lore.kernel.org/r/30af95c82754ad8029404c3b528a5ef1c05d1ed6.1643796665.git.karolinadrobnik@gmail.com
Diffstat (limited to 'tools/testing/memblock')
-rw-r--r-- | tools/testing/memblock/tests/basic_api.c | 203 |
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; } |