powerpc/mm: Add a _PAGE_PTE bit
authorAneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Tue, 1 Dec 2015 03:36:54 +0000 (09:06 +0530)
committerMichael Ellerman <mpe@ellerman.id.au>
Mon, 14 Dec 2015 04:19:14 +0000 (15:19 +1100)
For a pte entry we will have _PAGE_PTE set. Our pte page
address have a minimum alignment requirement of HUGEPD_SHIFT_MASK + 1.
We use the lower 7 bits to indicate hugepd. ie.

For pmd and pgd we can find:
1) _PAGE_PTE set pte -> indicate PTE
2) bits [2..6] non zero -> indicate hugepd.
   They also encode the size. We skip bit 1 (_PAGE_PRESENT).
3) othewise pointer to next table.

Acked-by: Scott Wood <scottwood@freescale.com>
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/book3s/64/hash-4k.h
arch/powerpc/include/asm/book3s/64/hash-64k.h
arch/powerpc/include/asm/book3s/64/hash.h
arch/powerpc/include/asm/book3s/64/pgtable.h
arch/powerpc/include/asm/pte-common.h
arch/powerpc/mm/hugetlbpage.c
arch/powerpc/mm/pgtable.c
arch/powerpc/mm/pgtable_64.c

index b4d25529d1798470e62741eabe03ba8c498bd513..e59832c9460942f7abbba6e055aaaafa4b18eaae 100644 (file)
@@ -116,10 +116,13 @@ static inline int pgd_huge(pgd_t pgd)
 static inline int hugepd_ok(hugepd_t hpd)
 {
        /*
-        * hugepd pointer, bottom two bits == 00 and next 4 bits
-        * indicate size of table
+        * if it is not a pte and have hugepd shift mask
+        * set, then it is a hugepd directory pointer
         */
-       return (((hpd.pd & 0x3) == 0x0) && ((hpd.pd & HUGEPD_SHIFT_MASK) != 0));
+       if (!(hpd.pd & _PAGE_PTE) &&
+           ((hpd.pd & HUGEPD_SHIFT_MASK) != 0))
+               return true;
+       return false;
 }
 #define is_hugepd(hpd)         (hugepd_ok(hpd))
 #endif
index 7570677c11c3e38627bafd04ca87d6ef28837601..52110d7af6597dc8f6ecc6175239ea7da3ac95a7 100644 (file)
@@ -130,25 +130,25 @@ extern bool __rpte_sub_valid(real_pte_t rpte, unsigned long index);
 static inline int pmd_huge(pmd_t pmd)
 {
        /*
-        * leaf pte for huge page, bottom two bits != 00
+        * leaf pte for huge page
         */
-       return ((pmd_val(pmd) & 0x3) != 0x0);
+       return !!(pmd_val(pmd) & _PAGE_PTE);
 }
 
 static inline int pud_huge(pud_t pud)
 {
        /*
-        * leaf pte for huge page, bottom two bits != 00
+        * leaf pte for huge page
         */
-       return ((pud_val(pud) & 0x3) != 0x0);
+       return !!(pud_val(pud) & _PAGE_PTE);
 }
 
 static inline int pgd_huge(pgd_t pgd)
 {
        /*
-        * leaf pte for huge page, bottom two bits != 00
+        * leaf pte for huge page
         */
-       return ((pgd_val(pgd) & 0x3) != 0x0);
+       return !!(pgd_val(pgd) & _PAGE_PTE);
 }
 #define pgd_huge pgd_huge
 
@@ -236,10 +236,8 @@ static inline void mark_hpte_slot_valid(unsigned char *hpte_slot_array,
  */
 static inline int pmd_trans_huge(pmd_t pmd)
 {
-       /*
-        * leaf pte for huge page, bottom two bits != 00
-        */
-       return (pmd_val(pmd) & 0x3) && (pmd_val(pmd) & _PAGE_THP_HUGE);
+       return !!((pmd_val(pmd) & (_PAGE_PTE | _PAGE_THP_HUGE)) ==
+                 (_PAGE_PTE | _PAGE_THP_HUGE));
 }
 
 static inline int pmd_trans_splitting(pmd_t pmd)
@@ -251,10 +249,7 @@ static inline int pmd_trans_splitting(pmd_t pmd)
 
 static inline int pmd_large(pmd_t pmd)
 {
-       /*
-        * leaf pte for huge page, bottom two bits != 00
-        */
-       return ((pmd_val(pmd) & 0x3) != 0x0);
+       return !!(pmd_val(pmd) & _PAGE_PTE);
 }
 
 static inline pmd_t pmd_mknotpresent(pmd_t pmd)
index 42e1273adad1b6a27ea12321f11eabfc5a2944e6..8b929e5317588af9745e7dd54d9896538ce27ccc 100644 (file)
  * We could create separate kernel read-only if we used the 3 PP bits
  * combinations that newer processors provide but we currently don't.
  */
-#define _PAGE_PRESENT          0x00001 /* software: pte contains a translation */
-#define _PAGE_USER             0x00002 /* matches one of the PP bits */
+#define _PAGE_PTE              0x00001
+#define _PAGE_PRESENT          0x00002 /* software: pte contains a translation */
 #define _PAGE_BIT_SWAP_TYPE    2
-#define _PAGE_EXEC             0x00004 /* No execute on POWER4 and newer (we invert) */
-#define _PAGE_GUARDED          0x00008
+#define _PAGE_USER             0x00004 /* matches one of the PP bits */
+#define _PAGE_EXEC             0x00008 /* No execute on POWER4 and newer (we invert) */
+#define _PAGE_GUARDED          0x00010
 /* We can derive Memory coherence from _PAGE_NO_CACHE */
 #define _PAGE_COHERENT         0x0
 #define _PAGE_NO_CACHE         0x00020 /* I: cache inhibit */
@@ -49,7 +50,7 @@
  */
 #define _HPAGE_CHG_MASK (PTE_RPN_MASK | _PAGE_HPTEFLAGS |              \
                         _PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_SPLITTING | \
-                        _PAGE_THP_HUGE)
+                        _PAGE_THP_HUGE | _PAGE_PTE)
 
 #ifdef CONFIG_PPC_64K_PAGES
 #include <asm/book3s/64/hash-64k.h>
  * pgprot changes
  */
 #define _PAGE_CHG_MASK (PTE_RPN_MASK | _PAGE_HPTEFLAGS | _PAGE_DIRTY | \
