Like PMD and PTE level page table, also add statistics for PUD and P4D
page table.

Signed-off-by: Qi Zheng <zhengqi.a...@bytedance.com>
Suggested-by: Peter Zijlstra (Intel) <pet...@infradead.org>
Cc: linux-s...@vger.kernel.org
---
 arch/s390/include/asm/pgalloc.h | 29 +++++++++++++++++++-------
 arch/s390/include/asm/tlb.h     | 37 +++++++++++++++++----------------
 2 files changed, 40 insertions(+), 26 deletions(-)

diff --git a/arch/s390/include/asm/pgalloc.h b/arch/s390/include/asm/pgalloc.h
index 7b84ef6dc4b6d..a0c1ca5d8423c 100644
--- a/arch/s390/include/asm/pgalloc.h
+++ b/arch/s390/include/asm/pgalloc.h
@@ -53,29 +53,42 @@ static inline p4d_t *p4d_alloc_one(struct mm_struct *mm, 
unsigned long address)
 {
        unsigned long *table = crst_table_alloc(mm);
 
-       if (table)
-               crst_table_init(table, _REGION2_ENTRY_EMPTY);
+       if (!table)
+               return NULL;
+       crst_table_init(table, _REGION2_ENTRY_EMPTY);
+       pagetable_p4d_ctor(virt_to_ptdesc(table));
+
        return (p4d_t *) table;
 }
 
 static inline void p4d_free(struct mm_struct *mm, p4d_t *p4d)
 {
-       if (!mm_p4d_folded(mm))
-               crst_table_free(mm, (unsigned long *) p4d);
+       if (mm_p4d_folded(mm))
+               return;
+
+       pagetable_p4d_dtor(virt_to_ptdesc(p4d));
+       crst_table_free(mm, (unsigned long *) p4d);
 }
 
 static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long address)
 {
        unsigned long *table = crst_table_alloc(mm);
-       if (table)
-               crst_table_init(table, _REGION3_ENTRY_EMPTY);
+
+       if (!table)
+               return NULL;
+       crst_table_init(table, _REGION3_ENTRY_EMPTY);
+       pagetable_pud_ctor(virt_to_ptdesc(table));
+
        return (pud_t *) table;
 }
 
 static inline void pud_free(struct mm_struct *mm, pud_t *pud)
 {
-       if (!mm_pud_folded(mm))
-               crst_table_free(mm, (unsigned long *) pud);
+       if (mm_pud_folded(mm))
+               return;
+
+       pagetable_pud_dtor(virt_to_ptdesc(pud));
+       crst_table_free(mm, (unsigned long *) pud);
 }
 
 static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long vmaddr)
diff --git a/arch/s390/include/asm/tlb.h b/arch/s390/include/asm/tlb.h
index e95b2c8081eb8..b946964afce8e 100644
--- a/arch/s390/include/asm/tlb.h
+++ b/arch/s390/include/asm/tlb.h
@@ -110,24 +110,6 @@ static inline void pmd_free_tlb(struct mmu_gather *tlb, 
pmd_t *pmd,
        tlb_remove_ptdesc(tlb, pmd);
 }
 
-/*
- * p4d_free_tlb frees a pud table and clears the CRSTE for the
- * region second table entry from the tlb.
- * If the mm uses a four level page table the single p4d is freed
- * as the pgd. p4d_free_tlb checks the asce_limit against 8PB
- * to avoid the double free of the p4d in this case.
- */
-static inline void p4d_free_tlb(struct mmu_gather *tlb, p4d_t *p4d,
-                               unsigned long address)
-{
-       if (mm_p4d_folded(tlb->mm))
-               return;
-       __tlb_adjust_range(tlb, address, PAGE_SIZE);
-       tlb->mm->context.flush_mm = 1;
-       tlb->freed_tables = 1;
-       tlb_remove_ptdesc(tlb, p4d);
-}
-
 /*
  * pud_free_tlb frees a pud table and clears the CRSTE for the
  * region third table entry from the tlb.
@@ -140,11 +122,30 @@ static inline void pud_free_tlb(struct mmu_gather *tlb, 
pud_t *pud,
 {
        if (mm_pud_folded(tlb->mm))
                return;
+       pagetable_pud_dtor(virt_to_ptdesc(pud));
        tlb->mm->context.flush_mm = 1;
        tlb->freed_tables = 1;
        tlb->cleared_p4ds = 1;
        tlb_remove_ptdesc(tlb, pud);
 }
 
+/*
+ * p4d_free_tlb frees a p4d table and clears the CRSTE for the
+ * region second table entry from the tlb.
+ * If the mm uses a four level page table the single p4d is freed
+ * as the pgd. p4d_free_tlb checks the asce_limit against 8PB
+ * to avoid the double free of the p4d in this case.
+ */
+static inline void p4d_free_tlb(struct mmu_gather *tlb, p4d_t *p4d,
+                               unsigned long address)
+{
+       if (mm_p4d_folded(tlb->mm))
+               return;
+       pagetable_p4d_dtor(virt_to_ptdesc(p4d));
+       __tlb_adjust_range(tlb, address, PAGE_SIZE);
+       tlb->mm->context.flush_mm = 1;
+       tlb->freed_tables = 1;
+       tlb_remove_ptdesc(tlb, p4d);
+}
 
 #endif /* _S390_TLB_H */
-- 
2.20.1


Reply via email to