powerpc/THP: Double the PMD table size for THP
authorAneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Thu, 20 Jun 2013 09:00:14 +0000 (14:30 +0530)
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>
Fri, 21 Jun 2013 06:01:53 +0000 (16:01 +1000)
THP code does PTE page allocation along with large page request and deposit them
for later use. This is to ensure that we won't have any failures when we split
hugepages to regular pages.

On powerpc we want to use the deposited PTE page for storing hash pte slot and
secondary bit information for the HPTEs. We use the second half
of the pmd table to save the deposted PTE page.

Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
arch/powerpc/include/asm/pgalloc-64.h
arch/powerpc/include/asm/pgtable-ppc64-64k.h
arch/powerpc/include/asm/pgtable-ppc64.h
arch/powerpc/mm/init_64.c

index b66ae722a8e9c2d9aacb9ef7eb49e553d9ad9dde..f65e27b09bd38010218b270ebcb27adb967c277b 100644 (file)
@@ -221,17 +221,17 @@ static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t table,
 
 static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr)
 {
-       return kmem_cache_alloc(PGT_CACHE(PMD_INDEX_SIZE),
+       return kmem_cache_alloc(PGT_CACHE(PMD_CACHE_INDEX),
                                GFP_KERNEL|__GFP_REPEAT);
 }
 
 static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
 {
-       kmem_cache_free(PGT_CACHE(PMD_INDEX_SIZE), pmd);
+       kmem_cache_free(PGT_CACHE(PMD_CACHE_INDEX), pmd);
 }
 
 #define __pmd_free_tlb(tlb, pmd, addr)               \
-       pgtable_free_tlb(tlb, pmd, PMD_INDEX_SIZE)
+       pgtable_free_tlb(tlb, pmd, PMD_CACHE_INDEX)
 #ifndef CONFIG_PPC_64K_PAGES
 #define __pud_free_tlb(tlb, pud, addr)               \
        pgtable_free_tlb(tlb, pud, PUD_INDEX_SIZE)
index 45142d640720697452db397e05a922f96083939d..a56b82fb0609b86102606c1232c42c2791595992 100644 (file)
@@ -33,7 +33,8 @@
 #define PGDIR_MASK     (~(PGDIR_SIZE-1))
 
 /* Bits to mask out from a PMD to get to the PTE page */
-#define PMD_MASKED_BITS                0x1ff
+/* PMDs point to PTE table fragments which are 4K aligned.  */
+#define PMD_MASKED_BITS                0xfff
 /* Bits to mask out from a PGD/PUD to get to the PMD page */
 #define PUD_MASKED_BITS                0x1ff
 
index e3d55f6f24fe1828ae3ce7603770fcbd6c7470f1..ab843328b47fc7f563fa7d392efaaea961aef7ec 100644 (file)
                            PUD_INDEX_SIZE + PGD_INDEX_SIZE + PAGE_SHIFT)
 #define PGTABLE_RANGE (ASM_CONST(1) << PGTABLE_EADDR_SIZE)
 
-
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+#define PMD_CACHE_INDEX        (PMD_INDEX_SIZE + 1)
+#else
+#define PMD_CACHE_INDEX        PMD_INDEX_SIZE
+#endif
 /*
  * Define the address range of the kernel non-linear virtual area
  */
index a90b9c4589908078f139d953707b6ce13b6860d0..d0cd9e4c6837d2d17620b0f646151d9a54408f71 100644 (file)
@@ -88,7 +88,11 @@ static void pgd_ctor(void *addr)
 
 static void pmd_ctor(void *addr)
 {
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+       memset(addr, 0, PMD_TABLE_SIZE * 2);
+#else
        memset(addr, 0, PMD_TABLE_SIZE);
+#endif
 }
 
 struct kmem_cache *pgtable_cache[MAX_PGTABLE_INDEX_SIZE];
@@ -137,10 +141,9 @@ void pgtable_cache_add(unsigned shift, void (*ctor)(void *))
 void pgtable_cache_init(void)
 {
        pgtable_cache_add(PGD_INDEX_SIZE, pgd_ctor);
-       pgtable_cache_add(PMD_INDEX_SIZE, pmd_ctor);
-       if (!PGT_CACHE(PGD_INDEX_SIZE) || !PGT_CACHE(PMD_INDEX_SIZE))
+       pgtable_cache_add(PMD_CACHE_INDEX, pmd_ctor);
+       if (!PGT_CACHE(PGD_INDEX_SIZE) || !PGT_CACHE(PMD_CACHE_INDEX))
                panic("Couldn't allocate pgtable caches");
-
        /* In all current configs, when the PUD index exists it's the
         * same size as either the pgd or pmd index.  Verify that the
         * initialization above has also created a PUD cache.  This