@@ -761,15 +761,20 @@ int kern_addr_valid(unsigned long addr)
761
761
}
762
762
763
763
#ifdef CONFIG_MEMORY_HOTPLUG
764
- static void free_hotplug_page_range (struct page * page , size_t size )
764
+ static void free_hotplug_page_range (struct page * page , size_t size ,
765
+ struct vmem_altmap * altmap )
765
766
{
766
- WARN_ON (PageReserved (page ));
767
- free_pages ((unsigned long )page_address (page ), get_order (size ));
767
+ if (altmap ) {
768
+ vmem_altmap_free (altmap , size >> PAGE_SHIFT );
769
+ } else {
770
+ WARN_ON (PageReserved (page ));
771
+ free_pages ((unsigned long )page_address (page ), get_order (size ));
772
+ }
768
773
}
769
774
770
775
static void free_hotplug_pgtable_page (struct page * page )
771
776
{
772
- free_hotplug_page_range (page , PAGE_SIZE );
777
+ free_hotplug_page_range (page , PAGE_SIZE , NULL );
773
778
}
774
779
775
780
static bool pgtable_range_aligned (unsigned long start , unsigned long end ,
@@ -792,7 +797,8 @@ static bool pgtable_range_aligned(unsigned long start, unsigned long end,
792
797
}
793
798
794
799
static void unmap_hotplug_pte_range (pmd_t * pmdp , unsigned long addr ,
795
- unsigned long end , bool free_mapped )
800
+ unsigned long end , bool free_mapped ,
801
+ struct vmem_altmap * altmap )
796
802
{
797
803
pte_t * ptep , pte ;
798
804
@@ -806,12 +812,14 @@ static void unmap_hotplug_pte_range(pmd_t *pmdp, unsigned long addr,
806
812
pte_clear (& init_mm , addr , ptep );
807
813
flush_tlb_kernel_range (addr , addr + PAGE_SIZE );
808
814
if (free_mapped )
809
- free_hotplug_page_range (pte_page (pte ), PAGE_SIZE );
815
+ free_hotplug_page_range (pte_page (pte ),
816
+ PAGE_SIZE , altmap );
810
817
} while (addr += PAGE_SIZE , addr < end );
811
818
}
812
819
813
820
static void unmap_hotplug_pmd_range (pud_t * pudp , unsigned long addr ,
814
- unsigned long end , bool free_mapped )
821
+ unsigned long end , bool free_mapped ,
822
+ struct vmem_altmap * altmap )
815
823
{
816
824
unsigned long next ;
817
825
pmd_t * pmdp , pmd ;
@@ -834,16 +842,17 @@ static void unmap_hotplug_pmd_range(pud_t *pudp, unsigned long addr,
834
842
flush_tlb_kernel_range (addr , addr + PAGE_SIZE );
835
843
if (free_mapped )
836
844
free_hotplug_page_range (pmd_page (pmd ),
837
- PMD_SIZE );
845
+ PMD_SIZE , altmap );
838
846
continue ;
839
847
}
840
848
WARN_ON (!pmd_table (pmd ));
841
- unmap_hotplug_pte_range (pmdp , addr , next , free_mapped );
849
+ unmap_hotplug_pte_range (pmdp , addr , next , free_mapped , altmap );
842
850
} while (addr = next , addr < end );
843
851
}
844
852
845
853
static void unmap_hotplug_pud_range (p4d_t * p4dp , unsigned long addr ,
846
- unsigned long end , bool free_mapped )
854
+ unsigned long end , bool free_mapped ,
855
+ struct vmem_altmap * altmap )
847
856
{
848
857
unsigned long next ;
849
858
pud_t * pudp , pud ;
@@ -866,16 +875,17 @@ static void unmap_hotplug_pud_range(p4d_t *p4dp, unsigned long addr,
866
875
flush_tlb_kernel_range (addr , addr + PAGE_SIZE );
867
876
if (free_mapped )
868
877
free_hotplug_page_range (pud_page (pud ),
869
- PUD_SIZE );
878
+ PUD_SIZE , altmap );
870
879
continue ;
871
880
}
872
881
WARN_ON (!pud_table (pud ));
873
- unmap_hotplug_pmd_range (pudp , addr , next , free_mapped );
882
+ unmap_hotplug_pmd_range (pudp , addr , next , free_mapped , altmap );
874
883
} while (addr = next , addr < end );
875
884
}
876
885
877
886
static void unmap_hotplug_p4d_range (pgd_t * pgdp , unsigned long addr ,
878
- unsigned long end , bool free_mapped )
887
+ unsigned long end , bool free_mapped ,
888
+ struct vmem_altmap * altmap )
879
889
{
880
890
unsigned long next ;
881
891
p4d_t * p4dp , p4d ;
@@ -888,16 +898,24 @@ static void unmap_hotplug_p4d_range(pgd_t *pgdp, unsigned long addr,
888
898
continue ;
889
899
890
900
WARN_ON (!p4d_present (p4d ));
891
- unmap_hotplug_pud_range (p4dp , addr , next , free_mapped );
901
+ unmap_hotplug_pud_range (p4dp , addr , next , free_mapped , altmap );
892
902
} while (addr = next , addr < end );
893
903
}
894
904
895
905
static void unmap_hotplug_range (unsigned long addr , unsigned long end ,
896
- bool free_mapped )
906
+ bool free_mapped , struct vmem_altmap * altmap )
897
907
{
898
908
unsigned long next ;
899
909
pgd_t * pgdp , pgd ;
900
910
911
+ /*
912
+ * altmap can only be used as vmemmap mapping backing memory.
913
+ * In case the backing memory itself is not being freed, then
914
+ * altmap is irrelevant. Warn about this inconsistency when
915
+ * encountered.
916
+ */
917
+ WARN_ON (!free_mapped && altmap );
918
+
901
919
do {
902
920
next = pgd_addr_end (addr , end );
903
921
pgdp = pgd_offset_k (addr );
@@ -906,7 +924,7 @@ static void unmap_hotplug_range(unsigned long addr, unsigned long end,
906
924
continue ;
907
925
908
926
WARN_ON (!pgd_present (pgd ));
909
- unmap_hotplug_p4d_range (pgdp , addr , next , free_mapped );
927
+ unmap_hotplug_p4d_range (pgdp , addr , next , free_mapped , altmap );
910
928
} while (addr = next , addr < end );
911
929
}
912
930
@@ -1070,7 +1088,7 @@ static void free_empty_tables(unsigned long addr, unsigned long end,
1070
1088
int __meminit vmemmap_populate (unsigned long start , unsigned long end , int node ,
1071
1089
struct vmem_altmap * altmap )
1072
1090
{
1073
- return vmemmap_populate_basepages (start , end , node , NULL );
1091
+ return vmemmap_populate_basepages (start , end , node , altmap );
1074
1092
}
1075
1093
#else /* !ARM64_SWAPPER_USES_SECTION_MAPS */
1076
1094
int __meminit vmemmap_populate (unsigned long start , unsigned long end , int node ,
@@ -1102,7 +1120,7 @@ int __meminit vmemmap_populate(unsigned long start, unsigned long end, int node,
1102
1120
if (pmd_none (READ_ONCE (* pmdp ))) {
1103
1121
void * p = NULL ;
1104
1122
1105
- p = vmemmap_alloc_block_buf (PMD_SIZE , node , NULL );
1123
+ p = vmemmap_alloc_block_buf (PMD_SIZE , node , altmap );
1106
1124
if (!p )
1107
1125
return - ENOMEM ;
1108
1126
@@ -1120,7 +1138,7 @@ void vmemmap_free(unsigned long start, unsigned long end,
1120
1138
#ifdef CONFIG_MEMORY_HOTPLUG
1121
1139
WARN_ON ((start < VMEMMAP_START ) || (end > VMEMMAP_END ));
1122
1140
1123
- unmap_hotplug_range (start , end , true);
1141
+ unmap_hotplug_range (start , end , true, altmap );
1124
1142
free_empty_tables (start , end , VMEMMAP_START , VMEMMAP_END );
1125
1143
#endif
1126
1144
}
@@ -1411,7 +1429,7 @@ static void __remove_pgd_mapping(pgd_t *pgdir, unsigned long start, u64 size)
1411
1429
WARN_ON (pgdir != init_mm .pgd );
1412
1430
WARN_ON ((start < PAGE_OFFSET ) || (end > PAGE_END ));
1413
1431
1414
- unmap_hotplug_range (start , end , false);
1432
+ unmap_hotplug_range (start , end , false, NULL );
1415
1433
free_empty_tables (start , end , PAGE_OFFSET , PAGE_END );
1416
1434
}
1417
1435
0 commit comments