powerpc/mm: Add missing pmd accessors
authorAneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Wed, 5 Nov 2014 16:27:39 +0000 (21:57 +0530)
committerMichael Ellerman <mpe@ellerman.id.au>
Fri, 14 Nov 2014 06:24:21 +0000 (17:24 +1100)
This patch add documentation and missing accessors.

Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
arch/powerpc/include/asm/pgtable-ppc64-4k.h
arch/powerpc/include/asm/pgtable-ppc64-64k.h
arch/powerpc/include/asm/pgtable-ppc64.h
arch/powerpc/mm/hugetlbpage.c
arch/powerpc/mm/pgtable_64.c

index 7b935683f2684687813f470765091bcec064b219..132ee1d482c255696a12b57e9541a57e9b1de19b 100644 (file)
 #define pgd_present(pgd)       (pgd_val(pgd) != 0)
 #define pgd_clear(pgdp)                (pgd_val(*(pgdp)) = 0)
 #define pgd_page_vaddr(pgd)    (pgd_val(pgd) & ~PGD_MASKED_BITS)
-#define pgd_page(pgd)          virt_to_page(pgd_page_vaddr(pgd))
+
+#ifndef __ASSEMBLY__
+
+static inline pte_t pgd_pte(pgd_t pgd)
+{
+       return __pte(pgd_val(pgd));
+}
+
+static inline pgd_t pte_pgd(pte_t pte)
+{
+       return __pgd(pte_val(pte));
+}
+extern struct page *pgd_page(pgd_t pgd);
+
+#endif /* !__ASSEMBLY__ */
 
 #define pud_offset(pgdp, addr) \
   (((pud_t *) pgd_page_vaddr(*(pgdp))) + \
index a56b82fb0609b86102606c1232c42c2791595992..1de35bbd02a64048d03aef0f3bdb08b51d6d8c0a 100644 (file)
@@ -38,4 +38,7 @@
 /* Bits to mask out from a PGD/PUD to get to the PMD page */
 #define PUD_MASKED_BITS                0x1ff
 
+#define pgd_pte(pgd)   (pud_pte(((pud_t){ pgd })))
+#define pte_pgd(pte)   ((pgd_t)pte_pud(pte))
+
 #endif /* _ASM_POWERPC_PGTABLE_PPC64_64K_H */
index ae153c40ab7c7e9a552731e3b5673c1cd0efdd75..d12092420560dd2ed982411e2ee08a3782ce51c5 100644 (file)
 #define pmd_none(pmd)          (!pmd_val(pmd))
 #define        pmd_bad(pmd)            (!is_kernel_addr(pmd_val(pmd)) \
                                 || (pmd_val(pmd) & PMD_BAD_BITS))
-#define        pmd_present(pmd)        (pmd_val(pmd) != 0)
+#define        pmd_present(pmd)        (!pmd_none(pmd))
 #define        pmd_clear(pmdp)         (pmd_val(*(pmdp)) = 0)
 #define pmd_page_vaddr(pmd)    (pmd_val(pmd) & ~PMD_MASKED_BITS)
 extern struct page *pmd_page(pmd_t pmd);
@@ -164,9 +164,21 @@ extern struct page *pmd_page(pmd_t pmd);
 #define pud_present(pud)       (pud_val(pud) != 0)
 #define pud_clear(pudp)                (pud_val(*(pudp)) = 0)
 #define pud_page_vaddr(pud)    (pud_val(pud) & ~PUD_MASKED_BITS)
-#define pud_page(pud)          virt_to_page(pud_page_vaddr(pud))
 
+extern struct page *pud_page(pud_t pud);
+
+static inline pte_t pud_pte(pud_t pud)
+{
+       return __pte(pud_val(pud));
+}
+
+static inline pud_t pte_pud(pte_t pte)
+{
+       return __pud(pte_val(pte));
+}
+#define pud_write(pud)         pte_write(pud_pte(pud))
 #define pgd_set(pgdp, pudp)    ({pgd_val(*(pgdp)) = (unsigned long)(pudp);})
