sh: Move page table allocation out of line
authorMatt Fleming <matt@console-pimps.org>
Thu, 31 Dec 2009 12:19:24 +0000 (12:19 +0000)
committerMatt Fleming <matt@console-pimps.org>
Sat, 2 Jan 2010 01:02:25 +0000 (01:02 +0000)
We also switched away from quicklists and instead moved to slab
caches. After benchmarking both implementations the difference is
negligible. The slab caches suit us better though because the size of a
pgd table is just 4 entries when we're using a 3-level page table layout
and quicklists always deal with pages.

Signed-off-by: Matt Fleming <matt@console-pimps.org>
arch/sh/include/asm/pgalloc.h
arch/sh/include/asm/pgalloc_nopmd.h [deleted file]
arch/sh/include/asm/pgalloc_pmd.h [deleted file]
arch/sh/include/asm/pgtable.h
arch/sh/mm/Makefile
arch/sh/mm/pgtable.c [new file with mode: 0644]

index 4ea2785..e106474 100644 (file)
@@ -6,10 +6,13 @@
 
 #define QUICK_PT 1     /* Other page table pages that are zero on free */
 
+extern pgd_t *pgd_alloc(struct mm_struct *);
+extern void pgd_free(struct mm_struct *mm, pgd_t *pgd);
+
 #ifdef CONFIG_PGTABLE_LEVELS_3
-#include <asm/pgalloc_pmd.h>
-#else
-#include <asm/pgalloc_nopmd.h>
+extern void pud_populate(struct mm_struct *mm, pud_t *pudp, pmd_t *pmd);
+extern pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address);
+extern void pmd_free(struct mm_struct *mm, pmd_t *pmd);
 #endif
 
 static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd,
