aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/mm/hash_low_64.S5
-rw-r--r--arch/powerpc/mm/hash_utils_64.c43
-rw-r--r--include/asm-powerpc/pgtable-4k.h3
-rw-r--r--include/asm-powerpc/pgtable-64k.h5
4 files changed, 42 insertions, 14 deletions
diff --git a/arch/powerpc/mm/hash_low_64.S b/arch/powerpc/mm/hash_low_64.S
index 9bc0a9c2b9bc..e64ce3eec36e 100644
--- a/arch/powerpc/mm/hash_low_64.S
+++ b/arch/powerpc/mm/hash_low_64.S
@@ -445,9 +445,12 @@ END_FTR_SECTION(CPU_FTR_NOEXECUTE|CPU_FTR_COHERENT_ICACHE, CPU_FTR_NOEXECUTE)
445 445
446htab_insert_pte: 446htab_insert_pte:
447 /* real page number in r5, PTE RPN value + index */ 447 /* real page number in r5, PTE RPN value + index */
448 rldicl r5,r31,64-PTE_RPN_SHIFT,PTE_RPN_SHIFT 448 andis. r0,r31,_PAGE_4K_PFN@h
449 srdi r5,r31,PTE_RPN_SHIFT
450 bne- htab_special_pfn
449 sldi r5,r5,PAGE_SHIFT-HW_PAGE_SHIFT 451 sldi r5,r5,PAGE_SHIFT-HW_PAGE_SHIFT
450 add r5,r5,r25 452 add r5,r5,r25
453htab_special_pfn:
451 sldi r5,r5,HW_PAGE_SHIFT 454 sldi r5,r5,HW_PAGE_SHIFT
452 455
453 /* Calculate primary group hash */ 456 /* Calculate primary group hash */
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c
index 3c7fe2c65b5a..aae085317018 100644
--- a/arch/powerpc/mm/hash_utils_64.c
+++ b/arch/powerpc/mm/hash_utils_64.c
@@ -573,6 +573,27 @@ unsigned int hash_page_do_lazy_icache(unsigned int pp, pte_t pte, int trap)
573 return pp; 573 return pp;
574} 574}
575 575
576/*
577 * Demote a segment to using 4k pages.
578 * For now this makes the whole process use 4k pages.
579 */
580void demote_segment_4k(struct mm_struct *mm, unsigned long addr)
581{
582#ifdef CONFIG_PPC_64K_PAGES
583 if (mm->context.user_psize == MMU_PAGE_4K)
584 return;
585 mm->context.user_psize = MMU_PAGE_4K;
586 mm->context.sllp = SLB_VSID_USER | mmu_psize_defs[MMU_PAGE_4K].sllp;
587 get_paca()->context = mm->context;
588 slb_flush_and_rebolt();
589#ifdef CONFIG_SPE_BASE
590 spu_flush_all_slbs(mm);
591#endif
592#endif
593}
594
595EXPORT_SYMBOL_GPL(demote_segment_4k);
596
576/* Result code is: 597/* Result code is:
577 * 0 - handled 598 * 0 - handled
578 * 1 - normal page fault 599 * 1 - normal page fault
@@ -665,15 +686,19 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap)
665#ifndef CONFIG_PPC_64K_PAGES 686#ifndef CONFIG_PPC_64K_PAGES
666 rc = __hash_page_4K(ea, access, vsid, ptep, trap, local); 687 rc = __hash_page_4K(ea, access, vsid, ptep, trap, local);
667#else 688#else
689 /* If _PAGE_4K_PFN is set, make sure this is a 4k segment */
690 if (pte_val(*ptep) & _PAGE_4K_PFN) {
691 demote_segment_4k(mm, ea);
692 psize = MMU_PAGE_4K;
693 }
694
668 if (mmu_ci_restrictions) { 695 if (mmu_ci_restrictions) {
669 /* If this PTE is non-cacheable, switch to 4k */ 696 /* If this PTE is non-cacheable, switch to 4k */
670 if (psize == MMU_PAGE_64K && 697 if (psize == MMU_PAGE_64K &&
671 (pte_val(*ptep) & _PAGE_NO_CACHE)) { 698 (pte_val(*ptep) & _PAGE_NO_CACHE)) {
672 if (user_region) { 699 if (user_region) {
700 demote_segment_4k(mm, ea);
673 psize = MMU_PAGE_4K; 701 psize = MMU_PAGE_4K;
674 mm->context.user_psize = MMU_PAGE_4K;
675 mm->context.sllp = SLB_VSID_USER |
676 mmu_psize_defs[MMU_PAGE_4K].sllp;
677 } else if (ea < VMALLOC_END) { 702 } else if (ea < VMALLOC_END) {
678 /* 703 /*
679 * some driver did a non-cacheable mapping 704 * some driver did a non-cacheable mapping
@@ -756,16 +781,8 @@ void hash_preload(struct mm_struct *mm, unsigned long ea,
756 if (mmu_ci_restrictions) { 781 if (mmu_ci_restrictions) {
757 /* If this PTE is non-cacheable, switch to 4k */ 782 /* If this PTE is non-cacheable, switch to 4k */
758 if (mm->context.user_psize == MMU_PAGE_64K && 783 if (mm->context.user_psize == MMU_PAGE_64K &&
759 (pte_val(*ptep) & _PAGE_NO_CACHE)) { 784 (pte_val(*ptep) & _PAGE_NO_CACHE))
760 mm->context.user_psize = MMU_PAGE_4K; 785 demote_segment_4k(mm, ea);
761 mm->context.sllp = SLB_VSID_USER |
762 mmu_psize_defs[MMU_PAGE_4K].sllp;
763 get_paca()->context = mm->context;
764 slb_flush_and_rebolt();
765#ifdef CONFIG_SPE_BASE
766 spu_flush_all_slbs(mm);
767#endif
768 }
769 } 786 }
770 if (mm->context.user_psize == MMU_PAGE_64K) 787 if (mm->context.user_psize == MMU_PAGE_64K)
771 __hash_page_64K(ea, access, vsid, ptep, trap, local); 788 __hash_page_64K(ea, access, vsid, ptep, trap, local);
diff --git a/include/asm-powerpc/pgtable-4k.h b/include/asm-powerpc/pgtable-4k.h
index 345d9b07b3e2..a28fa8bc01da 100644
--- a/include/asm-powerpc/pgtable-4k.h
+++ b/include/asm-powerpc/pgtable-4k.h
@@ -97,3 +97,6 @@
97 97
98#define pud_ERROR(e) \ 98#define pud_ERROR(e) \
99 printk("%s:%d: bad pud %08lx.\n", __FILE__, __LINE__, pud_val(e)) 99 printk("%s:%d: bad pud %08lx.\n", __FILE__, __LINE__, pud_val(e))
100
101#define remap_4k_pfn(vma, addr, pfn, prot) \
102 remap_pfn_range((vma), (addr), (pfn), PAGE_SIZE, (prot))
diff --git a/include/asm-powerpc/pgtable-64k.h b/include/asm-powerpc/pgtable-64k.h
index 4b7126c53f37..5e84f070eaf7 100644
--- a/include/asm-powerpc/pgtable-64k.h
+++ b/include/asm-powerpc/pgtable-64k.h
@@ -35,6 +35,7 @@
35#define _PAGE_HPTE_SUB 0x0ffff000 /* combo only: sub pages HPTE bits */ 35#define _PAGE_HPTE_SUB 0x0ffff000 /* combo only: sub pages HPTE bits */
36#define _PAGE_HPTE_SUB0 0x08000000 /* combo only: first sub page */ 36#define _PAGE_HPTE_SUB0 0x08000000 /* combo only: first sub page */
37#define _PAGE_COMBO 0x10000000 /* this is a combo 4k page */ 37#define _PAGE_COMBO 0x10000000 /* this is a combo 4k page */
38#define _PAGE_4K_PFN 0x20000000 /* PFN is for a single 4k page */
38#define _PAGE_F_SECOND 0x00008000 /* full page: hidx bits */ 39#define _PAGE_F_SECOND 0x00008000 /* full page: hidx bits */
39#define _PAGE_F_GIX 0x00007000 /* full page: hidx bits */ 40#define _PAGE_F_GIX 0x00007000 /* full page: hidx bits */
40 41
@@ -93,6 +94,10 @@
93#define pte_pagesize_index(pte) \ 94#define pte_pagesize_index(pte) \
94 (((pte) & _PAGE_COMBO)? MMU_PAGE_4K: MMU_PAGE_64K) 95 (((pte) & _PAGE_COMBO)? MMU_PAGE_4K: MMU_PAGE_64K)
95 96
97#define remap_4k_pfn(vma, addr, pfn, prot) \
98 remap_pfn_range((vma), (addr), (pfn), PAGE_SIZE, \
99 __pgprot(pgprot_val((prot)) | _PAGE_4K_PFN))
100
96#endif /* __ASSEMBLY__ */ 101#endif /* __ASSEMBLY__ */
97#endif /* __KERNEL__ */ 102#endif /* __KERNEL__ */
98#endif /* _ASM_POWERPC_PGTABLE_64K_H */ 103#endif /* _ASM_POWERPC_PGTABLE_64K_H */