@@ -692,12 +692,215 @@ static int memblock_remove_checks(void)
692
692
return 0 ;
693
693
}
694
694
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
+
695
897
int memblock_basic_checks (void )
696
898
{
697
899
memblock_initialization_check ();
698
900
memblock_add_checks ();
699
901
memblock_reserve_checks ();
700
902
memblock_remove_checks ();
903
+ memblock_free_checks ();
701
904
702
905
return 0 ;
703
906
}
0 commit comments