Skip to content

Commit eee0793

Browse files
Anshuman Khandualtorvalds
authored andcommitted
arm64/mm: enable vmem_altmap support for vmemmap mappings
Device memory ranges when getting hot added into ZONE_DEVICE, might require their vmemmap mapping's backing memory to be allocated from their own range instead of consuming system memory. This prevents large system memory usage for potentially large device memory ranges. Device driver communicates this request via vmem_altmap structure. Architecture needs to take this request into account while creating and tearing down vemmmap mappings. This enables vmem_altmap support in vmemmap_populate() and vmemmap_free() which includes vmemmap_populate_basepages() used for ARM64_16K_PAGES and ARM64_64K_PAGES configs. Signed-off-by: Anshuman Khandual <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Tested-by: Jia He <[email protected]> Reviewed-by: Catalin Marinas <[email protected]> Cc: Will Deacon <[email protected]> Cc: Mark Rutland <[email protected]> Cc: Steve Capper <[email protected]> Cc: David Hildenbrand <[email protected]> Cc: Yu Zhao <[email protected]> Cc: Hsin-Yi Wang <[email protected]> Cc: Thomas Gleixner <[email protected]> Cc: Andy Lutomirski <[email protected]> Cc: Benjamin Herrenschmidt <[email protected]> Cc: Borislav Petkov <[email protected]> Cc: Dan Williams <[email protected]> Cc: Dave Hansen <[email protected]> Cc: Fenghua Yu <[email protected]> Cc: "H. Peter Anvin" <[email protected]> Cc: Ingo Molnar <[email protected]> Cc: Jonathan Corbet <[email protected]> Cc: "Kirill A. Shutemov" <[email protected]> Cc: "Matthew Wilcox (Oracle)" <[email protected]> Cc: Michael Ellerman <[email protected]> Cc: Michal Hocko <[email protected]> Cc: Mike Rapoport <[email protected]> Cc: Palmer Dabbelt <[email protected]> Cc: Paul Mackerras <[email protected]> Cc: Paul Walmsley <[email protected]> Cc: Pavel Tatashin <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Robin Murphy <[email protected]> Cc: Tony Luck <[email protected]> Link: http://lkml.kernel.org/r/[email protected] Signed-off-by: Linus Torvalds <[email protected]>
1 parent 56993b4 commit eee0793

File tree

1 file changed

+38
-20
lines changed

1 file changed

+38
-20
lines changed

arch/arm64/mm/mmu.c

Lines changed: 38 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -761,15 +761,20 @@ int kern_addr_valid(unsigned long addr)
761761
}
762762

763763
#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)
765766
{
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+
}
768773
}
769774

770775
static void free_hotplug_pgtable_page(struct page *page)
771776
{
772-
free_hotplug_page_range(page, PAGE_SIZE);
777+
free_hotplug_page_range(page, PAGE_SIZE, NULL);
773778
}
774779

775780
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,
792797
}
793798

794799
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)
796802
{
797803
pte_t *ptep, pte;
798804

@@ -806,12 +812,14 @@ static void unmap_hotplug_pte_range(pmd_t *pmdp, unsigned long addr,
806812
pte_clear(&init_mm, addr, ptep);
807813
flush_tlb_kernel_range(addr, addr + PAGE_SIZE);
808814
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);
810817
} while (addr += PAGE_SIZE, addr < end);
811818
}
812819

813820
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)
815823
{
816824
unsigned long next;
817825
pmd_t *pmdp, pmd;
@@ -834,16 +842,17 @@ static void unmap_hotplug_pmd_range(pud_t *pudp, unsigned long addr,
834842
flush_tlb_kernel_range(addr, addr + PAGE_SIZE);
835843
if (free_mapped)
836844
free_hotplug_page_range(pmd_page(pmd),
837-
PMD_SIZE);
845+
PMD_SIZE, altmap);
838846
continue;
839847
}
840848
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);
842850
} while (addr = next, addr < end);
843851
}
844852

845853
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)
847856
{
848857
unsigned long next;
849858
pud_t *pudp, pud;
@@ -866,16 +875,17 @@ static void unmap_hotplug_pud_range(p4d_t *p4dp, unsigned long addr,
866875
flush_tlb_kernel_range(addr, addr + PAGE_SIZE);
867876
if (free_mapped)
868877
free_hotplug_page_range(pud_page(pud),
869-
PUD_SIZE);
878+
PUD_SIZE, altmap);
870879
continue;
871880
}
872881
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);
874883
} while (addr = next, addr < end);
875884
}
876885

877886
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)
879889
{
880890
unsigned long next;
881891
p4d_t *p4dp, p4d;
@@ -888,16 +898,24 @@ static void unmap_hotplug_p4d_range(pgd_t *pgdp, unsigned long addr,
888898
continue;
889899

890900
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);
892902
} while (addr = next, addr < end);
893903
}
894904

895905
static void unmap_hotplug_range(unsigned long addr, unsigned long end,
896-
bool free_mapped)
906+
bool free_mapped, struct vmem_altmap *altmap)
897907
{
898908
unsigned long next;
899909
pgd_t *pgdp, pgd;
900910

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+
901919
do {
902920
next = pgd_addr_end(addr, end);
903921
pgdp = pgd_offset_k(addr);
@@ -906,7 +924,7 @@ static void unmap_hotplug_range(unsigned long addr, unsigned long end,
906924
continue;
907925

908926
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);
910928
} while (addr = next, addr < end);
911929
}
912930

@@ -1070,7 +1088,7 @@ static void free_empty_tables(unsigned long addr, unsigned long end,
10701088
int __meminit vmemmap_populate(unsigned long start, unsigned long end, int node,
10711089
struct vmem_altmap *altmap)
10721090
{
1073-
return vmemmap_populate_basepages(start, end, node, NULL);
1091+
return vmemmap_populate_basepages(start, end, node, altmap);
10741092
}
10751093
#else /* !ARM64_SWAPPER_USES_SECTION_MAPS */
10761094
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,
11021120
if (pmd_none(READ_ONCE(*pmdp))) {
11031121
void *p = NULL;
11041122

1105-
p = vmemmap_alloc_block_buf(PMD_SIZE, node, NULL);
1123+
p = vmemmap_alloc_block_buf(PMD_SIZE, node, altmap);
11061124
if (!p)
11071125
return -ENOMEM;
11081126

@@ -1120,7 +1138,7 @@ void vmemmap_free(unsigned long start, unsigned long end,
11201138
#ifdef CONFIG_MEMORY_HOTPLUG
11211139
WARN_ON((start < VMEMMAP_START) || (end > VMEMMAP_END));
11221140

1123-
unmap_hotplug_range(start, end, true);
1141+
unmap_hotplug_range(start, end, true, altmap);
11241142
free_empty_tables(start, end, VMEMMAP_START, VMEMMAP_END);
11251143
#endif
11261144
}
@@ -1411,7 +1429,7 @@ static void __remove_pgd_mapping(pgd_t *pgdir, unsigned long start, u64 size)
14111429
WARN_ON(pgdir != init_mm.pgd);
14121430
WARN_ON((start < PAGE_OFFSET) || (end > PAGE_END));
14131431

1414-
unmap_hotplug_range(start, end, false);
1432+
unmap_hotplug_range(start, end, false, NULL);
14151433
free_empty_tables(start, end, PAGE_OFFSET, PAGE_END);
14161434
}
14171435

0 commit comments

Comments
 (0)