aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/mm/hugetlbpage.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/mm/hugetlbpage.c')
-rw-r--r--arch/powerpc/mm/hugetlbpage.c59
1 files changed, 33 insertions, 26 deletions
diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c
index f1c2d55b4377..a117024ab8cd 100644
--- a/arch/powerpc/mm/hugetlbpage.c
+++ b/arch/powerpc/mm/hugetlbpage.c
@@ -128,29 +128,37 @@ static int __hugepte_alloc(struct mm_struct *mm, hugepd_t *hpdp,
128 return 0; 128 return 0;
129} 129}
130 130
131/* Base page size affects how we walk hugetlb page tables */ 131
132#ifdef CONFIG_PPC_64K_PAGES 132static pud_t *hpud_offset(pgd_t *pgd, unsigned long addr, struct hstate *hstate)
133#define hpmd_offset(pud, addr, h) pmd_offset(pud, addr) 133{
134#define hpmd_alloc(mm, pud, addr, h) pmd_alloc(mm, pud, addr) 134 if (huge_page_shift(hstate) < PUD_SHIFT)
135#else 135 return pud_offset(pgd, addr);
136static inline 136 else
137pmd_t *hpmd_offset(pud_t *pud, unsigned long addr, struct hstate *hstate) 137 return (pud_t *) pgd;
138}
139static pud_t *hpud_alloc(struct mm_struct *mm, pgd_t *pgd, unsigned long addr,
140 struct hstate *hstate)
138{ 141{
139 if (huge_page_shift(hstate) == PAGE_SHIFT_64K) 142 if (huge_page_shift(hstate) < PUD_SHIFT)
143 return pud_alloc(mm, pgd, addr);
144 else
145 return (pud_t *) pgd;
146}
147static pmd_t *hpmd_offset(pud_t *pud, unsigned long addr, struct hstate *hstate)
148{
149 if (huge_page_shift(hstate) < PMD_SHIFT)
140 return pmd_offset(pud, addr); 150 return pmd_offset(pud, addr);
141 else 151 else
142 return (pmd_t *) pud; 152 return (pmd_t *) pud;
143} 153}
144static inline 154static pmd_t *hpmd_alloc(struct mm_struct *mm, pud_t *pud, unsigned long addr,
145pmd_t *hpmd_alloc(struct mm_struct *mm, pud_t *pud, unsigned long addr, 155 struct hstate *hstate)
146 struct hstate *hstate)
147{ 156{
148 if (huge_page_shift(hstate) == PAGE_SHIFT_64K) 157 if (huge_page_shift(hstate) < PMD_SHIFT)
149 return pmd_alloc(mm, pud, addr); 158 return pmd_alloc(mm, pud, addr);
150 else 159 else
151 return (pmd_t *) pud; 160 return (pmd_t *) pud;
152} 161}
153#endif
154 162
155/* Build list of addresses of gigantic pages. This function is used in early 163/* Build list of addresses of gigantic pages. This function is used in early
156 * boot before the buddy or bootmem allocator is setup. 164 * boot before the buddy or bootmem allocator is setup.
@@ -204,7 +212,7 @@ pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
204 212
205 pg = pgd_offset(mm, addr); 213 pg = pgd_offset(mm, addr);
206 if (!pgd_none(*pg)) { 214 if (!pgd_none(*pg)) {
207 pu = pud_offset(pg, addr); 215 pu = hpud_offset(pg, addr, hstate);
208 if (!pud_none(*pu)) { 216 if (!pud_none(*pu)) {
209 pm = hpmd_offset(pu, addr, hstate); 217 pm = hpmd_offset(pu, addr, hstate);
210 if (!pmd_none(*pm)) 218 if (!pmd_none(*pm))
@@ -233,7 +241,7 @@ pte_t *huge_pte_alloc(struct mm_struct *mm,
233 addr &= hstate->mask; 241 addr &= hstate->mask;
234 242
235 pg = pgd_offset(mm, addr); 243 pg = pgd_offset(mm, addr);
236 pu = pud_alloc(mm, pg, addr); 244 pu = hpud_alloc(mm, pg, addr, hstate);
237 245
238 if (pu) { 246 if (pu) {
239 pm = hpmd_alloc(mm, pu, addr, hstate); 247 pm = hpmd_alloc(mm, pu, addr, hstate);
@@ -316,13 +324,7 @@ static void hugetlb_free_pud_range(struct mmu_gather *tlb, pgd_t *pgd,
316 pud = pud_offset(pgd, addr); 324 pud = pud_offset(pgd, addr);
317 do { 325 do {
318 next = pud_addr_end(addr, end); 326 next = pud_addr_end(addr, end);
319#ifdef CONFIG_PPC_64K_PAGES 327 if (shift < PMD_SHIFT) {
320 if (pud_none_or_clear_bad(pud))
321 continue;
322 hugetlb_free_pmd_range(tlb, pud, addr, next, floor, ceiling,
323 psize);
324#else
325 if (shift == PAGE_SHIFT_64K) {
326 if (pud_none_or_clear_bad(pud)) 328 if (pud_none_or_clear_bad(pud))
327 continue; 329 continue;
328 hugetlb_free_pmd_range(tlb, pud, addr, next, floor, 330 hugetlb_free_pmd_range(tlb, pud, addr, next, floor,
@@ -332,7 +334,6 @@ static void hugetlb_free_pud_range(struct mmu_gather *tlb, pgd_t *pgd,
332 continue; 334 continue;
333 free_hugepte_range(tlb, (hugepd_t *)pud, psize); 335 free_hugepte_range(tlb, (hugepd_t *)pud, psize);
334 } 336 }
335#endif
336 } while (pud++, addr = next, addr != end); 337 } while (pud++, addr = next, addr != end);
337 338
338 start &= PGDIR_MASK; 339 start &= PGDIR_MASK;
@@ -422,9 +423,15 @@ void hugetlb_free_pgd_range(struct mmu_gather *tlb,
422 psize = get_slice_psize(tlb->mm, addr); 423 psize = get_slice_psize(tlb->mm, addr);
423 BUG_ON(!mmu_huge_psizes[psize]); 424 BUG_ON(!mmu_huge_psizes[psize]);
424 next = pgd_addr_end(addr, end); 425 next = pgd_addr_end(addr, end);
425 if (pgd_none_or_clear_bad(pgd)) 426 if (mmu_psize_to_shift(psize) < PUD_SHIFT) {
426 continue; 427 if (pgd_none_or_clear_bad(pgd))
427 hugetlb_free_pud_range(tlb, pgd, addr, next, floor, ceiling); 428 continue;
429 hugetlb_free_pud_range(tlb, pgd, addr, next, floor, ceiling);
430 } else {
431 if (pgd_none(*pgd))
432 continue;
433 free_hugepte_range(tlb, (hugepd_t *)pgd, psize);
434 }
428 } while (pgd++, addr = next, addr != end); 435 } while (pgd++, addr = next, addr != end);
429} 436}
430 437