-                        _PAGE_ACCESSED | _PAGE_SPECIAL)
+                        _PAGE_ACCESSED | _PAGE_SPECIAL | _PAGE_PTE)
 /*
  * Mask of bits returned by pte_pgprot()
  */
index f2ace2cac7bbb6c263260aeb2bd0e567ddf5d6e4..bb97b6a52b846ef5fcda82bbef1ad57659cbd904 100644 (file)
@@ -213,8 +213,7 @@ static inline int pmd_protnone(pmd_t pmd)
 
 static inline pmd_t pmd_mkhuge(pmd_t pmd)
 {
-       /* Do nothing, mk_pmd() does this part.  */
-       return pmd;
+       return __pmd(pmd_val(pmd) | (_PAGE_PTE | _PAGE_THP_HUGE));
 }
 
 #define __HAVE_ARCH_PMDP_SET_ACCESS_FLAGS
index 71537a319fc828474f71fd1855ed127b30d0cce5..1ec67b0430657c590fdbf2b230fc8ca926989e6e 100644 (file)
 #else
 #define _PAGE_RW 0
 #endif
+
+#ifndef _PAGE_PTE
+#define _PAGE_PTE 0
+#endif
+
 #ifndef _PMD_PRESENT_MASK
 #define _PMD_PRESENT_MASK      _PMD_PRESENT
 #endif
index bc72e542a83eee08d7fe6ae03f55dd04c2d3d9bb..61b8b7ccea4f55882ccf00f000879dda6e2dd493 100644 (file)
@@ -894,8 +894,8 @@ void flush_dcache_icache_hugepage(struct page *page)
  * We have 4 cases for pgds and pmds:
  * (1) invalid (all zeroes)
  * (2) pointer to next table, as normal; bottom 6 bits == 0
- * (3) leaf pte for huge page, bottom two bits != 00
- * (4) hugepd pointer, bottom two bits == 00, next 4 bits indicate size of table
+ * (3) leaf pte for huge page _PAGE_PTE set
+ * (4) hugepd pointer, _PAGE_PTE = 0 and bits [2..6] indicate size of table
  *
  * So long as we atomically load page table pointers we are safe against teardown,
  * we can follow the address down to the the page and take a ref on it.
index 83dfcb55ffef69b2f5921212ccdaf6d18b49da52..83dfd7925c72c95efa47766c1806ef3e4a39126c 100644 (file)
@@ -179,6 +179,10 @@ void set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep,
         */
        VM_WARN_ON((pte_val(*ptep) & (_PAGE_PRESENT | _PAGE_USER)) ==
                (_PAGE_PRESENT | _PAGE_USER));
+       /*
+        * Add the pte bit when tryint set a pte
+        */
+       pte = __pte(pte_val(pte) | _PAGE_PTE);
 
        /* Note: mm->context.id might not yet have been assigned as
         * this context might not have been activated yet when this
index d42dd289abfeddd24ffd790746c5ed5cc30a0055..ea6bc31debb05562cf235d0696f5aaadbc698982 100644 (file)
@@ -765,13 +765,8 @@ static pmd_t pmd_set_protbits(pmd_t pmd, pgprot_t pgprot)
 pmd_t pfn_pmd(unsigned long pfn, pgprot_t pgprot)
 {
        unsigned long pmdv;
-       /*
-        * For a valid pte, we would have _PAGE_PRESENT always
-        * set. We use this to check THP page at pmd level.
-        * leaf pte for huge page, bottom two bits != 00
-        */
+
        pmdv = pfn << PTE_RPN_SHIFT;
-       pmdv |= _PAGE_THP_HUGE;
        return pmd_set_protbits(__pmd(pmdv), pgprot);
 }