powerpc/mm/book3s-64: Free up 7 high-order bits in the Linux PTE
authorPaul Mackerras <paulus@samba.org>
Mon, 22 Feb 2016 02:41:13 +0000 (13:41 +1100)
committerMichael Ellerman <mpe@ellerman.id.au>
Sat, 27 Feb 2016 10:06:57 +0000 (21:06 +1100)
This frees up bits 57-63 in the Linux PTE on 64-bit Book 3S machines.
In the 4k page case, this is done just by reducing the size of the
RPN field to 39 bits, giving 51-bit real addresses.  In the 64k page
case, we had 10 unused bits in the middle of the PTE, so this moves
the RPN field down 10 bits to make use of those unused bits.  This
means the RPN field is now 3 bits larger at 37 bits, giving 53-bit
real addresses in the normal case, or 49-bit real addresses for the
special 4k PFN case.

We are doing this in order to be able to move some other PTE bits
into the positions where PowerISA V3.0 processors will expect to
find them in radix-tree mode.  Ultimately we will be able to move
the RPN field to lower bit positions and make it larger.

Signed-off-by: Paul Mackerras <paulus@samba.org>
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/mm/pgtable_64.c

index ea0414d6659e0e515ce82d8ecde796cacff8b6c2..bee3643fa097d790dd8b0bf74c3451df6b3460f9 100644 (file)
@@ -53,6 +53,7 @@
 
 /* shift to put page number into pte */
 #define PTE_RPN_SHIFT  (18)
+#define PTE_RPN_SIZE   (39)    /* gives 51-bit real addresses */
 
 #define _PAGE_4K_PFN           0
 #ifndef __ASSEMBLY__
index 849bbec80f7bb1afd2a8622f75801fe2f7a67cb1..a8c4c2a1940b4a9886d26bb1c3d86b73ab5c950c 100644 (file)
 
 /* Shift to put page number into pte.
  *
- * That gives us a max RPN of 34 bits, which means a max of 50 bits
- * of addressable physical space, or 46 bits for the special 4k PFNs.
+ * That gives us a max RPN of 37 bits, which means a max of 53 bits
+ * of addressable physical space, or 49 bits for the special 4k PFNs.
  */
-#define PTE_RPN_SHIFT  (30)
+#define PTE_RPN_SHIFT  (20)
+#define PTE_RPN_SIZE   (37)
+
 /*
  * we support 16 fragments per PTE page of 64K size.
  */
@@ -120,7 +122,7 @@ extern bool __rpte_sub_valid(real_pte_t rpte, unsigned long index);
        (((pte) & _PAGE_COMBO)? MMU_PAGE_4K: MMU_PAGE_64K)
 
 #define remap_4k_pfn(vma, addr, pfn, prot)                             \
-       (WARN_ON(((pfn) >= (1UL << (64 - PTE_RPN_SHIFT)))) ? -EINVAL :  \
+       (WARN_ON(((pfn) >= (1UL << PTE_RPN_SIZE))) ? -EINVAL :  \
                remap_pfn_range((vma), (addr), (pfn), PAGE_SIZE,        \
                        __pgprot(pgprot_val((prot)) | _PAGE_4K_PFN)))
 
index 9a0a4ef53b6d9483abb9b10c076e9c7442de39fc..64eff409b027ed17b0c5d7bd214aaf30415789a1 100644 (file)
  * The mask convered by the RPN must be a ULL on 32-bit platforms with
  * 64-bit PTEs
  */
-#define PTE_RPN_MASK   (~((1UL << PTE_RPN_SHIFT) - 1))
+#define PTE_RPN_MASK   (((1UL << PTE_RPN_SIZE) - 1) << PTE_RPN_SHIFT)
 /*
  * _PAGE_CHG_MASK masks of bits that are to be preserved across
  * pgprot changes
@@ -412,13 +412,13 @@ static inline int pte_present(pte_t pte)
  */
 static inline pte_t pfn_pte(unsigned long pfn, pgprot_t pgprot)
 {
-       return __pte(((pte_basic_t)(pfn) << PTE_RPN_SHIFT) |
+       return __pte((((pte_basic_t)(pfn) << PTE_RPN_SHIFT) & PTE_RPN_MASK) |
                     pgprot_val(pgprot));
 }
 
 static inline unsigned long pte_pfn(pte_t pte)
 {
-       return pte_val(pte) >> PTE_RPN_SHIFT;
+       return (pte_val(pte) & PTE_RPN_MASK) >> PTE_RPN_SHIFT;
 }
 
 /* Generic modifiers for PTE bits */
index ac07a30a7934265ed98706efb9f2c82ac8db85ce..c8240b737d11fe5b47fcace8a499d1847327653f 100644 (file)
@@ -154,10 +154,10 @@ static inline void pgd_set(pgd_t *pgdp, unsigned long val)
 #define SWP_TYPE_BITS 5
 #define __swp_type(x)          (((x).val >> _PAGE_BIT_SWAP_TYPE) \
                                & ((1UL << SWP_TYPE_BITS) - 1))
-#define __swp_offset(x)                ((x).val >> PTE_RPN_SHIFT)
+#define __swp_offset(x)                (((x).val & PTE_RPN_MASK) >> PTE_RPN_SHIFT)
 #define __swp_entry(type, offset)      ((swp_entry_t) { \
-                                       ((type) << _PAGE_BIT_SWAP_TYPE) \
-                                       | ((offset) << PTE_RPN_SHIFT) })
+                               ((type) << _PAGE_BIT_SWAP_TYPE) \
+                               | (((offset) << PTE_RPN_SHIFT) & PTE_RPN_MASK)})
 /*
  * swp_entry_t must be independent of pte bits. We build a swp_entry_t from
  * swap type and offset we get from swap and convert that to pte to find a
index cdf2123d46db4813a4e87f30d29f8da359c313d9..a1bbdfd88630774390af3be36b30ebd09b9e159e 100644 (file)
@@ -749,7 +749,7 @@ pmd_t pfn_pmd(unsigned long pfn, pgprot_t pgprot)
 {
        unsigned long pmdv;
 
-       pmdv = pfn << PTE_RPN_SHIFT;
+       pmdv = (pfn << PTE_RPN_SHIFT) & PTE_RPN_MASK;
        return pmd_set_protbits(__pmd(pmdv), pgprot);
 }