+#define pgd_write(pgd)         pte_write(pgd_pte(pgd))
 
 /*
  * Find an entry in a page-table-directory.  We combine the address region
@@ -422,7 +434,22 @@ extern void set_pmd_at(struct mm_struct *mm, unsigned long addr,
                       pmd_t *pmdp, pmd_t pmd);
 extern void update_mmu_cache_pmd(struct vm_area_struct *vma, unsigned long addr,
                                 pmd_t *pmd);
-
+/*
+ *
+ * For core kernel code by design pmd_trans_huge is never run on any hugetlbfs
+ * page. The hugetlbfs page table walking and mangling paths are totally
+ * separated form the core VM paths and they're differentiated by
+ *  VM_HUGETLB being set on vm_flags well before any pmd_trans_huge could run.
+ *
+ * pmd_trans_huge() is defined as false at build time if
+ * CONFIG_TRANSPARENT_HUGEPAGE=n to optimize away code blocks at build
+ * time in such case.
+ *
+ * For ppc64 we need to differntiate from explicit hugepages from THP, because
+ * for THP we also track the subpage details at the pmd level. We don't do
+ * that for explicit huge pages.
+ *
+ */
 static inline int pmd_trans_huge(pmd_t pmd)
 {
        /*
@@ -431,16 +458,6 @@ static inline int pmd_trans_huge(pmd_t pmd)
        return (pmd_val(pmd) & 0x3) && (pmd_val(pmd) & _PAGE_THP_HUGE);
 }
 
-static inline int pmd_large(pmd_t pmd)
-{
-       /*
-        * leaf pte for huge page, bottom two bits != 00
-        */
-       if (pmd_trans_huge(pmd))
-               return pmd_val(pmd) & _PAGE_PRESENT;
-       return 0;
-}
-
 static inline int pmd_trans_splitting(pmd_t pmd)
 {
        if (pmd_trans_huge(pmd))
@@ -451,6 +468,14 @@ static inline int pmd_trans_splitting(pmd_t pmd)
 extern int has_transparent_hugepage(void);
 #endif /* CONFIG_TRANSPARENT_HUGEPAGE */
 
+static inline int pmd_large(pmd_t pmd)
+{
+       /*
+        * leaf pte for huge page, bottom two bits != 00
+        */
+       return ((pmd_val(pmd) & 0x3) != 0x0);
+}
+
 static inline pte_t pmd_pte(pmd_t pmd)
 {
        return __pte(pmd_val(pmd));
index b460e723f0ece3b0195321759b9251503311578d..2b8e5ed28831a46aa49bedfae5dc5bf8e3228537 100644 (file)
@@ -62,6 +62,9 @@ static unsigned nr_gpages;
 /*
  * We have PGD_INDEX_SIZ = 12 and PTE_INDEX_SIZE = 8, so that we can have
  * 16GB hugepage pte in PGD and 16MB hugepage pte at PMD;
+ *
+ * Defined in such a way that we can optimize away code block at build time
+ * if CONFIG_HUGETLB_PAGE=n.
  */
 int pmd_huge(pmd_t pmd)
 {
index e0c71854317412e60671b5074fe07bcf91f47b38..87ff0c1908a9ed6dcf7300e9619fdb1794ef0a0f 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/vmalloc.h>
 #include <linux/memblock.h>
 #include <linux/slab.h>
+#include <linux/hugetlb.h>
 
 #include <asm/pgalloc.h>
 #include <asm/page.h>
@@ -344,16 +345,31 @@ EXPORT_SYMBOL(iounmap);
 EXPORT_SYMBOL(__iounmap);
 EXPORT_SYMBOL(__iounmap_at);
 
+#ifndef __PAGETABLE_PUD_FOLDED
+/* 4 level page table */
+struct page *pgd_page(pgd_t pgd)
+{
+       if (pgd_huge(pgd))
+               return pte_page(pgd_pte(pgd));
+       return virt_to_page(pgd_page_vaddr(pgd));
+}
+#endif
+
+struct page *pud_page(pud_t pud)
+{
+       if (pud_huge(pud))
+               return pte_page(pud_pte(pud));
+       return virt_to_page(pud_page_vaddr(pud));
+}
+
 /*
  * For hugepage we have pfn in the pmd, we use PTE_RPN_SHIFT bits for flags
  * For PTE page, we have a PTE_FRAG_SIZE (4K) aligned virtual address.
  */
 struct page *pmd_page(pmd_t pmd)
 {
-#ifdef CONFIG_TRANSPARENT_HUGEPAGE
-       if (pmd_trans_huge(pmd))
+       if (pmd_trans_huge(pmd) || pmd_huge(pmd))
                return pfn_to_page(pmd_pfn(pmd));
-#endif
        return virt_to_page(pmd_page_vaddr(pmd));
 }