aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/include/asm/book3s/64/pgtable.h21
-rw-r--r--arch/powerpc/include/asm/pgtable.h24
-rw-r--r--arch/powerpc/include/asm/pte-walk.h28
-rw-r--r--arch/powerpc/kvm/book3s_64_mmu_radix.c12
-rw-r--r--arch/powerpc/mm/book3s64/radix_pgtable.c10
-rw-r--r--arch/powerpc/mm/pgtable.c16
-rw-r--r--arch/powerpc/mm/pgtable_64.c12
-rw-r--r--arch/powerpc/mm/ptdump/ptdump.c6
-rw-r--r--arch/powerpc/xmon/xmon.c6
9 files changed, 102 insertions, 33 deletions
diff --git a/arch/powerpc/include/asm/book3s/64/pgtable.h b/arch/powerpc/include/asm/book3s/64/pgtable.h
index beabb099c040..62e6ea0a7650 100644
--- a/arch/powerpc/include/asm/book3s/64/pgtable.h
+++ b/arch/powerpc/include/asm/book3s/64/pgtable.h
@@ -1350,5 +1350,26 @@ static inline bool is_pte_rw_upgrade(unsigned long old_val, unsigned long new_va
1350 return false; 1350 return false;
1351} 1351}
1352 1352
1353/*
1354 * Like pmd_huge() and pmd_large(), but works regardless of config options
1355 */
1356#define pmd_is_leaf pmd_is_leaf
1357static inline bool pmd_is_leaf(pmd_t pmd)
1358{
1359 return !!(pmd_raw(pmd) & cpu_to_be64(_PAGE_PTE));
1360}
1361
1362#define pud_is_leaf pud_is_leaf
1363static inline bool pud_is_leaf(pud_t pud)
1364{
1365 return !!(pud_raw(pud) & cpu_to_be64(_PAGE_PTE));
1366}
1367
1368#define pgd_is_leaf pgd_is_leaf
1369static inline bool pgd_is_leaf(pgd_t pgd)
1370{
1371 return !!(pgd_raw(pgd) & cpu_to_be64(_PAGE_PTE));
1372}
1373
1353#endif /* __ASSEMBLY__ */ 1374#endif /* __ASSEMBLY__ */
1354#endif /* _ASM_POWERPC_BOOK3S_64_PGTABLE_H_ */ 1375#endif /* _ASM_POWERPC_BOOK3S_64_PGTABLE_H_ */
diff --git a/arch/powerpc/include/asm/pgtable.h b/arch/powerpc/include/asm/pgtable.h
index 3f53be60fb01..bf7d771f342e 100644
--- a/arch/powerpc/include/asm/pgtable.h
+++ b/arch/powerpc/include/asm/pgtable.h
@@ -140,6 +140,30 @@ static inline void pte_frag_set(mm_context_t *ctx, void *p)
140} 140}
141#endif 141#endif
142 142
143#ifndef pmd_is_leaf
144#define pmd_is_leaf pmd_is_leaf
145static inline bool pmd_is_leaf(pmd_t pmd)
146{
147 return false;
148}
149#endif
150
151#ifndef pud_is_leaf
152#define pud_is_leaf pud_is_leaf
153static inline bool pud_is_leaf(pud_t pud)
154{
155 return false;
156}
157#endif
158
159#ifndef pgd_is_leaf
160#define pgd_is_leaf pgd_is_leaf
161static inline bool pgd_is_leaf(pgd_t pgd)
162{
163 return false;
164}
165#endif
166
143#endif /* __ASSEMBLY__ */ 167#endif /* __ASSEMBLY__ */
144 168
145#endif /* _ASM_POWERPC_PGTABLE_H */ 169#endif /* _ASM_POWERPC_PGTABLE_H */
diff --git a/arch/powerpc/include/asm/pte-walk.h b/arch/powerpc/include/asm/pte-walk.h
index 2d633e9d686c..33fa5dd8ee6a 100644
--- a/arch/powerpc/include/asm/pte-walk.h
+++ b/arch/powerpc/include/asm/pte-walk.h
@@ -10,8 +10,20 @@ extern pte_t *__find_linux_pte(pgd_t *pgdir, unsigned long ea,
10static inline pte_t *find_linux_pte(pgd_t *pgdir, unsigned long ea, 10static inline pte_t *find_linux_pte(pgd_t *pgdir, unsigned long ea,
11 bool *is_thp, unsigned *hshift) 11 bool *is_thp, unsigned *hshift)
12{ 12{
13 pte_t *pte;
14
13 VM_WARN(!arch_irqs_disabled(), "%s called with irq enabled\n", __func__); 15 VM_WARN(!arch_irqs_disabled(), "%s called with irq enabled\n", __func__);
14 return __find_linux_pte(pgdir, ea, is_thp, hshift); 16 pte = __find_linux_pte(pgdir, ea, is_thp, hshift);
17
18#if defined(CONFIG_DEBUG_VM) && \
19 !(defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE))
20 /*
21 * We should not find huge page if these configs are not enabled.
22 */
23 if (hshift)
24 WARN_ON(*hshift);
25#endif
26 return pte;
15} 27}
16 28
17static inline pte_t *find_init_mm_pte(unsigned long ea, unsigned *hshift) 29static inline pte_t *find_init_mm_pte(unsigned long ea, unsigned *hshift)
@@ -26,10 +38,22 @@ static inline pte_t *find_init_mm_pte(unsigned long ea, unsigned *hshift)
26static inline pte_t *find_current_mm_pte(pgd_t *pgdir, unsigned long ea, 38static inline pte_t *find_current_mm_pte(pgd_t *pgdir, unsigned long ea,
27 bool *is_thp, unsigned *hshift) 39 bool *is_thp, unsigned *hshift)
28{ 40{
41 pte_t *pte;
42
29 VM_WARN(!arch_irqs_disabled(), "%s called with irq enabled\n", __func__); 43 VM_WARN(!arch_irqs_disabled(), "%s called with irq enabled\n", __func__);
30 VM_WARN(pgdir != current->mm->pgd, 44 VM_WARN(pgdir != current->mm->pgd,
31 "%s lock less page table lookup called on wrong mm\n", __func__); 45 "%s lock less page table lookup called on wrong mm\n", __func__);
32 return __find_linux_pte(pgdir, ea, is_thp, hshift); 46 pte = __find_linux_pte(pgdir, ea, is_thp, hshift);
47
48#if defined(CONFIG_DEBUG_VM) && \
49 !(defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE))
50 /*
51 * We should not find huge page if these configs are not enabled.
52 */
53 if (hshift)
54 WARN_ON(*hshift);
55#endif
56 return pte;
33} 57}
34 58
35#endif /* _ASM_POWERPC_PTE_WALK_H */ 59#endif /* _ASM_POWERPC_PTE_WALK_H */
diff --git a/arch/powerpc/kvm/book3s_64_mmu_radix.c b/arch/powerpc/kvm/book3s_64_mmu_radix.c
index f55ef071883f..91efee7f0329 100644
--- a/arch/powerpc/kvm/book3s_64_mmu_radix.c
+++ b/arch/powerpc/kvm/book3s_64_mmu_radix.c
@@ -363,12 +363,6 @@ static void kvmppc_pte_free(pte_t *ptep)
363 kmem_cache_free(kvm_pte_cache, ptep); 363 kmem_cache_free(kvm_pte_cache, ptep);
364} 364}
365 365
366/* Like pmd_huge() and pmd_large(), but works regardless of config options */
367static inline int pmd_is_leaf(pmd_t pmd)
368{
369 return !!(pmd_val(pmd) & _PAGE_PTE);
370}
371
372static pmd_t *kvmppc_pmd_alloc(void) 366static pmd_t *kvmppc_pmd_alloc(void)
373{ 367{
374 return kmem_cache_alloc(kvm_pmd_cache, GFP_KERNEL); 368 return kmem_cache_alloc(kvm_pmd_cache, GFP_KERNEL);
@@ -489,7 +483,7 @@ static void kvmppc_unmap_free_pud(struct kvm *kvm, pud_t *pud,
489 for (iu = 0; iu < PTRS_PER_PUD; ++iu, ++p) { 483 for (iu = 0; iu < PTRS_PER_PUD; ++iu, ++p) {
490 if (!pud_present(*p)) 484 if (!pud_present(*p))
491 continue; 485 continue;
492 if (pud_huge(*p)) { 486 if (pud_is_leaf(*p)) {
493 pud_clear(p); 487 pud_clear(p);
494 } else { 488 } else {
495 pmd_t *pmd; 489 pmd_t *pmd;
@@ -588,7 +582,7 @@ int kvmppc_create_pte(struct kvm *kvm, pgd_t *pgtable, pte_t pte,
588 new_pud = pud_alloc_one(kvm->mm, gpa); 582 new_pud = pud_alloc_one(kvm->mm, gpa);
589 583
590 pmd = NULL; 584 pmd = NULL;
591 if (pud && pud_present(*pud) && !pud_huge(*pud)) 585 if (pud && pud_present(*pud) && !pud_is_leaf(*pud))
592 pmd = pmd_offset(pud, gpa); 586 pmd = pmd_offset(pud, gpa);
593 else if (level <= 1) 587 else if (level <= 1)
594 new_pmd = kvmppc_pmd_alloc(); 588 new_pmd = kvmppc_pmd_alloc();
@@ -611,7 +605,7 @@ int kvmppc_create_pte(struct kvm *kvm, pgd_t *pgtable, pte_t pte,
611 new_pud = NULL; 605 new_pud = NULL;
612 } 606 }
613 pud = pud_offset(pgd, gpa); 607 pud = pud_offset(pgd, gpa);
614 if (pud_huge(*pud)) { 608 if (pud_is_leaf(*pud)) {
615 unsigned long hgpa = gpa & PUD_MASK; 609 unsigned long hgpa = gpa & PUD_MASK;
616 610
617 /* Check if we raced and someone else has set the same thing */ 611 /* Check if we raced and someone else has set the same thing */
diff --git a/arch/powerpc/mm/book3s64/radix_pgtable.c b/arch/powerpc/mm/book3s64/radix_pgtable.c
index b573fa024b32..e92c6472a20c 100644
--- a/arch/powerpc/mm/book3s64/radix_pgtable.c
+++ b/arch/powerpc/mm/book3s64/radix_pgtable.c
@@ -203,14 +203,14 @@ void radix__change_memory_range(unsigned long start, unsigned long end,
203 pudp = pud_alloc(&init_mm, pgdp, idx); 203 pudp = pud_alloc(&init_mm, pgdp, idx);
204 if (!pudp) 204 if (!pudp)
205 continue; 205 continue;
206 if (pud_huge(*pudp)) { 206 if (pud_is_leaf(*pudp)) {
207 ptep = (pte_t *)pudp; 207 ptep = (pte_t *)pudp;
208 goto update_the_pte; 208 goto update_the_pte;
209 } 209 }
210 pmdp = pmd_alloc(&init_mm, pudp, idx); 210 pmdp = pmd_alloc(&init_mm, pudp, idx);
211 if (!pmdp) 211 if (!pmdp)
212 continue; 212 continue;
213 if (pmd_huge(*pmdp)) { 213 if (pmd_is_leaf(*pmdp)) {
214 ptep = pmdp_ptep(pmdp); 214 ptep = pmdp_ptep(pmdp);
215 goto update_the_pte; 215 goto update_the_pte;
216 } 216 }
@@ -835,7 +835,7 @@ static void remove_pmd_table(pmd_t *pmd_start, unsigned long addr,
835 if (!pmd_present(*pmd)) 835 if (!pmd_present(*pmd))
836 continue; 836 continue;
837 837
838 if (pmd_huge(*pmd)) { 838 if (pmd_is_leaf(*pmd)) {
839 split_kernel_mapping(addr, end, PMD_SIZE, (pte_t *)pmd); 839 split_kernel_mapping(addr, end, PMD_SIZE, (pte_t *)pmd);
840 continue; 840 continue;
841 } 841 }
@@ -860,7 +860,7 @@ static void remove_pud_table(pud_t *pud_start, unsigned long addr,
860 if (!pud_present(*pud)) 860 if (!pud_present(*pud))
861 continue; 861 continue;
862 862
863 if (pud_huge(*pud)) { 863 if (pud_is_leaf(*pud)) {
864 split_kernel_mapping(addr, end, PUD_SIZE, (pte_t *)pud); 864 split_kernel_mapping(addr, end, PUD_SIZE, (pte_t *)pud);
865 continue; 865 continue;
866 } 866 }
@@ -886,7 +886,7 @@ static void __meminit remove_pagetable(unsigned long start, unsigned long end)
886 if (!pgd_present(*pgd)) 886 if (!pgd_present(*pgd))
887 continue; 887 continue;
888 888
889 if (pgd_huge(*pgd)) { 889 if (pgd_is_leaf(*pgd)) {
890 split_kernel_mapping(addr, end, PGDIR_SIZE, (pte_t *)pgd); 890 split_kernel_mapping(addr, end, PGDIR_SIZE, (pte_t *)pgd);
891 continue; 891 continue;
892 } 892 }
diff --git a/arch/powerpc/mm/pgtable.c b/arch/powerpc/mm/pgtable.c
index 533fc6fa6726..2029e585e5c3 100644
--- a/arch/powerpc/mm/pgtable.c
+++ b/arch/powerpc/mm/pgtable.c
@@ -340,10 +340,11 @@ pte_t *__find_linux_pte(pgd_t *pgdir, unsigned long ea,
340 if (pgd_none(pgd)) 340 if (pgd_none(pgd))
341 return NULL; 341 return NULL;
342 342
343 if (pgd_huge(pgd)) { 343 if (pgd_is_leaf(pgd)) {
344 ret_pte = (pte_t *)pgdp; 344 ret_pte = (pte_t *)pgdp;
345 goto out; 345 goto out;
346 } 346 }
347
347 if (is_hugepd(__hugepd(pgd_val(pgd)))) { 348 if (is_hugepd(__hugepd(pgd_val(pgd)))) {
348 hpdp = (hugepd_t *)&pgd; 349 hpdp = (hugepd_t *)&pgd;
349 goto out_huge; 350 goto out_huge;
@@ -361,14 +362,16 @@ pte_t *__find_linux_pte(pgd_t *pgdir, unsigned long ea,
361 if (pud_none(pud)) 362 if (pud_none(pud))
362 return NULL; 363 return NULL;
363 364
364 if (pud_huge(pud)) { 365 if (pud_is_leaf(pud)) {
365 ret_pte = (pte_t *)pudp; 366 ret_pte = (pte_t *)pudp;
366 goto out; 367 goto out;
367 } 368 }
369
368 if (is_hugepd(__hugepd(pud_val(pud)))) { 370 if (is_hugepd(__hugepd(pud_val(pud)))) {
369 hpdp = (hugepd_t *)&pud; 371 hpdp = (hugepd_t *)&pud;
370 goto out_huge; 372 goto out_huge;
371 } 373 }
374
372 pdshift = PMD_SHIFT; 375 pdshift = PMD_SHIFT;
373 pmdp = pmd_offset(&pud, ea); 376 pmdp = pmd_offset(&pud, ea);
374 pmd = READ_ONCE(*pmdp); 377 pmd = READ_ONCE(*pmdp);
@@ -397,15 +400,12 @@ pte_t *__find_linux_pte(pgd_t *pgdir, unsigned long ea,
397 ret_pte = (pte_t *)pmdp; 400 ret_pte = (pte_t *)pmdp;
398 goto out; 401 goto out;
399 } 402 }
400 /* 403
401 * pmd_large check below will handle the swap pmd pte 404 if (pmd_is_leaf(pmd)) {
402 * we need to do both the check because they are config
403 * dependent.
404 */
405 if (pmd_huge(pmd) || pmd_large(pmd)) {
406 ret_pte = (pte_t *)pmdp; 405 ret_pte = (pte_t *)pmdp;
407 goto out; 406 goto out;
408 } 407 }
408
409 if (is_hugepd(__hugepd(pmd_val(pmd)))) { 409 if (is_hugepd(__hugepd(pmd_val(pmd)))) {
410 hpdp = (hugepd_t *)&pmd; 410 hpdp = (hugepd_t *)&pmd;
411 goto out_huge; 411 goto out_huge;
diff --git a/arch/powerpc/mm/pgtable_64.c b/arch/powerpc/mm/pgtable_64.c
index 63cd81130643..2892246a6fef 100644
--- a/arch/powerpc/mm/pgtable_64.c
+++ b/arch/powerpc/mm/pgtable_64.c
@@ -309,16 +309,20 @@ EXPORT_SYMBOL(__iounmap_at);
309/* 4 level page table */ 309/* 4 level page table */
310struct page *pgd_page(pgd_t pgd) 310struct page *pgd_page(pgd_t pgd)
311{ 311{
312 if (pgd_huge(pgd)) 312 if (pgd_is_leaf(pgd)) {
313 VM_WARN_ON(!pgd_huge(pgd));
313 return pte_page(pgd_pte(pgd)); 314 return pte_page(pgd_pte(pgd));
315 }
314 return virt_to_page(pgd_page_vaddr(pgd)); 316 return virt_to_page(pgd_page_vaddr(pgd));
315} 317}
316#endif 318#endif
317 319
318struct page *pud_page(pud_t pud) 320struct page *pud_page(pud_t pud)
319{ 321{
320 if (pud_huge(pud)) 322 if (pud_is_leaf(pud)) {
323 VM_WARN_ON(!pud_huge(pud));
321 return pte_page(pud_pte(pud)); 324 return pte_page(pud_pte(pud));
325 }
322 return virt_to_page(pud_page_vaddr(pud)); 326 return virt_to_page(pud_page_vaddr(pud));
323} 327}
324 328
@@ -328,8 +332,10 @@ struct page *pud_page(pud_t pud)
328 */ 332 */
329struct page *pmd_page(pmd_t pmd) 333struct page *pmd_page(pmd_t pmd)
330{ 334{
331 if (pmd_large(pmd) || pmd_huge(pmd) || pmd_devmap(pmd)) 335 if (pmd_is_leaf(pmd)) {
336 VM_WARN_ON(!(pmd_large(pmd) || pmd_huge(pmd) || pmd_devmap(pmd)));
332 return pte_page(pmd_pte(pmd)); 337 return pte_page(pmd_pte(pmd));
338 }
333 return virt_to_page(pmd_page_vaddr(pmd)); 339 return virt_to_page(pmd_page_vaddr(pmd));
334} 340}
335 341
diff --git a/arch/powerpc/mm/ptdump/ptdump.c b/arch/powerpc/mm/ptdump/ptdump.c
index 646876d9da64..abe60d25b4e6 100644
--- a/arch/powerpc/mm/ptdump/ptdump.c
+++ b/arch/powerpc/mm/ptdump/ptdump.c
@@ -277,7 +277,7 @@ static void walk_pmd(struct pg_state *st, pud_t *pud, unsigned long start)
277 277
278 for (i = 0; i < PTRS_PER_PMD; i++, pmd++) { 278 for (i = 0; i < PTRS_PER_PMD; i++, pmd++) {
279 addr = start + i * PMD_SIZE; 279 addr = start + i * PMD_SIZE;
280 if (!pmd_none(*pmd) && !pmd_huge(*pmd)) 280 if (!pmd_none(*pmd) && !pmd_is_leaf(*pmd))
281 /* pmd exists */ 281 /* pmd exists */
282 walk_pte(st, pmd, addr); 282 walk_pte(st, pmd, addr);
283 else 283 else
@@ -293,7 +293,7 @@ static void walk_pud(struct pg_state *st, pgd_t *pgd, unsigned long start)
293 293
294 for (i = 0; i < PTRS_PER_PUD; i++, pud++) { 294 for (i = 0; i < PTRS_PER_PUD; i++, pud++) {
295 addr = start + i * PUD_SIZE; 295 addr = start + i * PUD_SIZE;
296 if (!pud_none(*pud) && !pud_huge(*pud)) 296 if (!pud_none(*pud) && !pud_is_leaf(*pud))
297 /* pud exists */ 297 /* pud exists */
298 walk_pmd(st, pud, addr); 298 walk_pmd(st, pud, addr);
299 else 299 else
@@ -314,7 +314,7 @@ static void walk_pagetables(struct pg_state *st)
314 * the hash pagetable. 314 * the hash pagetable.
315 */ 315 */
316 for (i = 0; i < PTRS_PER_PGD; i++, pgd++, addr += PGDIR_SIZE) { 316 for (i = 0; i < PTRS_PER_PGD; i++, pgd++, addr += PGDIR_SIZE) {
317 if (!pgd_none(*pgd) && !pgd_huge(*pgd)) 317 if (!pgd_none(*pgd) && !pgd_is_leaf(*pgd))
318 /* pgd exists */ 318 /* pgd exists */
319 walk_pud(st, pgd, addr); 319 walk_pud(st, pgd, addr);
320 else 320 else
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index f879e9fe9733..2ec20a5bb556 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -3098,7 +3098,7 @@ static void show_pte(unsigned long addr)
3098 3098
3099 printf("pgd @ 0x%px\n", pgdir); 3099 printf("pgd @ 0x%px\n", pgdir);
3100 3100
3101 if (pgd_huge(*pgdp)) { 3101 if (pgd_is_leaf(*pgdp)) {
3102 format_pte(pgdp, pgd_val(*pgdp)); 3102 format_pte(pgdp, pgd_val(*pgdp));
3103 return; 3103 return;
3104 } 3104 }
@@ -3111,7 +3111,7 @@ static void show_pte(unsigned long addr)
3111 return; 3111 return;
3112 } 3112 }
3113 3113
3114 if (pud_huge(*pudp)) { 3114 if (pud_is_leaf(*pudp)) {
3115 format_pte(pudp, pud_val(*pudp)); 3115 format_pte(pudp, pud_val(*pudp));
3116 return; 3116 return;
3117 } 3117 }
@@ -3125,7 +3125,7 @@ static void show_pte(unsigned long addr)
3125 return; 3125 return;
3126 } 3126 }
3127 3127
3128 if (pmd_huge(*pmdp)) { 3128 if (pmd_is_leaf(*pmdp)) {
3129 format_pte(pmdp, pmd_val(*pmdp)); 3129 format_pte(pmdp, pmd_val(*pmdp));
3130 return; 3130 return;
3131 } 3131 }