powerpc32: Use kmem_cache memory for PGDIR
authorLEROY Christophe <christophe.leroy@c-s.fr>
Tue, 20 Jan 2015 09:57:34 +0000 (10:57 +0100)
committerScott Wood <scottwood@freescale.com>
Fri, 30 Jan 2015 03:59:02 +0000 (21:59 -0600)
When pages are not 4K, PGDIR table is allocated with kmalloc(). In order to
optimise TLB handlers, aligned memory is needed. kmalloc() doesn't provide
aligned memory blocks, so lets use a kmem_cache pool instead.

Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
Signed-off-by: Scott Wood <scottwood@freescale.com>
arch/powerpc/include/asm/pgtable-ppc32.h
arch/powerpc/mm/pgtable_32.c

index 9cde3c1522e316a4ab414adb52d53c9686317ebb..26ce0ab0a9e45f4a3d06a3a8a9ea4dae8a833390 100644 (file)
@@ -347,10 +347,14 @@ static inline void __ptep_set_access_flags(pte_t *ptep, pte_t entry)
 #define pte_to_pgoff(pte)      (pte_val(pte) >> 3)
 #define pgoff_to_pte(off)      ((pte_t) { ((off) << 3) | _PAGE_FILE })
 
+#ifndef CONFIG_PPC_4K_PAGES
+void pgtable_cache_init(void);
+#else
 /*
  * No page table caches to initialise
  */
 #define pgtable_cache_init()   do { } while (0)
+#endif
 
 extern int get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep,
                      pmd_t **pmdp);
index 833139620431282abb7fd3e1fba3e84922c67cc6..03b1a3b0fbd539cb3cbc6232bb72f9a8a1cc94b6 100644 (file)
@@ -72,13 +72,25 @@ extern unsigned long p_mapped_by_tlbcam(phys_addr_t pa);
 
 #define PGDIR_ORDER    (32 + PGD_T_LOG2 - PGDIR_SHIFT)
 
+#ifndef CONFIG_PPC_4K_PAGES
+static struct kmem_cache *pgtable_cache;
+
+void pgtable_cache_init(void)
+{
+       pgtable_cache = kmem_cache_create("PGDIR cache", 1 << PGDIR_ORDER,
+                                         1 << PGDIR_ORDER, 0, NULL);
+       if (pgtable_cache == NULL)
+               panic("Couldn't allocate pgtable caches");
+}
+#endif
+
 pgd_t *pgd_alloc(struct mm_struct *mm)
 {
        pgd_t *ret;
 
        /* pgdir take page or two with 4K pages and a page fraction otherwise */
 #ifndef CONFIG_PPC_4K_PAGES
-       ret = kzalloc(1 << PGDIR_ORDER, GFP_KERNEL);
+       ret = kmem_cache_alloc(pgtable_cache, GFP_KERNEL | __GFP_ZERO);
 #else
        ret = (pgd_t *)__get_free_pages(GFP_KERNEL|__GFP_ZERO,
                        PGDIR_ORDER - PAGE_SHIFT);
@@ -89,7 +101,7 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
 void pgd_free(struct mm_struct *mm, pgd_t *pgd)
 {
 #ifndef CONFIG_PPC_4K_PAGES
-       kfree((void *)pgd);
+       kmem_cache_free(pgtable_cache, (void *)pgd);
 #else
        free_pages((unsigned long)pgd, PGDIR_ORDER - PAGE_SHIFT);
 #endif