powerpc compound vmemmap population still finds a reusable tail page by
walking the vmemmap page tables.

Switch it to the common vmemmap_shared_tail_page() helper instead, so it
can use the shared tail page directly without probing or populating
neighboring mappings.

This removes the powerpc-specific tail-page lookup and its fallback path
and aligns the radix vmemmap optimization path with the generic shared
tail-page scheme.

Signed-off-by: Muchun Song <[email protected]>
---
 arch/powerpc/mm/book3s64/radix_pgtable.c | 76 ++----------------------
 1 file changed, 6 insertions(+), 70 deletions(-)

diff --git a/arch/powerpc/mm/book3s64/radix_pgtable.c 
b/arch/powerpc/mm/book3s64/radix_pgtable.c
index cf692b2b5f7b..95e65ac8cdea 100644
--- a/arch/powerpc/mm/book3s64/radix_pgtable.c
+++ b/arch/powerpc/mm/book3s64/radix_pgtable.c
@@ -1250,59 +1250,6 @@ static pte_t * __meminit 
radix__vmemmap_populate_address(unsigned long addr, int
        return pte;
 }
 
-static pte_t * __meminit vmemmap_compound_tail_page(unsigned long addr,
-                                                   unsigned long pfn_offset, 
int node)
-{
-       pgd_t *pgd;
-       p4d_t *p4d;
-       pud_t *pud;
-       pmd_t *pmd;
-       pte_t *pte;
-       unsigned long map_addr;
-
-       /* the second vmemmap page which we use for duplication */
-       map_addr = addr - pfn_offset * sizeof(struct page) + PAGE_SIZE;
-       pgd = pgd_offset_k(map_addr);
-       p4d = p4d_offset(pgd, map_addr);
-       pud = vmemmap_pud_alloc(p4d, node, map_addr);
-       if (!pud)
-               return NULL;
-       pmd = vmemmap_pmd_alloc(pud, node, map_addr);
-       if (!pmd)
-               return NULL;
-       if (pmd_leaf(*pmd))
-               /*
-                * The second page is mapped as a hugepage due to a nearby 
request.
-                * Force our mapping to page size without deduplication
-                */
-               return NULL;
-       pte = vmemmap_pte_alloc(pmd, node, map_addr);
-       if (!pte)
-               return NULL;
-       /*
-        * Check if there exist a mapping to the left
-        */
-       if (pte_none(*pte)) {
-               /*
-                * Populate the head page vmemmap page.
-                * It can fall in different pmd, hence
-                * vmemmap_populate_address()
-                */
-               pte = radix__vmemmap_populate_address(map_addr - PAGE_SIZE, 
node, NULL, NULL);
-               if (!pte)
-                       return NULL;
-               /*
-                * Populate the tail pages vmemmap page
-                */
-               pte = radix__vmemmap_pte_populate(pmd, map_addr, node, NULL, 
NULL);
-               if (!pte)
-                       return NULL;
-               vmemmap_verify(pte, node, map_addr, map_addr + PAGE_SIZE);
-               return pte;
-       }
-       return pte;
-}
-
 int __meminit vmemmap_populate_compound_pages(unsigned long start_pfn,
                                              unsigned long start,
                                              unsigned long end, int node,
@@ -1320,6 +1267,11 @@ int __meminit vmemmap_populate_compound_pages(unsigned 
long start_pfn,
        pud_t *pud;
        pmd_t *pmd;
        pte_t *pte;
+       struct page *tail_page;
+
+       tail_page = vmemmap_shared_tail_page(pgmap->vmemmap_shift, 
device_zone(node));
+       if (!tail_page)
+               return -ENOMEM;
 
        for (addr = start; addr < end; addr = next) {
 
@@ -1352,7 +1304,6 @@ int __meminit vmemmap_populate_compound_pages(unsigned 
long start_pfn,
                        unsigned long nr_pages = pgmap_vmemmap_nr(pgmap);
                        unsigned long addr_pfn = page_to_pfn((struct page 
*)addr);
                        unsigned long pfn_offset = addr_pfn - 
ALIGN_DOWN(addr_pfn, nr_pages);
-                       pte_t *tail_page_pte;
 
                        /*
                         * if the address is aligned to huge page size it is the
@@ -1377,23 +1328,8 @@ int __meminit vmemmap_populate_compound_pages(unsigned 
long start_pfn,
                                next = addr + 2 * PAGE_SIZE;
                                continue;
                        }
-                       /*
-                        * get the 2nd mapping details
-                        * Also create it if that doesn't exist
-                        */
-                       tail_page_pte = vmemmap_compound_tail_page(addr, 
pfn_offset, node);
-                       if (!tail_page_pte) {
-
-                               pte = radix__vmemmap_pte_populate(pmd, addr, 
node, NULL, NULL);
-                               if (!pte)
-                                       return -ENOMEM;
-                               vmemmap_verify(pte, node, addr, addr + 
PAGE_SIZE);
-
-                               next = addr + PAGE_SIZE;
-                               continue;
-                       }
 
-                       pte = radix__vmemmap_pte_populate(pmd, addr, node, 
NULL, pte_page(*tail_page_pte));
+                       pte = radix__vmemmap_pte_populate(pmd, addr, node, 
NULL, tail_page);
                        if (!pte)
                                return -ENOMEM;
                        vmemmap_verify(pte, node, addr, addr + PAGE_SIZE);
-- 
2.54.0


Reply via email to