aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatt Fleming <matt@console-pimps.org>2009-12-31 07:19:24 -0500
committerMatt Fleming <matt@console-pimps.org>2010-01-01 20:02:25 -0500
commit2a5eacca85d39d8b6dffae821d7d260f05584dc7 (patch)
treed3c686fffb3b181a6d9b6790ce912e308c45a0ce
parentb4c892762373c5e59c7e8db35f5f9a7658602bda (diff)
sh: Move page table allocation out of line
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>
-rw-r--r--arch/sh/include/asm/pgalloc.h10
-rw-r--r--arch/sh/include/asm/pgalloc_nopmd.h30
-rw-r--r--arch/sh/include/asm/pgalloc_pmd.h41
-rw-r--r--arch/sh/include/asm/pgtable.h4
-rw-r--r--arch/sh/mm/Makefile2
-rw-r--r--arch/sh/mm/pgtable.c57
6 files changed, 66 insertions, 78 deletions
diff --git a/arch/sh/include/asm/pgalloc.h b/arch/sh/include/asm/pgalloc.h
index 4ea27855c3b5..e106474996b2 100644
--- a/arch/sh/include/asm/pgalloc.h
+++ b/arch/sh/include/asm/pgalloc.h
@@ -6,10 +6,13 @@
6 6
7#define QUICK_PT 1 /* Other page table pages that are zero on free */ 7#define QUICK_PT 1 /* Other page table pages that are zero on free */
8 8
9extern pgd_t *pgd_alloc(struct mm_struct *);
10extern void pgd_free(struct mm_struct *mm, pgd_t *pgd);
11
9#ifdef CONFIG_PGTABLE_LEVELS_3 12#ifdef CONFIG_PGTABLE_LEVELS_3
10#include <asm/pgalloc_pmd.h> 13extern void pud_populate(struct mm_struct *mm, pud_t *pudp, pmd_t *pmd);
11#else 14extern pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address);
12#include <asm/pgalloc_nopmd.h> 15extern void pmd_free(struct mm_struct *mm, pmd_t *pmd);
13#endif 16#endif
14 17
15static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd, 18static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd,
@@ -67,7 +70,6 @@ do { \
67 70
68static inline void check_pgt_cache(void) 71static inline void check_pgt_cache(void)
69{ 72{
70 __check_pgt_cache();
71 quicklist_trim(QUICK_PT, NULL, 25, 16); 73 quicklist_trim(QUICK_PT, NULL, 25, 16);
72} 74}
73 75
diff --git a/arch/sh/include/asm/pgalloc_nopmd.h b/arch/sh/include/asm/pgalloc_nopmd.h
deleted file mode 100644
index e4b344c37e74..000000000000
--- a/arch/sh/include/asm/pgalloc_nopmd.h
+++ /dev/null
@@ -1,30 +0,0 @@
1#ifndef __ASM_SH_PGALLOC_NOPMD_H
2#define __ASM_SH_PGALLOC_NOPMD_H
3
4#define QUICK_PGD 0 /* We preserve special mappings over free */
5
6static inline void pgd_ctor(void *x)
7{
8 pgd_t *pgd = x;
9
10 memcpy(pgd + USER_PTRS_PER_PGD,
11 swapper_pg_dir + USER_PTRS_PER_PGD,
12 (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
13}
14
15static inline pgd_t *pgd_alloc(struct mm_struct *mm)
16{
17 return quicklist_alloc(QUICK_PGD, GFP_KERNEL | __GFP_REPEAT, pgd_ctor);
18}
19
20static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
21{
22 quicklist_free(QUICK_PGD, NULL, pgd);
23}
24
25static inline void __check_pgt_cache(void)
26{
27 quicklist_trim(QUICK_PGD, NULL, 25, 16);
28}
29
30#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
index 20f75cc4eb09..000000000000
--- a/arch/sh/include/asm/pgalloc_pmd.h
+++ /dev/null
@@ -1,41 +0,0 @@
1#ifndef __ASM_SH_PGALLOC_PMD_H
2#define __ASM_SH_PGALLOC_PMD_H
3
4static inline pgd_t *pgd_alloc(struct mm_struct *mm)
5{
6 pgd_t *pgd;
7 int i;
8
9 pgd = kzalloc(sizeof(*pgd) * PTRS_PER_PGD, GFP_KERNEL | __GFP_REPEAT);
10
11 for (i = USER_PTRS_PER_PGD; i < PTRS_PER_PGD; i++)
12 pgd[i] = swapper_pg_dir[i];
13
14 return pgd;
15}
16
17static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
18{
19 kfree(pgd);
20}
21
22static inline void __check_pgt_cache(void)
23{
24}
25
26static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd)
27{
28 set_pud(pud, __pud((unsigned long)pmd));
29}
30
31static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address)
32{
33 return quicklist_alloc(QUICK_PT, GFP_KERNEL | __GFP_REPEAT, NULL);
34}
35
36static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
37{
38 quicklist_free(QUICK_PT, NULL, pmd);
39}
40
41#endif /* __ASM_SH_PGALLOC_PMD_H */
diff --git a/arch/sh/include/asm/pgtable.h b/arch/sh/include/asm/pgtable.h
index 9effcc3b0d10..78598ec33d0a 100644
--- a/arch/sh/include/asm/pgtable.h
+++ b/arch/sh/include/asm/pgtable.h
@@ -141,9 +141,9 @@ typedef pte_t *pte_addr_t;
141#define pte_pfn(x) ((unsigned long)(((x).pte_low >> PAGE_SHIFT))) 141#define pte_pfn(x) ((unsigned long)(((x).pte_low >> PAGE_SHIFT)))
142 142
143/* 143/*
144 * No page table caches to initialise 144 * Initialise the page table caches
145 */ 145 */
146#define pgtable_cache_init() do { } while (0) 146extern void pgtable_cache_init(void);
147 147
148struct vm_area_struct; 148struct vm_area_struct;
149 149
diff --git a/arch/sh/mm/Makefile b/arch/sh/mm/Makefile
index 8a70535fa7ce..dd5010c708e0 100644
--- a/arch/sh/mm/Makefile
+++ b/arch/sh/mm/Makefile
@@ -15,7 +15,7 @@ obj-y += $(cacheops-y)
15 15
16mmu-y := nommu.o extable_32.o 16mmu-y := nommu.o extable_32.o
17mmu-$(CONFIG_MMU) := extable_$(BITS).o fault_$(BITS).o \ 17mmu-$(CONFIG_MMU) := extable_$(BITS).o fault_$(BITS).o \
18 ioremap_$(BITS).o kmap.o tlbflush_$(BITS).o 18 ioremap_$(BITS).o kmap.o pgtable.o tlbflush_$(BITS).o
19 19
20obj-y += $(mmu-y) 20obj-y += $(mmu-y)
21obj-$(CONFIG_DEBUG_FS) += asids-debugfs.o 21obj-$(CONFIG_DEBUG_FS) += asids-debugfs.o
diff --git a/arch/sh/mm/pgtable.c b/arch/sh/mm/pgtable.c
new file mode 100644
index 000000000000..e1bc5483cc07
--- /dev/null
+++ b/arch/sh/mm/pgtable.c
@@ -0,0 +1,57 @@
1#include <linux/mm.h>
2
3#define PGALLOC_GFP GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO
4
5static struct kmem_cache *pgd_cachep;
6
7#ifdef CONFIG_PGTABLE_LEVELS_3
8static struct kmem_cache *pmd_cachep;
9#endif
10
11void pgd_ctor(void *x)
12{
13 pgd_t *pgd = x;
14
15 memcpy(pgd + USER_PTRS_PER_PGD,
16 swapper_pg_dir + USER_PTRS_PER_PGD,
17 (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
18}
19
20void pgtable_cache_init(void)
21{
22 pgd_cachep = kmem_cache_create("pgd_cache",
23 PTRS_PER_PGD * (1<<PTE_MAGNITUDE),
24 PAGE_SIZE, SLAB_PANIC, pgd_ctor);
25#ifdef CONFIG_PGTABLE_LEVELS_3
26 pmd_cachep = kmem_cache_create("pmd_cache",
27 PTRS_PER_PMD * (1<<PTE_MAGNITUDE),
28 PAGE_SIZE, SLAB_PANIC, NULL);
29#endif
30}
31
32pgd_t *pgd_alloc(struct mm_struct *mm)
33{
34 return kmem_cache_alloc(pgd_cachep, PGALLOC_GFP);
35}
36
37void pgd_free(struct mm_struct *mm, pgd_t *pgd)
38{
39 kmem_cache_free(pgd_cachep, pgd);
40}
41
42#ifdef CONFIG_PGTABLE_LEVELS_3
43void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd)
44{
45 set_pud(pud, __pud((unsigned long)pmd));
46}
47
48pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address)
49{
50 return kmem_cache_alloc(pmd_cachep, PGALLOC_GFP);
51}
52
53void pmd_free(struct mm_struct *mm, pmd_t *pmd)
54{
55 kmem_cache_free(pmd_cachep, pmd);
56}
57#endif /* CONFIG_PGTABLE_LEVELS_3 */