aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
authorAneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>2013-04-28 05:37:29 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2013-04-30 01:59:53 -0400
commitcf9427b85e90bb1ff90e2397ff419691d983c68b (patch)
tree023cfcfe1875f79398dfa6028e23a245140d60dc /arch/powerpc
parent0e5f35d0e4a8179cdfac115023f418126419e659 (diff)
powerpc: New hugepage directory format
Change the hugepage directory format so that we can have leaf ptes directly at page directory avoiding the allocation of hugepage directory. With the new table format we have 3 cases for pgds and pmds: (1) invalid (all zeroes) (2) pointer to next table, as normal; bottom 6 bits == 0 (4) hugepd pointer, bottom two bits == 00, next 4 bits indicate size of table Instead of storing shift value in hugepd pointer we use mmu_psize_def index so that we can fit all the supported hugepage size in 4 bits Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> Acked-by: Paul Mackerras <paulus@samba.org> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/include/asm/hugetlb.h30
-rw-r--r--arch/powerpc/include/asm/mmu-hash64.h20
-rw-r--r--arch/powerpc/include/asm/page.h13
-rw-r--r--arch/powerpc/include/asm/pgalloc-64.h5
-rw-r--r--arch/powerpc/mm/hugetlbpage.c26
-rw-r--r--arch/powerpc/mm/init_64.c3
6 files changed, 75 insertions, 22 deletions
diff --git a/arch/powerpc/include/asm/hugetlb.h b/arch/powerpc/include/asm/hugetlb.h
index 62e11a32c4c2..4daf7e684f58 100644
--- a/arch/powerpc/include/asm/hugetlb.h
+++ b/arch/powerpc/include/asm/hugetlb.h
@@ -6,6 +6,33 @@
6 6
7extern struct kmem_cache *hugepte_cache; 7extern struct kmem_cache *hugepte_cache;
8 8
9#ifdef CONFIG_PPC_BOOK3S_64
10/*
11 * This should work for other subarchs too. But right now we use the
12 * new format only for 64bit book3s
13 */
14static inline pte_t *hugepd_page(hugepd_t hpd)
15{
16 BUG_ON(!hugepd_ok(hpd));
17 /*
18 * We have only four bits to encode, MMU page size
19 */
20 BUILD_BUG_ON((MMU_PAGE_COUNT - 1) > 0xf);
21 return (pte_t *)(hpd.pd & ~HUGEPD_SHIFT_MASK);
22}
23
24static inline unsigned int hugepd_mmu_psize(hugepd_t hpd)
25{
26 return (hpd.pd & HUGEPD_SHIFT_MASK) >> 2;
27}
28
29static inline unsigned int hugepd_shift(hugepd_t hpd)
30{
31 return mmu_psize_to_shift(hugepd_mmu_psize(hpd));
32}
33
34#else
35
9static inline pte_t *hugepd_page(hugepd_t hpd) 36static inline pte_t *hugepd_page(hugepd_t hpd)
10{ 37{
11 BUG_ON(!hugepd_ok(hpd)); 38 BUG_ON(!hugepd_ok(hpd));
@@ -17,6 +44,9 @@ static inline unsigned int hugepd_shift(hugepd_t hpd)
17 return hpd.pd & HUGEPD_SHIFT_MASK; 44 return hpd.pd & HUGEPD_SHIFT_MASK;
18} 45}
19 46
47#endif /* CONFIG_PPC_BOOK3S_64 */
48
49
20static inline pte_t *hugepte_offset(hugepd_t *hpdp, unsigned long addr, 50static inline pte_t *hugepte_offset(hugepd_t *hpdp, unsigned long addr,
21 unsigned pdshift) 51 unsigned pdshift)
22{ 52{
diff --git a/arch/powerpc/include/asm/mmu-hash64.h b/arch/powerpc/include/asm/mmu-hash64.h
index b59e06f507ea..05895cff1345 100644
--- a/arch/powerpc/include/asm/mmu-hash64.h
+++ b/arch/powerpc/include/asm/mmu-hash64.h
@@ -21,6 +21,7 @@
21 * complete pgtable.h but only a portion of it. 21 * complete pgtable.h but only a portion of it.
22 */ 22 */
23#include <asm/pgtable-ppc64.h> 23#include <asm/pgtable-ppc64.h>
24#include <asm/bug.h>
24 25
25/* 26/*
26 * Segment table 27 * Segment table
@@ -159,6 +160,24 @@ struct mmu_psize_def
159 unsigned long avpnm; /* bits to mask out in AVPN in the HPTE */ 160 unsigned long avpnm; /* bits to mask out in AVPN in the HPTE */
160 unsigned long sllp; /* SLB L||LP (exact mask to use in slbmte) */ 161 unsigned long sllp; /* SLB L||LP (exact mask to use in slbmte) */
161}; 162};
163extern struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT];
164
165static inline int shift_to_mmu_psize(unsigned int shift)
166{
167 int psize;
168
169 for (psize = 0; psize < MMU_PAGE_COUNT; ++psize)
170 if (mmu_psize_defs[psize].shift == shift)
171 return psize;
172 return -1;
173}
174
175static inline unsigned int mmu_psize_to_shift(unsigned int mmu_psize)
176{
177 if (mmu_psize_defs[mmu_psize].shift)
178 return mmu_psize_defs[mmu_psize].shift;
179 BUG();
180}
162 181
163#endif /* __ASSEMBLY__ */ 182#endif /* __ASSEMBLY__ */
164 183
@@ -193,7 +212,6 @@ static inline int segment_shift(int ssize)
193/* 212/*
194 * The current system page and segment sizes 213 * The current system page and segment sizes
195 */ 214 */
196extern struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT];
197extern int mmu_linear_psize; 215extern int mmu_linear_psize;
198extern int mmu_virtual_psize; 216extern int mmu_virtual_psize;
199extern int mmu_vmalloc_psize; 217extern int mmu_vmalloc_psize;
diff --git a/arch/powerpc/include/asm/page.h b/arch/powerpc/include/asm/page.h
index f072e974f8a2..652719ccd2e9 100644
--- a/arch/powerpc/include/asm/page.h
+++ b/arch/powerpc/include/asm/page.h
@@ -249,6 +249,7 @@ extern long long virt_phys_offset;
249#define is_kernel_addr(x) ((x) >= PAGE_OFFSET) 249#define is_kernel_addr(x) ((x) >= PAGE_OFFSET)
250#endif 250#endif
251 251
252#ifndef CONFIG_PPC_BOOK3S_64
252/* 253/*
253 * Use the top bit of the higher-level page table entries to indicate whether 254 * Use the top bit of the higher-level page table entries to indicate whether
254 * the entries we point to contain hugepages. This works because we know that 255 * the entries we point to contain hugepages. This works because we know that
@@ -260,6 +261,7 @@ extern long long virt_phys_offset;
260#else 261#else
261#define PD_HUGE 0x80000000 262#define PD_HUGE 0x80000000
262#endif 263#endif
264#endif /* CONFIG_PPC_BOOK3S_64 */
263 265
264/* 266/*
265 * Some number of bits at the level of the page table that points to 267 * Some number of bits at the level of the page table that points to
@@ -354,10 +356,21 @@ typedef unsigned long pgprot_t;
354typedef struct { signed long pd; } hugepd_t; 356typedef struct { signed long pd; } hugepd_t;
355 357
356#ifdef CONFIG_HUGETLB_PAGE 358#ifdef CONFIG_HUGETLB_PAGE
359#ifdef CONFIG_PPC_BOOK3S_64
360static inline int hugepd_ok(hugepd_t hpd)
361{
362 /*
363 * hugepd pointer, bottom two bits == 00 and next 4 bits
364 * indicate size of table
365 */
366 return (((hpd.pd & 0x3) == 0x0) && ((hpd.pd & HUGEPD_SHIFT_MASK) != 0));
367}
368#else
357static inline int hugepd_ok(hugepd_t hpd) 369static inline int hugepd_ok(hugepd_t hpd)
358{ 370{
359 return (hpd.pd > 0); 371 return (hpd.pd > 0);
360} 372}
373#endif
361 374
362#define is_hugepd(pdep) (hugepd_ok(*((hugepd_t *)(pdep)))) 375#define is_hugepd(pdep) (hugepd_ok(*((hugepd_t *)(pdep))))
363#else /* CONFIG_HUGETLB_PAGE */ 376#else /* CONFIG_HUGETLB_PAGE */
diff --git a/arch/powerpc/include/asm/pgalloc-64.h b/arch/powerpc/include/asm/pgalloc-64.h
index 292725cec2e3..69e352a5252b 100644
--- a/arch/powerpc/include/asm/pgalloc-64.h
+++ b/arch/powerpc/include/asm/pgalloc-64.h
@@ -35,7 +35,10 @@ struct vmemmap_backing {
35#define MAX_PGTABLE_INDEX_SIZE 0xf 35#define MAX_PGTABLE_INDEX_SIZE 0xf
36 36
37extern struct kmem_cache *pgtable_cache[]; 37extern struct kmem_cache *pgtable_cache[];
38#define PGT_CACHE(shift) (pgtable_cache[(shift)-1]) 38#define PGT_CACHE(shift) ({ \
39 BUG_ON(!(shift)); \
40 pgtable_cache[(shift) - 1]; \
41 })
39 42
40static inline pgd_t *pgd_alloc(struct mm_struct *mm) 43static inline pgd_t *pgd_alloc(struct mm_struct *mm)
41{ 44{
diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c
index 5dc52d803ed8..b4e2f24a9b8f 100644
--- a/arch/powerpc/mm/hugetlbpage.c
+++ b/arch/powerpc/mm/hugetlbpage.c
@@ -48,23 +48,6 @@ static u64 gpage_freearray[MAX_NUMBER_GPAGES];
48static unsigned nr_gpages; 48static unsigned nr_gpages;
49#endif 49#endif
50 50
51static inline int shift_to_mmu_psize(unsigned int shift)
52{
53 int psize;
54
55 for (psize = 0; psize < MMU_PAGE_COUNT; ++psize)
56 if (mmu_psize_defs[psize].shift == shift)
57 return psize;
58 return -1;
59}
60
61static inline unsigned int mmu_psize_to_shift(unsigned int mmu_psize)
62{
63 if (mmu_psize_defs[mmu_psize].shift)
64 return mmu_psize_defs[mmu_psize].shift;
65 BUG();
66}
67
68#define hugepd_none(hpd) ((hpd).pd == 0) 51#define hugepd_none(hpd) ((hpd).pd == 0)
69 52
70pte_t *find_linux_pte_or_hugepte(pgd_t *pgdir, unsigned long ea, unsigned *shift) 53pte_t *find_linux_pte_or_hugepte(pgd_t *pgdir, unsigned long ea, unsigned *shift)
@@ -145,6 +128,7 @@ static int __hugepte_alloc(struct mm_struct *mm, hugepd_t *hpdp,
145 if (unlikely(!hugepd_none(*hpdp))) 128 if (unlikely(!hugepd_none(*hpdp)))
146 break; 129 break;
147 else 130 else
131 /* We use the old format for PPC_FSL_BOOK3E */
148 hpdp->pd = ((unsigned long)new & ~PD_HUGE) | pshift; 132 hpdp->pd = ((unsigned long)new & ~PD_HUGE) | pshift;
149 } 133 }
150 /* If we bailed from the for loop early, an error occurred, clean up */ 134 /* If we bailed from the for loop early, an error occurred, clean up */
@@ -156,9 +140,15 @@ static int __hugepte_alloc(struct mm_struct *mm, hugepd_t *hpdp,
156#else 140#else
157 if (!hugepd_none(*hpdp)) 141 if (!hugepd_none(*hpdp))
158 kmem_cache_free(cachep, new); 142 kmem_cache_free(cachep, new);
159 else 143 else {
144#ifdef CONFIG_PPC_BOOK3S_64
145 hpdp->pd = (unsigned long)new |
146 (shift_to_mmu_psize(pshift) << 2);
147#else
160 hpdp->pd = ((unsigned long)new & ~PD_HUGE) | pshift; 148 hpdp->pd = ((unsigned long)new & ~PD_HUGE) | pshift;
161#endif 149#endif
150 }
151#endif
162 spin_unlock(&mm->page_table_lock); 152 spin_unlock(&mm->page_table_lock);
163 return 0; 153 return 0;
164} 154}
diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c
index 7e2246fb2f31..a56de85ad3b7 100644
--- a/arch/powerpc/mm/init_64.c
+++ b/arch/powerpc/mm/init_64.c
@@ -129,8 +129,7 @@ void pgtable_cache_add(unsigned shift, void (*ctor)(void *))
129 align = max_t(unsigned long, align, minalign); 129 align = max_t(unsigned long, align, minalign);
130 name = kasprintf(GFP_KERNEL, "pgtable-2^%d", shift); 130 name = kasprintf(GFP_KERNEL, "pgtable-2^%d", shift);
131 new = kmem_cache_create(name, table_size, align, 0, ctor); 131 new = kmem_cache_create(name, table_size, align, 0, ctor);
132 PGT_CACHE(shift) = new; 132 pgtable_cache[shift - 1] = new;
133
134 pr_debug("Allocated pgtable cache for order %d\n", shift); 133 pr_debug("Allocated pgtable cache for order %d\n", shift);
135} 134}
136 135