@@ -67,7 +70,6 @@ do {                                                  \
 
 static inline void check_pgt_cache(void)
 {
-       __check_pgt_cache();
        quicklist_trim(QUICK_PT, NULL, 25, 16);
 }
 
diff --git a/arch/sh/include/asm/pgalloc_nopmd.h b/arch/sh/include/asm/pgalloc_nopmd.h
deleted file mode 100644 (file)
index e4b344c..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-#ifndef __ASM_SH_PGALLOC_NOPMD_H
-#define __ASM_SH_PGALLOC_NOPMD_H
-
-#define QUICK_PGD 0    /* We preserve special mappings over free */
-
-static inline void pgd_ctor(void *x)
-{
-       pgd_t *pgd = x;
-
-       memcpy(pgd + USER_PTRS_PER_PGD,
-              swapper_pg_dir + USER_PTRS_PER_PGD,
-              (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
-}
-
-static inline pgd_t *pgd_alloc(struct mm_struct *mm)
-{
-       return quicklist_alloc(QUICK_PGD, GFP_KERNEL | __GFP_REPEAT, pgd_ctor);
-}
-
-static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
-{
-       quicklist_free(QUICK_PGD, NULL, pgd);
-}
-
-static inline void __check_pgt_cache(void)
-{
-       quicklist_trim(QUICK_PGD, NULL, 25, 16);
-}
-
-#endif /* __ASM_SH_PGALLOC_NOPMD_H */
diff --git a/arch/sh/include/asm/pgalloc_pmd.h b/arch/sh/include/asm/pgalloc_pmd.h
deleted file mode 100644 (file)
index 20f75cc..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-#ifndef __ASM_SH_PGALLOC_PMD_H
-#define __ASM_SH_PGALLOC_PMD_H
-
-static inline pgd_t *pgd_alloc(struct mm_struct *mm)
-{
-       pgd_t *pgd;
-       int i;
-
-       pgd = kzalloc(sizeof(*pgd) * PTRS_PER_PGD, GFP_KERNEL | __GFP_REPEAT);
-
-       for (i = USER_PTRS_PER_PGD; i < PTRS_PER_PGD; i++)
-               pgd[i] = swapper_pg_dir[i];
-
-       return pgd;
-}
-
-static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
-{
-       kfree(pgd);
-}
-
-static inline void __check_pgt_cache(void)
-{
-}
-
-static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd)
-{
-       set_pud(pud, __pud((unsigned long)pmd));
-}
-
-static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address)
-{
-       return quicklist_alloc(QUICK_PT, GFP_KERNEL | __GFP_REPEAT, NULL);
-}
-
-static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
-{
-       quicklist_free(QUICK_PT, NULL, pmd);
-}
-
-#endif /* __ASM_SH_PGALLOC_PMD_H */
index 9effcc3..78598ec 100644 (file)
@@ -141,9 +141,9 @@ typedef pte_t *pte_addr_t;
 #define pte_pfn(x)             ((unsigned long)(((x).pte_low >> PAGE_SHIFT)))
 
 /*
- * No page table caches to initialise
+ * Initialise the page table caches
  */
-#define pgtable_cache_init()   do { } while (0)
+extern void pgtable_cache_init(void);
 
 struct vm_area_struct;
 
index 8a70535..dd5010c 100644 (file)
@@ -15,7 +15,7 @@ obj-y                 += $(cacheops-y)
 
 mmu-y                  := nommu.o extable_32.o
 mmu-$(CONFIG_MMU)      := extable_$(BITS).o fault_$(BITS).o \
-                          ioremap_$(BITS).o kmap.o tlbflush_$(BITS).o
+                          ioremap_$(BITS).o kmap.o pgtable.o tlbflush_$(BITS).o
 
 obj-y                  += $(mmu-y)
 obj-$(CONFIG_DEBUG_FS) += asids-debugfs.o
diff --git a/arch/sh/mm/pgtable.c b/arch/sh/mm/pgtable.c
new file mode 100644 (file)
index 0000000..e1bc548
--- /dev/null
@@ -0,0 +1,57 @@
+#include <linux/mm.h>
+
+#define PGALLOC_GFP GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO
+
+static struct kmem_cache *pgd_cachep;
+
+#ifdef CONFIG_PGTABLE_LEVELS_3
+static struct kmem_cache *pmd_cachep;
+#endif
+
+void pgd_ctor(void *x)
+{
+       pgd_t *pgd = x;
+
+       memcpy(pgd + USER_PTRS_PER_PGD,
+              swapper_pg_dir + USER_PTRS_PER_PGD,
+              (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
+}
+
+void pgtable_cache_init(void)
+{
+       pgd_cachep = kmem_cache_create("pgd_cache",
+                                      PTRS_PER_PGD * (1<<PTE_MAGNITUDE),
+                                      PAGE_SIZE, SLAB_PANIC, pgd_ctor);
+#ifdef CONFIG_PGTABLE_LEVELS_3
+       pmd_cachep = kmem_cache_create("pmd_cache",
+                                      PTRS_PER_PMD * (1<<PTE_MAGNITUDE),
+                                      PAGE_SIZE, SLAB_PANIC, NULL);
+#endif
+}
+
+pgd_t *pgd_alloc(struct mm_struct *mm)
+{
+       return kmem_cache_alloc(pgd_cachep, PGALLOC_GFP);
+}
+
+void pgd_free(struct mm_struct *mm, pgd_t *pgd)
+{
+       kmem_cache_free(pgd_cachep, pgd);
+}
+
+#ifdef CONFIG_PGTABLE_LEVELS_3
+void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd)
+{
+       set_pud(pud, __pud((unsigned long)pmd));
+}
+
+pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address)
+{
+       return kmem_cache_alloc(pmd_cachep, PGALLOC_GFP);
+}
+
+void pmd_free(struct mm_struct *mm, pmd_t *pmd)
+{
+       kmem_cache_free(pmd_cachep, pmd);
+}
+#endif /* CONFIG_PGTABLE_LEVELS_3 */