diff options
Diffstat (limited to 'arch/powerpc/mm/hash_utils_64.c')
-rw-r--r-- | arch/powerpc/mm/hash_utils_64.c | 46 |
1 files changed, 20 insertions, 26 deletions
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c index 1ade7eb6ae00..50f867d657df 100644 --- a/arch/powerpc/mm/hash_utils_64.c +++ b/arch/powerpc/mm/hash_utils_64.c | |||
@@ -92,6 +92,7 @@ struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT]; | |||
92 | struct hash_pte *htab_address; | 92 | struct hash_pte *htab_address; |
93 | unsigned long htab_size_bytes; | 93 | unsigned long htab_size_bytes; |
94 | unsigned long htab_hash_mask; | 94 | unsigned long htab_hash_mask; |
95 | EXPORT_SYMBOL_GPL(htab_hash_mask); | ||
95 | int mmu_linear_psize = MMU_PAGE_4K; | 96 | int mmu_linear_psize = MMU_PAGE_4K; |
96 | int mmu_virtual_psize = MMU_PAGE_4K; | 97 | int mmu_virtual_psize = MMU_PAGE_4K; |
97 | int mmu_vmalloc_psize = MMU_PAGE_4K; | 98 | int mmu_vmalloc_psize = MMU_PAGE_4K; |
@@ -102,6 +103,7 @@ int mmu_io_psize = MMU_PAGE_4K; | |||
102 | int mmu_kernel_ssize = MMU_SEGSIZE_256M; | 103 | int mmu_kernel_ssize = MMU_SEGSIZE_256M; |
103 | int mmu_highuser_ssize = MMU_SEGSIZE_256M; | 104 | int mmu_highuser_ssize = MMU_SEGSIZE_256M; |
104 | u16 mmu_slb_size = 64; | 105 | u16 mmu_slb_size = 64; |
106 | EXPORT_SYMBOL_GPL(mmu_slb_size); | ||
105 | #ifdef CONFIG_HUGETLB_PAGE | 107 | #ifdef CONFIG_HUGETLB_PAGE |
106 | unsigned int HPAGE_SHIFT; | 108 | unsigned int HPAGE_SHIFT; |
107 | #endif | 109 | #endif |
@@ -481,16 +483,6 @@ static void __init htab_init_page_sizes(void) | |||
481 | #ifdef CONFIG_HUGETLB_PAGE | 483 | #ifdef CONFIG_HUGETLB_PAGE |
482 | /* Reserve 16G huge page memory sections for huge pages */ | 484 | /* Reserve 16G huge page memory sections for huge pages */ |
483 | of_scan_flat_dt(htab_dt_scan_hugepage_blocks, NULL); | 485 | of_scan_flat_dt(htab_dt_scan_hugepage_blocks, NULL); |
484 | |||
485 | /* Set default large page size. Currently, we pick 16M or 1M depending | ||
486 | * on what is available | ||
487 | */ | ||
488 | if (mmu_psize_defs[MMU_PAGE_16M].shift) | ||
489 | HPAGE_SHIFT = mmu_psize_defs[MMU_PAGE_16M].shift; | ||
490 | /* With 4k/4level pagetables, we can't (for now) cope with a | ||
491 | * huge page size < PMD_SIZE */ | ||
492 | else if (mmu_psize_defs[MMU_PAGE_1M].shift) | ||
493 | HPAGE_SHIFT = mmu_psize_defs[MMU_PAGE_1M].shift; | ||
494 | #endif /* CONFIG_HUGETLB_PAGE */ | 486 | #endif /* CONFIG_HUGETLB_PAGE */ |
495 | } | 487 | } |
496 | 488 | ||
@@ -785,7 +777,7 @@ unsigned int hash_page_do_lazy_icache(unsigned int pp, pte_t pte, int trap) | |||
785 | /* page is dirty */ | 777 | /* page is dirty */ |
786 | if (!test_bit(PG_arch_1, &page->flags) && !PageReserved(page)) { | 778 | if (!test_bit(PG_arch_1, &page->flags) && !PageReserved(page)) { |
787 | if (trap == 0x400) { | 779 | if (trap == 0x400) { |
788 | __flush_dcache_icache(page_address(page)); | 780 | flush_dcache_icache_page(page); |
789 | set_bit(PG_arch_1, &page->flags); | 781 | set_bit(PG_arch_1, &page->flags); |
790 | } else | 782 | } else |
791 | pp |= HPTE_R_N; | 783 | pp |= HPTE_R_N; |
@@ -843,9 +835,9 @@ void demote_segment_4k(struct mm_struct *mm, unsigned long addr) | |||
843 | * Result is 0: full permissions, _PAGE_RW: read-only, | 835 | * Result is 0: full permissions, _PAGE_RW: read-only, |
844 | * _PAGE_USER or _PAGE_USER|_PAGE_RW: no access. | 836 | * _PAGE_USER or _PAGE_USER|_PAGE_RW: no access. |
845 | */ | 837 | */ |
846 | static int subpage_protection(pgd_t *pgdir, unsigned long ea) | 838 | static int subpage_protection(struct mm_struct *mm, unsigned long ea) |
847 | { | 839 | { |
848 | struct subpage_prot_table *spt = pgd_subpage_prot(pgdir); | 840 | struct subpage_prot_table *spt = &mm->context.spt; |
849 | u32 spp = 0; | 841 | u32 spp = 0; |
850 | u32 **sbpm, *sbpp; | 842 | u32 **sbpm, *sbpp; |
851 | 843 | ||
@@ -873,7 +865,7 @@ static int subpage_protection(pgd_t *pgdir, unsigned long ea) | |||
873 | } | 865 | } |
874 | 866 | ||
875 | #else /* CONFIG_PPC_SUBPAGE_PROT */ | 867 | #else /* CONFIG_PPC_SUBPAGE_PROT */ |
876 | static inline int subpage_protection(pgd_t *pgdir, unsigned long ea) | 868 | static inline int subpage_protection(struct mm_struct *mm, unsigned long ea) |
877 | { | 869 | { |
878 | return 0; | 870 | return 0; |
879 | } | 871 | } |
@@ -891,6 +883,7 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap) | |||
891 | unsigned long vsid; | 883 | unsigned long vsid; |
892 | struct mm_struct *mm; | 884 | struct mm_struct *mm; |
893 | pte_t *ptep; | 885 | pte_t *ptep; |
886 | unsigned hugeshift; | ||
894 | const struct cpumask *tmp; | 887 | const struct cpumask *tmp; |
895 | int rc, user_region = 0, local = 0; | 888 | int rc, user_region = 0, local = 0; |
896 | int psize, ssize; | 889 | int psize, ssize; |
@@ -943,30 +936,31 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap) | |||
943 | if (user_region && cpumask_equal(mm_cpumask(mm), tmp)) | 936 | if (user_region && cpumask_equal(mm_cpumask(mm), tmp)) |
944 | local = 1; | 937 | local = 1; |
945 | 938 | ||
946 | #ifdef CONFIG_HUGETLB_PAGE | ||
947 | /* Handle hugepage regions */ | ||
948 | if (HPAGE_SHIFT && mmu_huge_psizes[psize]) { | ||
949 | DBG_LOW(" -> huge page !\n"); | ||
950 | return hash_huge_page(mm, access, ea, vsid, local, trap); | ||
951 | } | ||
952 | #endif /* CONFIG_HUGETLB_PAGE */ | ||
953 | |||
954 | #ifndef CONFIG_PPC_64K_PAGES | 939 | #ifndef CONFIG_PPC_64K_PAGES |
955 | /* If we use 4K pages and our psize is not 4K, then we are hitting | 940 | /* If we use 4K pages and our psize is not 4K, then we might |
956 | * a special driver mapping, we need to align the address before | 941 | * be hitting a special driver mapping, and need to align the |
957 | * we fetch the PTE | 942 | * address before we fetch the PTE. |
943 | * | ||
944 | * It could also be a hugepage mapping, in which case this is | ||
945 | * not necessary, but it's not harmful, either. | ||
958 | */ | 946 | */ |
959 | if (psize != MMU_PAGE_4K) | 947 | if (psize != MMU_PAGE_4K) |
960 | ea &= ~((1ul << mmu_psize_defs[psize].shift) - 1); | 948 | ea &= ~((1ul << mmu_psize_defs[psize].shift) - 1); |
961 | #endif /* CONFIG_PPC_64K_PAGES */ | 949 | #endif /* CONFIG_PPC_64K_PAGES */ |
962 | 950 | ||
963 | /* Get PTE and page size from page tables */ | 951 | /* Get PTE and page size from page tables */ |
964 | ptep = find_linux_pte(pgdir, ea); | 952 | ptep = find_linux_pte_or_hugepte(pgdir, ea, &hugeshift); |
965 | if (ptep == NULL || !pte_present(*ptep)) { | 953 | if (ptep == NULL || !pte_present(*ptep)) { |
966 | DBG_LOW(" no PTE !\n"); | 954 | DBG_LOW(" no PTE !\n"); |
967 | return 1; | 955 | return 1; |
968 | } | 956 | } |
969 | 957 | ||
958 | #ifdef CONFIG_HUGETLB_PAGE | ||
959 | if (hugeshift) | ||
960 | return __hash_page_huge(ea, access, vsid, ptep, trap, local, | ||
961 | ssize, hugeshift, psize); | ||
962 | #endif /* CONFIG_HUGETLB_PAGE */ | ||
963 | |||
970 | #ifndef CONFIG_PPC_64K_PAGES | 964 | #ifndef CONFIG_PPC_64K_PAGES |
971 | DBG_LOW(" i-pte: %016lx\n", pte_val(*ptep)); | 965 | DBG_LOW(" i-pte: %016lx\n", pte_val(*ptep)); |
972 | #else | 966 | #else |