diff options
-rw-r--r-- | arch/powerpc/mm/hash_low_64.S | 5 | ||||
-rw-r--r-- | arch/powerpc/mm/hash_utils_64.c | 43 | ||||
-rw-r--r-- | include/asm-powerpc/pgtable-4k.h | 3 | ||||
-rw-r--r-- | include/asm-powerpc/pgtable-64k.h | 5 |
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 | ||
446 | htab_insert_pte: | 446 | htab_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 |
453 | htab_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 | */ | ||
580 | void 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 | |||
595 | EXPORT_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 */ |