diff options
-rw-r--r-- | arch/powerpc/include/asm/pgalloc-32.h | 10 | ||||
-rw-r--r-- | arch/powerpc/include/asm/pgalloc-64.h | 60 | ||||
-rw-r--r-- | arch/powerpc/include/asm/pgalloc.h | 30 | ||||
-rw-r--r-- | arch/powerpc/include/asm/pgtable-ppc64.h | 1 | ||||
-rw-r--r-- | arch/powerpc/mm/hugetlbpage.c | 51 | ||||
-rw-r--r-- | arch/powerpc/mm/init_64.c | 70 | ||||
-rw-r--r-- | arch/powerpc/mm/pgtable.c | 25 |
7 files changed, 125 insertions, 122 deletions
diff --git a/arch/powerpc/include/asm/pgalloc-32.h b/arch/powerpc/include/asm/pgalloc-32.h index c9500d666a1d..580cf73b96e8 100644 --- a/arch/powerpc/include/asm/pgalloc-32.h +++ b/arch/powerpc/include/asm/pgalloc-32.h | |||
@@ -3,7 +3,8 @@ | |||
3 | 3 | ||
4 | #include <linux/threads.h> | 4 | #include <linux/threads.h> |
5 | 5 | ||
6 | #define PTE_NONCACHE_NUM 0 /* dummy for now to share code w/ppc64 */ | 6 | /* For 32-bit, all levels of page tables are just drawn from get_free_page() */ |
7 | #define MAX_PGTABLE_INDEX_SIZE 0 | ||
7 | 8 | ||
8 | extern void __bad_pte(pmd_t *pmd); | 9 | extern void __bad_pte(pmd_t *pmd); |
9 | 10 | ||
@@ -36,11 +37,10 @@ extern void pgd_free(struct mm_struct *mm, pgd_t *pgd); | |||
36 | extern pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr); | 37 | extern pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr); |
37 | extern pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long addr); | 38 | extern pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long addr); |
38 | 39 | ||
39 | static inline void pgtable_free(pgtable_free_t pgf) | 40 | static inline void pgtable_free(void *table, unsigned index_size) |
40 | { | 41 | { |
41 | void *p = (void *)(pgf.val & ~PGF_CACHENUM_MASK); | 42 | BUG_ON(index_size); /* 32-bit doesn't use this */ |
42 | 43 | free_page((unsigned long)table); | |
43 | free_page((unsigned long)p); | ||
44 | } | 44 | } |
45 | 45 | ||
46 | #define check_pgt_cache() do { } while (0) | 46 | #define check_pgt_cache() do { } while (0) |
diff --git a/arch/powerpc/include/asm/pgalloc-64.h b/arch/powerpc/include/asm/pgalloc-64.h index e6f069c4f713..5c1cd73dafa8 100644 --- a/arch/powerpc/include/asm/pgalloc-64.h +++ b/arch/powerpc/include/asm/pgalloc-64.h | |||
@@ -11,27 +11,39 @@ | |||
11 | #include <linux/cpumask.h> | 11 | #include <linux/cpumask.h> |
12 | #include <linux/percpu.h> | 12 | #include <linux/percpu.h> |
13 | 13 | ||
14 | /* | ||
15 | * Functions that deal with pagetables that could be at any level of | ||
16 | * the table need to be passed an "index_size" so they know how to | ||
17 | * handle allocation. For PTE pages (which are linked to a struct | ||
18 | * page for now, and drawn from the main get_free_pages() pool), the | ||
19 | * allocation size will be (2^index_size * sizeof(pointer)) and | ||
20 | * allocations are drawn from the kmem_cache in PGT_CACHE(index_size). | ||
21 | * | ||
22 | * The maximum index size needs to be big enough to allow any | ||
23 | * pagetable sizes we need, but small enough to fit in the low bits of | ||
24 | * any page table pointer. In other words all pagetables, even tiny | ||
25 | * ones, must be aligned to allow at least enough low 0 bits to | ||
26 | * contain this value. This value is also used as a mask, so it must | ||
27 | * be one less than a power of two. | ||
28 | */ | ||
29 | #define MAX_PGTABLE_INDEX_SIZE 0xf | ||
30 | |||
14 | #ifndef CONFIG_PPC_SUBPAGE_PROT | 31 | #ifndef CONFIG_PPC_SUBPAGE_PROT |
15 | static inline void subpage_prot_free(pgd_t *pgd) {} | 32 | static inline void subpage_prot_free(pgd_t *pgd) {} |
16 | #endif | 33 | #endif |
17 | 34 | ||
18 | extern struct kmem_cache *pgtable_cache[]; | 35 | extern struct kmem_cache *pgtable_cache[]; |
19 | 36 | #define PGT_CACHE(shift) (pgtable_cache[(shift)-1]) | |
20 | #define PGD_CACHE_NUM 0 | ||
21 | #define PUD_CACHE_NUM 1 | ||
22 | #define PMD_CACHE_NUM 1 | ||
23 | #define HUGEPTE_CACHE_NUM 2 | ||
24 | #define PTE_NONCACHE_NUM 7 /* from GFP rather than kmem_cache */ | ||
25 | 37 | ||
26 | static inline pgd_t *pgd_alloc(struct mm_struct *mm) | 38 | static inline pgd_t *pgd_alloc(struct mm_struct *mm) |
27 | { | 39 | { |
28 | return kmem_cache_alloc(pgtable_cache[PGD_CACHE_NUM], GFP_KERNEL); | 40 | return kmem_cache_alloc(PGT_CACHE(PGD_INDEX_SIZE), GFP_KERNEL); |
29 | } | 41 | } |
30 | 42 | ||
31 | static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd) | 43 | static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd) |
32 | { | 44 | { |
33 | subpage_prot_free(pgd); | 45 | subpage_prot_free(pgd); |
34 | kmem_cache_free(pgtable_cache[PGD_CACHE_NUM], pgd); | 46 | kmem_cache_free(PGT_CACHE(PGD_INDEX_SIZE), pgd); |
35 | } | 47 | } |
36 | 48 | ||
37 | #ifndef CONFIG_PPC_64K_PAGES | 49 | #ifndef CONFIG_PPC_64K_PAGES |
@@ -40,13 +52,13 @@ static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd) | |||
40 | 52 | ||
41 | static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr) | 53 | static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr) |
42 | { | 54 | { |
43 | return kmem_cache_alloc(pgtable_cache[PUD_CACHE_NUM], | 55 | return kmem_cache_alloc(PGT_CACHE(PUD_INDEX_SIZE), |
44 | GFP_KERNEL|__GFP_REPEAT); | 56 | GFP_KERNEL|__GFP_REPEAT); |
45 | } | 57 | } |
46 | 58 | ||
47 | static inline void pud_free(struct mm_struct *mm, pud_t *pud) | 59 | static inline void pud_free(struct mm_struct *mm, pud_t *pud) |
48 | { | 60 | { |
49 | kmem_cache_free(pgtable_cache[PUD_CACHE_NUM], pud); | 61 | kmem_cache_free(PGT_CACHE(PUD_INDEX_SIZE), pud); |
50 | } | 62 | } |
51 | 63 | ||
52 | static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd) | 64 | static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd) |
@@ -78,13 +90,13 @@ static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd, | |||
78 | 90 | ||
79 | static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr) | 91 | static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr) |
80 | { | 92 | { |
81 | return kmem_cache_alloc(pgtable_cache[PMD_CACHE_NUM], | 93 | return kmem_cache_alloc(PGT_CACHE(PMD_INDEX_SIZE), |
82 | GFP_KERNEL|__GFP_REPEAT); | 94 | GFP_KERNEL|__GFP_REPEAT); |
83 | } | 95 | } |
84 | 96 | ||
85 | static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd) | 97 | static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd) |
86 | { | 98 | { |
87 | kmem_cache_free(pgtable_cache[PMD_CACHE_NUM], pmd); | 99 | kmem_cache_free(PGT_CACHE(PMD_INDEX_SIZE), pmd); |
88 | } | 100 | } |
89 | 101 | ||
90 | static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, | 102 | static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, |
@@ -107,24 +119,22 @@ static inline pgtable_t pte_alloc_one(struct mm_struct *mm, | |||
107 | return page; | 119 | return page; |
108 | } | 120 | } |
109 | 121 | ||
110 | static inline void pgtable_free(pgtable_free_t pgf) | 122 | static inline void pgtable_free(void *table, unsigned index_size) |
111 | { | 123 | { |
112 | void *p = (void *)(pgf.val & ~PGF_CACHENUM_MASK); | 124 | if (!index_size) |
113 | int cachenum = pgf.val & PGF_CACHENUM_MASK; | 125 | free_page((unsigned long)table); |
114 | 126 | else { | |
115 | if (cachenum == PTE_NONCACHE_NUM) | 127 | BUG_ON(index_size > MAX_PGTABLE_INDEX_SIZE); |
116 | free_page((unsigned long)p); | 128 | kmem_cache_free(PGT_CACHE(index_size), table); |
117 | else | 129 | } |
118 | kmem_cache_free(pgtable_cache[cachenum], p); | ||
119 | } | 130 | } |
120 | 131 | ||
121 | #define __pmd_free_tlb(tlb, pmd,addr) \ | 132 | #define __pmd_free_tlb(tlb, pmd, addr) \ |
122 | pgtable_free_tlb(tlb, pgtable_free_cache(pmd, \ | 133 | pgtable_free_tlb(tlb, pmd, PMD_INDEX_SIZE) |
123 | PMD_CACHE_NUM, PMD_TABLE_SIZE-1)) | ||
124 | #ifndef CONFIG_PPC_64K_PAGES | 134 | #ifndef CONFIG_PPC_64K_PAGES |
125 | #define __pud_free_tlb(tlb, pud, addr) \ | 135 | #define __pud_free_tlb(tlb, pud, addr) \ |
126 | pgtable_free_tlb(tlb, pgtable_free_cache(pud, \ | 136 | pgtable_free_tlb(tlb, pud, PUD_INDEX_SIZE) |
127 | PUD_CACHE_NUM, PUD_TABLE_SIZE-1)) | 137 | |
128 | #endif /* CONFIG_PPC_64K_PAGES */ | 138 | #endif /* CONFIG_PPC_64K_PAGES */ |
129 | 139 | ||
130 | #define check_pgt_cache() do { } while (0) | 140 | #define check_pgt_cache() do { } while (0) |
diff --git a/arch/powerpc/include/asm/pgalloc.h b/arch/powerpc/include/asm/pgalloc.h index f2e812de7c3c..abe8532bd14e 100644 --- a/arch/powerpc/include/asm/pgalloc.h +++ b/arch/powerpc/include/asm/pgalloc.h | |||
@@ -24,25 +24,6 @@ static inline void pte_free(struct mm_struct *mm, pgtable_t ptepage) | |||
24 | __free_page(ptepage); | 24 | __free_page(ptepage); |
25 | } | 25 | } |
26 | 26 | ||
27 | typedef struct pgtable_free { | ||
28 | unsigned long val; | ||
29 | } pgtable_free_t; | ||
30 | |||
31 | /* This needs to be big enough to allow for MMU_PAGE_COUNT + 2 to be stored | ||
32 | * and small enough to fit in the low bits of any naturally aligned page | ||
33 | * table cache entry. Arbitrarily set to 0x1f, that should give us some | ||
34 | * room to grow | ||
35 | */ | ||
36 | #define PGF_CACHENUM_MASK 0x1f | ||
37 | |||
38 | static inline pgtable_free_t pgtable_free_cache(void *p, int cachenum, | ||
39 | unsigned long mask) | ||
40 | { | ||
41 | BUG_ON(cachenum > PGF_CACHENUM_MASK); | ||
42 | |||
43 | return (pgtable_free_t){.val = ((unsigned long) p & ~mask) | cachenum}; | ||
44 | } | ||
45 | |||
46 | #ifdef CONFIG_PPC64 | 27 | #ifdef CONFIG_PPC64 |
47 | #include <asm/pgalloc-64.h> | 28 | #include <asm/pgalloc-64.h> |
48 | #else | 29 | #else |
@@ -50,12 +31,12 @@ static inline pgtable_free_t pgtable_free_cache(void *p, int cachenum, | |||
50 | #endif | 31 | #endif |
51 | 32 | ||
52 | #ifdef CONFIG_SMP | 33 | #ifdef CONFIG_SMP |
53 | extern void pgtable_free_tlb(struct mmu_gather *tlb, pgtable_free_t pgf); | 34 | extern void pgtable_free_tlb(struct mmu_gather *tlb, void *table, unsigned shift); |
54 | extern void pte_free_finish(void); | 35 | extern void pte_free_finish(void); |
55 | #else /* CONFIG_SMP */ | 36 | #else /* CONFIG_SMP */ |
56 | static inline void pgtable_free_tlb(struct mmu_gather *tlb, pgtable_free_t pgf) | 37 | static inline void pgtable_free_tlb(struct mmu_gather *tlb, void *table, unsigned shift) |
57 | { | 38 | { |
58 | pgtable_free(pgf); | 39 | pgtable_free(table, shift); |
59 | } | 40 | } |
60 | static inline void pte_free_finish(void) { } | 41 | static inline void pte_free_finish(void) { } |
61 | #endif /* !CONFIG_SMP */ | 42 | #endif /* !CONFIG_SMP */ |
@@ -63,12 +44,9 @@ static inline void pte_free_finish(void) { } | |||
63 | static inline void __pte_free_tlb(struct mmu_gather *tlb, struct page *ptepage, | 44 | static inline void __pte_free_tlb(struct mmu_gather *tlb, struct page *ptepage, |
64 | unsigned long address) | 45 | unsigned long address) |
65 | { | 46 | { |
66 | pgtable_free_t pgf = pgtable_free_cache(page_address(ptepage), | ||
67 | PTE_NONCACHE_NUM, | ||
68 | PTE_TABLE_SIZE-1); | ||
69 | tlb_flush_pgtable(tlb, address); | 47 | tlb_flush_pgtable(tlb, address); |
70 | pgtable_page_dtor(ptepage); | 48 | pgtable_page_dtor(ptepage); |
71 | pgtable_free_tlb(tlb, pgf); | 49 | pgtable_free_tlb(tlb, page_address(ptepage), 0); |
72 | } | 50 | } |
73 | 51 | ||
74 | #endif /* __KERNEL__ */ | 52 | #endif /* __KERNEL__ */ |
diff --git a/arch/powerpc/include/asm/pgtable-ppc64.h b/arch/powerpc/include/asm/pgtable-ppc64.h index 806abe7a3fa5..8697d6555090 100644 --- a/arch/powerpc/include/asm/pgtable-ppc64.h +++ b/arch/powerpc/include/asm/pgtable-ppc64.h | |||
@@ -354,6 +354,7 @@ static inline void __ptep_set_access_flags(pte_t *ptep, pte_t entry) | |||
354 | #define pgoff_to_pte(off) ((pte_t) {((off) << PTE_RPN_SHIFT)|_PAGE_FILE}) | 354 | #define pgoff_to_pte(off) ((pte_t) {((off) << PTE_RPN_SHIFT)|_PAGE_FILE}) |
355 | #define PTE_FILE_MAX_BITS (BITS_PER_LONG - PTE_RPN_SHIFT) | 355 | #define PTE_FILE_MAX_BITS (BITS_PER_LONG - PTE_RPN_SHIFT) |
356 | 356 | ||
357 | void pgtable_cache_add(unsigned shift, void (*ctor)(void *)); | ||
357 | void pgtable_cache_init(void); | 358 | void pgtable_cache_init(void); |
358 | 359 | ||
359 | /* | 360 | /* |
diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c index 3d542a9732ae..7230d7a4fbd9 100644 --- a/arch/powerpc/mm/hugetlbpage.c +++ b/arch/powerpc/mm/hugetlbpage.c | |||
@@ -43,26 +43,14 @@ static unsigned nr_gpages; | |||
43 | unsigned int mmu_huge_psizes[MMU_PAGE_COUNT] = { }; /* initialize all to 0 */ | 43 | unsigned int mmu_huge_psizes[MMU_PAGE_COUNT] = { }; /* initialize all to 0 */ |
44 | 44 | ||
45 | #define hugepte_shift mmu_huge_psizes | 45 | #define hugepte_shift mmu_huge_psizes |
46 | #define PTRS_PER_HUGEPTE(psize) (1 << hugepte_shift[psize]) | 46 | #define HUGEPTE_INDEX_SIZE(psize) (mmu_huge_psizes[(psize)]) |
47 | #define HUGEPTE_TABLE_SIZE(psize) (sizeof(pte_t) << hugepte_shift[psize]) | 47 | #define PTRS_PER_HUGEPTE(psize) (1 << mmu_huge_psizes[psize]) |
48 | 48 | ||
49 | #define HUGEPD_SHIFT(psize) (mmu_psize_to_shift(psize) \ | 49 | #define HUGEPD_SHIFT(psize) (mmu_psize_to_shift(psize) \ |
50 | + hugepte_shift[psize]) | 50 | + HUGEPTE_INDEX_SIZE(psize)) |
51 | #define HUGEPD_SIZE(psize) (1UL << HUGEPD_SHIFT(psize)) | 51 | #define HUGEPD_SIZE(psize) (1UL << HUGEPD_SHIFT(psize)) |
52 | #define HUGEPD_MASK(psize) (~(HUGEPD_SIZE(psize)-1)) | 52 | #define HUGEPD_MASK(psize) (~(HUGEPD_SIZE(psize)-1)) |
53 | 53 | ||
54 | /* Subtract one from array size because we don't need a cache for 4K since | ||
55 | * is not a huge page size */ | ||
56 | #define HUGE_PGTABLE_INDEX(psize) (HUGEPTE_CACHE_NUM + psize - 1) | ||
57 | #define HUGEPTE_CACHE_NAME(psize) (huge_pgtable_cache_name[psize]) | ||
58 | |||
59 | static const char *huge_pgtable_cache_name[MMU_PAGE_COUNT] = { | ||
60 | [MMU_PAGE_64K] = "hugepte_cache_64K", | ||
61 | [MMU_PAGE_1M] = "hugepte_cache_1M", | ||
62 | [MMU_PAGE_16M] = "hugepte_cache_16M", | ||
63 | [MMU_PAGE_16G] = "hugepte_cache_16G", | ||
64 | }; | ||
65 | |||
66 | /* Flag to mark huge PD pointers. This means pmd_bad() and pud_bad() | 54 | /* Flag to mark huge PD pointers. This means pmd_bad() and pud_bad() |
67 | * will choke on pointers to hugepte tables, which is handy for | 55 | * will choke on pointers to hugepte tables, which is handy for |
68 | * catching screwups early. */ | 56 | * catching screwups early. */ |
@@ -114,15 +102,15 @@ static inline pte_t *hugepte_offset(hugepd_t *hpdp, unsigned long addr, | |||
114 | static int __hugepte_alloc(struct mm_struct *mm, hugepd_t *hpdp, | 102 | static int __hugepte_alloc(struct mm_struct *mm, hugepd_t *hpdp, |
115 | unsigned long address, unsigned int psize) | 103 | unsigned long address, unsigned int psize) |
116 | { | 104 | { |
117 | pte_t *new = kmem_cache_zalloc(pgtable_cache[HUGE_PGTABLE_INDEX(psize)], | 105 | pte_t *new = kmem_cache_zalloc(PGT_CACHE(hugepte_shift[psize]), |
118 | GFP_KERNEL|__GFP_REPEAT); | 106 | GFP_KERNEL|__GFP_REPEAT); |
119 | 107 | ||
120 | if (! new) | 108 | if (! new) |
121 | return -ENOMEM; | 109 | return -ENOMEM; |
122 | 110 | ||
123 | spin_lock(&mm->page_table_lock); | 111 | spin_lock(&mm->page_table_lock); |
124 | if (!hugepd_none(*hpdp)) | 112 | if (!hugepd_none(*hpdp)) |
125 | kmem_cache_free(pgtable_cache[HUGE_PGTABLE_INDEX(psize)], new); | 113 | kmem_cache_free(PGT_CACHE(hugepte_shift[psize]), new); |
126 | else | 114 | else |
127 | hpdp->pd = (unsigned long)new | HUGEPD_OK; | 115 | hpdp->pd = (unsigned long)new | HUGEPD_OK; |
128 | spin_unlock(&mm->page_table_lock); | 116 | spin_unlock(&mm->page_table_lock); |
@@ -271,9 +259,7 @@ static void free_hugepte_range(struct mmu_gather *tlb, hugepd_t *hpdp, | |||
271 | 259 | ||
272 | hpdp->pd = 0; | 260 | hpdp->pd = 0; |
273 | tlb->need_flush = 1; | 261 | tlb->need_flush = 1; |
274 | pgtable_free_tlb(tlb, pgtable_free_cache(hugepte, | 262 | pgtable_free_tlb(tlb, hugepte, hugepte_shift[psize]); |
275 | HUGEPTE_CACHE_NUM+psize-1, | ||
276 | PGF_CACHENUM_MASK)); | ||
277 | } | 263 | } |
278 | 264 | ||
279 | static void hugetlb_free_pmd_range(struct mmu_gather *tlb, pud_t *pud, | 265 | static void hugetlb_free_pmd_range(struct mmu_gather *tlb, pud_t *pud, |
@@ -698,8 +684,6 @@ static void __init set_huge_psize(int psize) | |||
698 | if (mmu_huge_psizes[psize] || | 684 | if (mmu_huge_psizes[psize] || |
699 | mmu_psize_defs[psize].shift == PAGE_SHIFT) | 685 | mmu_psize_defs[psize].shift == PAGE_SHIFT) |
700 | return; | 686 | return; |
701 | if (WARN_ON(HUGEPTE_CACHE_NAME(psize) == NULL)) | ||
702 | return; | ||
703 | hugetlb_add_hstate(mmu_psize_defs[psize].shift - PAGE_SHIFT); | 687 | hugetlb_add_hstate(mmu_psize_defs[psize].shift - PAGE_SHIFT); |
704 | 688 | ||
705 | switch (mmu_psize_defs[psize].shift) { | 689 | switch (mmu_psize_defs[psize].shift) { |
@@ -753,9 +737,9 @@ static int __init hugetlbpage_init(void) | |||
753 | if (!cpu_has_feature(CPU_FTR_16M_PAGE)) | 737 | if (!cpu_has_feature(CPU_FTR_16M_PAGE)) |
754 | return -ENODEV; | 738 | return -ENODEV; |
755 | 739 | ||
756 | /* Add supported huge page sizes. Need to change HUGE_MAX_HSTATE | 740 | /* Add supported huge page sizes. Need to change |
757 | * and adjust PTE_NONCACHE_NUM if the number of supported huge page | 741 | * HUGE_MAX_HSTATE if the number of supported huge page sizes |
758 | * sizes changes. | 742 | * changes. |
759 | */ | 743 | */ |
760 | set_huge_psize(MMU_PAGE_16M); | 744 | set_huge_psize(MMU_PAGE_16M); |
761 | set_huge_psize(MMU_PAGE_16G); | 745 | set_huge_psize(MMU_PAGE_16G); |
@@ -769,16 +753,11 @@ static int __init hugetlbpage_init(void) | |||
769 | 753 | ||
770 | for (psize = 0; psize < MMU_PAGE_COUNT; ++psize) { | 754 | for (psize = 0; psize < MMU_PAGE_COUNT; ++psize) { |
771 | if (mmu_huge_psizes[psize]) { | 755 | if (mmu_huge_psizes[psize]) { |
772 | pgtable_cache[HUGE_PGTABLE_INDEX(psize)] = | 756 | pgtable_cache_add(hugepte_shift[psize], NULL); |
773 | kmem_cache_create( | 757 | if (!PGT_CACHE(hugepte_shift[psize])) |
774 | HUGEPTE_CACHE_NAME(psize), | 758 | panic("hugetlbpage_init(): could not create " |
775 | HUGEPTE_TABLE_SIZE(psize), | 759 | "pgtable cache for %d bit pagesize\n", |
776 | HUGEPTE_TABLE_SIZE(psize), | 760 | mmu_psize_to_shift(psize)); |
777 | 0, | ||
778 | NULL); | ||
779 | if (!pgtable_cache[HUGE_PGTABLE_INDEX(psize)]) | ||
780 | panic("hugetlbpage_init(): could not create %s"\ | ||
781 | "\n", HUGEPTE_CACHE_NAME(psize)); | ||
782 | } | 761 | } |
783 | } | 762 | } |
784 | 763 | ||
diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c index 335c578b9cc3..82ac61dcd3af 100644 --- a/arch/powerpc/mm/init_64.c +++ b/arch/powerpc/mm/init_64.c | |||
@@ -119,30 +119,58 @@ static void pmd_ctor(void *addr) | |||
119 | memset(addr, 0, PMD_TABLE_SIZE); | 119 | memset(addr, 0, PMD_TABLE_SIZE); |
120 | } | 120 | } |
121 | 121 | ||
122 | static const unsigned int pgtable_cache_size[2] = { | 122 | struct kmem_cache *pgtable_cache[MAX_PGTABLE_INDEX_SIZE]; |
123 | PGD_TABLE_SIZE, PMD_TABLE_SIZE | 123 | |
124 | }; | 124 | /* |
125 | static const char *pgtable_cache_name[ARRAY_SIZE(pgtable_cache_size)] = { | 125 | * Create a kmem_cache() for pagetables. This is not used for PTE |
126 | #ifdef CONFIG_PPC_64K_PAGES | 126 | * pages - they're linked to struct page, come from the normal free |
127 | "pgd_cache", "pmd_cache", | 127 | * pages pool and have a different entry size (see real_pte_t) to |
128 | #else | 128 | * everything else. Caches created by this function are used for all |
129 | "pgd_cache", "pud_pmd_cache", | 129 | * the higher level pagetables, and for hugepage pagetables. |
130 | #endif /* CONFIG_PPC_64K_PAGES */ | 130 | */ |
131 | }; | 131 | void pgtable_cache_add(unsigned shift, void (*ctor)(void *)) |
132 | 132 | { | |
133 | #ifdef CONFIG_HUGETLB_PAGE | 133 | char *name; |
134 | /* Hugepages need an extra cache per hugepagesize, initialized in | 134 | unsigned long table_size = sizeof(void *) << shift; |
135 | * hugetlbpage.c. We can't put into the tables above, because HPAGE_SHIFT | 135 | unsigned long align = table_size; |
136 | * is not compile time constant. */ | 136 | |
137 | struct kmem_cache *pgtable_cache[ARRAY_SIZE(pgtable_cache_size)+MMU_PAGE_COUNT]; | 137 | /* When batching pgtable pointers for RCU freeing, we store |
138 | #else | 138 | * the index size in the low bits. Table alignment must be |
139 | struct kmem_cache *pgtable_cache[ARRAY_SIZE(pgtable_cache_size)]; | 139 | * big enough to fit it */ |
140 | #endif | 140 | unsigned long minalign = MAX_PGTABLE_INDEX_SIZE + 1; |
141 | struct kmem_cache *new; | ||
142 | |||
143 | /* It would be nice if this was a BUILD_BUG_ON(), but at the | ||
144 | * moment, gcc doesn't seem to recognize is_power_of_2 as a | ||
145 | * constant expression, so so much for that. */ | ||
146 | BUG_ON(!is_power_of_2(minalign)); | ||
147 | BUG_ON((shift < 1) || (shift > MAX_PGTABLE_INDEX_SIZE)); | ||
148 | |||
149 | if (PGT_CACHE(shift)) | ||
150 | return; /* Already have a cache of this size */ | ||
151 | |||
152 | align = max_t(unsigned long, align, minalign); | ||
153 | name = kasprintf(GFP_KERNEL, "pgtable-2^%d", shift); | ||
154 | new = kmem_cache_create(name, table_size, align, 0, ctor); | ||
155 | PGT_CACHE(shift) = new; | ||
156 | |||
157 | pr_debug("Allocated pgtable cache for order %d\n", shift); | ||
158 | } | ||
159 | |||
141 | 160 | ||
142 | void pgtable_cache_init(void) | 161 | void pgtable_cache_init(void) |
143 | { | 162 | { |
144 | pgtable_cache[0] = kmem_cache_create(pgtable_cache_name[0], PGD_TABLE_SIZE, PGD_TABLE_SIZE, SLAB_PANIC, pgd_ctor); | 163 | pgtable_cache_add(PGD_INDEX_SIZE, pgd_ctor); |
145 | pgtable_cache[1] = kmem_cache_create(pgtable_cache_name[1], PMD_TABLE_SIZE, PMD_TABLE_SIZE, SLAB_PANIC, pmd_ctor); | 164 | pgtable_cache_add(PMD_INDEX_SIZE, pmd_ctor); |
165 | if (!PGT_CACHE(PGD_INDEX_SIZE) || !PGT_CACHE(PMD_INDEX_SIZE)) | ||
166 | panic("Couldn't allocate pgtable caches"); | ||
167 | |||
168 | /* In all current configs, when the PUD index exists it's the | ||
169 | * same size as either the pgd or pmd index. Verify that the | ||
170 | * initialization above has also created a PUD cache. This | ||
171 | * will need re-examiniation if we add new possibilities for | ||
172 | * the pagetable layout. */ | ||
173 | BUG_ON(PUD_INDEX_SIZE && !PGT_CACHE(PUD_INDEX_SIZE)); | ||
146 | } | 174 | } |
147 | 175 | ||
148 | #ifdef CONFIG_SPARSEMEM_VMEMMAP | 176 | #ifdef CONFIG_SPARSEMEM_VMEMMAP |
diff --git a/arch/powerpc/mm/pgtable.c b/arch/powerpc/mm/pgtable.c index 53040931de32..99df697c601a 100644 --- a/arch/powerpc/mm/pgtable.c +++ b/arch/powerpc/mm/pgtable.c | |||
@@ -49,12 +49,12 @@ struct pte_freelist_batch | |||
49 | { | 49 | { |
50 | struct rcu_head rcu; | 50 | struct rcu_head rcu; |
51 | unsigned int index; | 51 | unsigned int index; |
52 | pgtable_free_t tables[0]; | 52 | unsigned long tables[0]; |
53 | }; | 53 | }; |
54 | 54 | ||
55 | #define PTE_FREELIST_SIZE \ | 55 | #define PTE_FREELIST_SIZE \ |
56 | ((PAGE_SIZE - sizeof(struct pte_freelist_batch)) \ | 56 | ((PAGE_SIZE - sizeof(struct pte_freelist_batch)) \ |
57 | / sizeof(pgtable_free_t)) | 57 | / sizeof(unsigned long)) |
58 | 58 | ||
59 | static void pte_free_smp_sync(void *arg) | 59 | static void pte_free_smp_sync(void *arg) |
60 | { | 60 | { |
@@ -64,13 +64,13 @@ static void pte_free_smp_sync(void *arg) | |||
64 | /* This is only called when we are critically out of memory | 64 | /* This is only called when we are critically out of memory |
65 | * (and fail to get a page in pte_free_tlb). | 65 | * (and fail to get a page in pte_free_tlb). |
66 | */ | 66 | */ |
67 | static void pgtable_free_now(pgtable_free_t pgf) | 67 | static void pgtable_free_now(void *table, unsigned shift) |
68 | { | 68 | { |
69 | pte_freelist_forced_free++; | 69 | pte_freelist_forced_free++; |
70 | 70 | ||
71 | smp_call_function(pte_free_smp_sync, NULL, 1); | 71 | smp_call_function(pte_free_smp_sync, NULL, 1); |
72 | 72 | ||
73 | pgtable_free(pgf); | 73 | pgtable_free(table, shift); |
74 | } | 74 | } |
75 | 75 | ||
76 | static void pte_free_rcu_callback(struct rcu_head *head) | 76 | static void pte_free_rcu_callback(struct rcu_head *head) |
@@ -79,8 +79,12 @@ static void pte_free_rcu_callback(struct rcu_head *head) | |||
79 | container_of(head, struct pte_freelist_batch, rcu); | 79 | container_of(head, struct pte_freelist_batch, rcu); |
80 | unsigned int i; | 80 | unsigned int i; |
81 | 81 | ||
82 | for (i = 0; i < batch->index; i++) | 82 | for (i = 0; i < batch->index; i++) { |
83 | pgtable_free(batch->tables[i]); | 83 | void *table = (void *)(batch->tables[i] & ~MAX_PGTABLE_INDEX_SIZE); |
84 | unsigned shift = batch->tables[i] & MAX_PGTABLE_INDEX_SIZE; | ||
85 | |||
86 | pgtable_free(table, shift); | ||
87 | } | ||
84 | 88 | ||
85 | free_page((unsigned long)batch); | 89 | free_page((unsigned long)batch); |
86 | } | 90 | } |
@@ -91,25 +95,28 @@ static void pte_free_submit(struct pte_freelist_batch *batch) | |||
91 | call_rcu(&batch->rcu, pte_free_rcu_callback); | 95 | call_rcu(&batch->rcu, pte_free_rcu_callback); |
92 | } | 96 | } |
93 | 97 | ||
94 | void pgtable_free_tlb(struct mmu_gather *tlb, pgtable_free_t pgf) | 98 | void pgtable_free_tlb(struct mmu_gather *tlb, void *table, unsigned shift) |
95 | { | 99 | { |
96 | /* This is safe since tlb_gather_mmu has disabled preemption */ | 100 | /* This is safe since tlb_gather_mmu has disabled preemption */ |
97 | struct pte_freelist_batch **batchp = &__get_cpu_var(pte_freelist_cur); | 101 | struct pte_freelist_batch **batchp = &__get_cpu_var(pte_freelist_cur); |
102 | unsigned long pgf; | ||
98 | 103 | ||
99 | if (atomic_read(&tlb->mm->mm_users) < 2 || | 104 | if (atomic_read(&tlb->mm->mm_users) < 2 || |
100 | cpumask_equal(mm_cpumask(tlb->mm), cpumask_of(smp_processor_id()))){ | 105 | cpumask_equal(mm_cpumask(tlb->mm), cpumask_of(smp_processor_id()))){ |
101 | pgtable_free(pgf); | 106 | pgtable_free(table, shift); |
102 | return; | 107 | return; |
103 | } | 108 | } |
104 | 109 | ||
105 | if (*batchp == NULL) { | 110 | if (*batchp == NULL) { |
106 | *batchp = (struct pte_freelist_batch *)__get_free_page(GFP_ATOMIC); | 111 | *batchp = (struct pte_freelist_batch *)__get_free_page(GFP_ATOMIC); |
107 | if (*batchp == NULL) { | 112 | if (*batchp == NULL) { |
108 | pgtable_free_now(pgf); | 113 | pgtable_free_now(table, shift); |
109 | return; | 114 | return; |
110 | } | 115 | } |
111 | (*batchp)->index = 0; | 116 | (*batchp)->index = 0; |
112 | } | 117 | } |
118 | BUG_ON(shift > MAX_PGTABLE_INDEX_SIZE); | ||
119 | pgf = (unsigned long)table | shift; | ||
113 | (*batchp)->tables[(*batchp)->index++] = pgf; | 120 | (*batchp)->tables[(*batchp)->index++] = pgf; |
114 | if ((*batchp)->index == PTE_FREELIST_SIZE) { | 121 | if ((*batchp)->index == PTE_FREELIST_SIZE) { |
115 | pte_free_submit(*batchp); | 122 | pte_free_submit(*batchp); |