Skip to content

Commit dd45dc0

Browse files
drobnikrppt
authored andcommitted
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 <[email protected]> Signed-off-by: Mike Rapoport <[email protected]> Link: https://lore.kernel.org/r/30af95c82754ad8029404c3b528a5ef1c05d1ed6.1643796665.git.karolinadrobnik@gmail.com
1 parent e393c09 commit dd45dc0

File tree

1 file changed

+203
-0
lines changed

1 file changed

+203
-0
lines changed

tools/testing/memblock/tests/basic_api.c

Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -692,12 +692,215 @@ static int memblock_remove_checks(void)
692692
return 0;
693693
}
694694

695+
/*
696+
* A simple test that tries to free a memory block that was marked earlier
697+
* as reserved. By "freeing" a region we mean overwriting it with the next
698+
* entry in memblock.reserved. To check this is the case, the test reserves
699+
* two memory regions and verifies that the value of the latter was used to
700+
* erase r1 region.
701+
* The test also checks if the region counter and total size were updated.
702+
*/
703+
static int memblock_free_simple_check(void)
704+
{
705+
struct memblock_region *rgn;
706+
707+
rgn = &memblock.reserved.regions[0];
708+
709+
struct region r1 = {
710+
.base = SZ_4M,
711+
.size = SZ_1M
712+
};
713+
struct region r2 = {
714+
.base = SZ_8M,
715+
.size = SZ_1M
716+
};
717+
718+
reset_memblock();
719+
memblock_reserve(r1.base, r1.size);
720+
memblock_reserve(r2.base, r2.size);
721+
memblock_free((void *)r1.base, r1.size);
722+
723+
assert(rgn->base == r2.base);
724+
assert(rgn->size == r2.size);
725+
726+
assert(memblock.reserved.cnt == 1);
727+
assert(memblock.reserved.total_size == r2.size);
728+
729+
return 0;
730+
}
731+
732+
/*
733+
* A test that tries to free a region that was not marked as reserved
734+
* (i.e. has no corresponding entry in memblock.reserved). It verifies
735+
* that array, regions counter and total size were not modified.
736+
*/
737+
static int memblock_free_absent_check(void)
738+
{
739+
struct memblock_region *rgn;
740+
741+
rgn = &memblock.reserved.regions[0];
742+
743+
struct region r1 = {
744+
.base = SZ_2M,
745+
.size = SZ_8K
746+
};
747+
struct region r2 = {
748+
.base = SZ_16M,
749+
.size = SZ_128M
750+
};
751+
752+
reset_memblock();
753+
memblock_reserve(r1.base, r1.size);
754+
memblock_free((void *)r2.base, r2.size);
755+
756+
assert(rgn->base == r1.base);
757+
assert(rgn->size == r1.size);
758+
759+
assert(memblock.reserved.cnt == 1);
760+
assert(memblock.reserved.total_size == r1.size);
761+
762+
return 0;
763+
}
764+
765+
/*
766+
* A test that tries to free a region which overlaps with the beginning of
767+
* the already existing entry r1 (that is r1.base < r2.base + r2.size). It
768+
* checks if only the intersection of both regions is freed. The test also
769+
* checks if the regions counter and total size are updated to expected
770+
* values.
771+
*/
772+
static int memblock_free_overlap_top_check(void)
773+
{
774+
struct memblock_region *rgn;
775+
phys_addr_t total_size;
776+
777+
rgn = &memblock.reserved.regions[0];
778+
779+
struct region r1 = {
780+
.base = SZ_8M,
781+
.size = SZ_32M
782+
};
783+
struct region r2 = {
784+
.base = SZ_1M,
785+
.size = SZ_8M
786+
};
787+
788+
total_size = (r1.size + r1.base) - (r2.base + r2.size);
789+
790+
reset_memblock();
791+
memblock_reserve(r1.base, r1.size);
792+
memblock_free((void *)r2.base, r2.size);
793+
794+
assert(rgn->base == r2.base + r2.size);
795+
assert(rgn->size == total_size);
796+
797+
assert(memblock.reserved.cnt == 1);
798+
assert(memblock.reserved.total_size == total_size);
799+
800+
return 0;
801+
}
802+
803+
/*
804+
* A test that tries to free a region which overlaps with the end of the
805+
* first entry (that is r2.base < r1.base + r1.size). It checks if only the
806+
* intersection of both regions is freed. The test also checks if the
807+
* regions counter and total size are updated to expected values.
808+
*/
809+
static int memblock_free_overlap_bottom_check(void)
810+
{
811+
struct memblock_region *rgn;
812+
phys_addr_t total_size;
813+
814+
rgn = &memblock.reserved.regions[0];
815+
816+
struct region r1 = {
817+
.base = SZ_8M,
818+
.size = SZ_32M
819+
};
820+
struct region r2 = {
821+
.base = SZ_32M,
822+
.size = SZ_32M
823+
};
824+
825+
total_size = r2.base - r1.base;
826+
827+
reset_memblock();
828+
memblock_reserve(r1.base, r1.size);
829+
memblock_free((void *)r2.base, r2.size);
830+
831+
assert(rgn->base == r1.base);
832+
assert(rgn->size == total_size);
833+
834+
assert(memblock.reserved.cnt == 1);
835+
assert(memblock.reserved.total_size == total_size);
836+
837+
return 0;
838+
}
839+
840+
/*
841+
* A test that tries to free a region which is within the range of the
842+
* already existing entry (that is
843+
* (r1.base < r2.base) && (r2.base + r2.size < r1.base + r1.size)).
844+
* It checks if the region is split into two - one that ends at r2.base and
845+
* second that starts at r2.base + size, with appropriate sizes. It is
846+
* expected that the region counter and total size fields were updated t
847+
* reflect that change.
848+
*/
849+
static int memblock_free_within_check(void)
850+
{
851+
struct memblock_region *rgn1, *rgn2;
852+
phys_addr_t r1_size, r2_size, total_size;
853+
854+
rgn1 = &memblock.reserved.regions[0];
855+
rgn2 = &memblock.reserved.regions[1];
856+
857+
struct region r1 = {
858+
.base = SZ_1M,
859+
.size = SZ_8M
860+
};
861+
struct region r2 = {
862+
.base = SZ_4M,
863+
.size = SZ_1M
864+
};
865+
866+
r1_size = r2.base - r1.base;
867+
r2_size = (r1.base + r1.size) - (r2.base + r2.size);
868+
total_size = r1_size + r2_size;
869+
870+
reset_memblock();
871+
memblock_reserve(r1.base, r1.size);
872+
memblock_free((void *)r2.base, r2.size);
873+
874+
assert(rgn1->base == r1.base);
875+
assert(rgn1->size == r1_size);
876+
877+
assert(rgn2->base == r2.base + r2.size);
878+
assert(rgn2->size == r2_size);
879+
880+
assert(memblock.reserved.cnt == 2);
881+
assert(memblock.reserved.total_size == total_size);
882+
883+
return 0;
884+
}
885+
886+
static int memblock_free_checks(void)
887+
{
888+
memblock_free_simple_check();
889+
memblock_free_absent_check();
890+
memblock_free_overlap_top_check();
891+
memblock_free_overlap_bottom_check();
892+
memblock_free_within_check();
893+
894+
return 0;
895+
}
896+
695897
int memblock_basic_checks(void)
696898
{
697899
memblock_initialization_check();
698900
memblock_add_checks();
699901
memblock_reserve_checks();
700902
memblock_remove_checks();
903+
memblock_free_checks();
701904

702905
return 0;
703906
}

0 commit comments

Comments
 (0)