aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/mm/hash_utils_64.c27
-rw-r--r--arch/powerpc/mm/hugepage-hash64.c3
-rw-r--r--arch/powerpc/mm/hugetlbpage.c72
-rw-r--r--arch/powerpc/mm/mem.c4
4 files changed, 68 insertions, 38 deletions
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c
index 7a81e866e7b1..845231643987 100644
--- a/arch/powerpc/mm/hash_utils_64.c
+++ b/arch/powerpc/mm/hash_utils_64.c
@@ -1180,13 +1180,25 @@ void hash_preload(struct mm_struct *mm, unsigned long ea,
1180 pgdir = mm->pgd; 1180 pgdir = mm->pgd;
1181 if (pgdir == NULL) 1181 if (pgdir == NULL)
1182 return; 1182 return;
1183
1184 /* Get VSID */
1185 ssize = user_segment_size(ea);
1186 vsid = get_vsid(mm->context.id, ea, ssize);
1187 if (!vsid)
1188 return;
1189 /*
1190 * Hash doesn't like irqs. Walking linux page table with irq disabled
1191 * saves us from holding multiple locks.
1192 */
1193 local_irq_save(flags);
1194
1183 /* 1195 /*
1184 * THP pages use update_mmu_cache_pmd. We don't do 1196 * THP pages use update_mmu_cache_pmd. We don't do
1185 * hash preload there. Hence can ignore THP here 1197 * hash preload there. Hence can ignore THP here
1186 */ 1198 */
1187 ptep = find_linux_pte_or_hugepte(pgdir, ea, &hugepage_shift); 1199 ptep = find_linux_pte_or_hugepte(pgdir, ea, &hugepage_shift);
1188 if (!ptep) 1200 if (!ptep)
1189 return; 1201 goto out_exit;
1190 1202
1191 WARN_ON(hugepage_shift); 1203 WARN_ON(hugepage_shift);
1192#ifdef CONFIG_PPC_64K_PAGES 1204#ifdef CONFIG_PPC_64K_PAGES
@@ -1197,18 +1209,9 @@ void hash_preload(struct mm_struct *mm, unsigned long ea,
1197 * page size demotion here 1209 * page size demotion here
1198 */ 1210 */
1199 if (pte_val(*ptep) & (_PAGE_4K_PFN | _PAGE_NO_CACHE)) 1211 if (pte_val(*ptep) & (_PAGE_4K_PFN | _PAGE_NO_CACHE))
1200 return; 1212 goto out_exit;
1201#endif /* CONFIG_PPC_64K_PAGES */ 1213#endif /* CONFIG_PPC_64K_PAGES */
1202 1214
1203 /* Get VSID */
1204 ssize = user_segment_size(ea);
1205 vsid = get_vsid(mm->context.id, ea, ssize);
1206 if (!vsid)
1207 return;
1208
1209 /* Hash doesn't like irqs */
1210 local_irq_save(flags);
1211
1212 /* Is that local to this CPU ? */ 1215 /* Is that local to this CPU ? */
1213 if (cpumask_equal(mm_cpumask(mm), cpumask_of(smp_processor_id()))) 1216 if (cpumask_equal(mm_cpumask(mm), cpumask_of(smp_processor_id())))
1214 local = 1; 1217 local = 1;
@@ -1230,7 +1233,7 @@ void hash_preload(struct mm_struct *mm, unsigned long ea,
1230 mm->context.user_psize, 1233 mm->context.user_psize,
1231 mm->context.user_psize, 1234 mm->context.user_psize,
1232 pte_val(*ptep)); 1235 pte_val(*ptep));
1233 1236out_exit:
1234 local_irq_restore(flags); 1237 local_irq_restore(flags);
1235} 1238}
1236 1239
diff --git a/arch/powerpc/mm/hugepage-hash64.c b/arch/powerpc/mm/hugepage-hash64.c
index 3c22fa307b9b..34de9e0cdc34 100644
--- a/arch/powerpc/mm/hugepage-hash64.c
+++ b/arch/powerpc/mm/hugepage-hash64.c
@@ -37,6 +37,9 @@ int __hash_page_thp(unsigned long ea, unsigned long access, unsigned long vsid,
37 /* If PMD busy, retry the access */ 37 /* If PMD busy, retry the access */
38 if (unlikely(old_pmd & _PAGE_BUSY)) 38 if (unlikely(old_pmd & _PAGE_BUSY))
39 return 0; 39 return 0;
40 /* If PMD is trans splitting retry the access */
41 if (unlikely(old_pmd & _PAGE_SPLITTING))
42 return 0;
40 /* If PMD permissions don't match, take page fault */ 43 /* If PMD permissions don't match, take page fault */
41 if (unlikely(access & ~old_pmd)) 44 if (unlikely(access & ~old_pmd))
42 return 1; 45 return 1;
diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c
index 8add58061003..e9e6882231da 100644
--- a/arch/powerpc/mm/hugetlbpage.c
+++ b/arch/powerpc/mm/hugetlbpage.c
@@ -925,12 +925,16 @@ void flush_dcache_icache_hugepage(struct page *page)
925 * (2) pointer to next table, as normal; bottom 6 bits == 0 925 * (2) pointer to next table, as normal; bottom 6 bits == 0
926 * (3) leaf pte for huge page, bottom two bits != 00 926 * (3) leaf pte for huge page, bottom two bits != 00
927 * (4) hugepd pointer, bottom two bits == 00, next 4 bits indicate size of table 927 * (4) hugepd pointer, bottom two bits == 00, next 4 bits indicate size of table
928 *
929 * So long as we atomically load page table pointers we are safe against teardown,
930 * we can follow the address down to the the page and take a ref on it.
928 */ 931 */
932
929pte_t *find_linux_pte_or_hugepte(pgd_t *pgdir, unsigned long ea, unsigned *shift) 933pte_t *find_linux_pte_or_hugepte(pgd_t *pgdir, unsigned long ea, unsigned *shift)
930{ 934{
931 pgd_t *pg; 935 pgd_t pgd, *pgdp;
932 pud_t *pu; 936 pud_t pud, *pudp;
933 pmd_t *pm; 937 pmd_t pmd, *pmdp;
934 pte_t *ret_pte; 938 pte_t *ret_pte;
935 hugepd_t *hpdp = NULL; 939 hugepd_t *hpdp = NULL;
936 unsigned pdshift = PGDIR_SHIFT; 940 unsigned pdshift = PGDIR_SHIFT;
@@ -938,34 +942,42 @@ pte_t *find_linux_pte_or_hugepte(pgd_t *pgdir, unsigned long ea, unsigned *shift
938 if (shift) 942 if (shift)
939 *shift = 0; 943 *shift = 0;
940 944
941 pg = pgdir + pgd_index(ea); 945 pgdp = pgdir + pgd_index(ea);
942 946 pgd = ACCESS_ONCE(*pgdp);
943 /* 947 /*
944 * we should first check for none. That takes care of a 948 * Always operate on the local stack value. This make sure the
945 * a parallel hugetlb or THP pagefault moving none entries 949 * value don't get updated by a parallel THP split/collapse,
946 * to respective types. 950 * page fault or a page unmap. The return pte_t * is still not
951 * stable. So should be checked there for above conditions.
947 */ 952 */
948 if (pgd_none(*pg)) 953 if (pgd_none(pgd))
949 return NULL; 954 return NULL;
950 else if (pgd_huge(*pg)) { 955 else if (pgd_huge(pgd)) {
951 ret_pte = (pte_t *) pg; 956 ret_pte = (pte_t *) pgdp;
952 goto out; 957 goto out;
953 } else if (is_hugepd(pg)) 958 } else if (is_hugepd(&pgd))
954 hpdp = (hugepd_t *)pg; 959 hpdp = (hugepd_t *)&pgd;
955 else { 960 else {
961 /*
962 * Even if we end up with an unmap, the pgtable will not
963 * be freed, because we do an rcu free and here we are
964 * irq disabled
965 */
956 pdshift = PUD_SHIFT; 966 pdshift = PUD_SHIFT;
957 pu = pud_offset(pg, ea); 967 pudp = pud_offset(&pgd, ea);
968 pud = ACCESS_ONCE(*pudp);
958 969
959 if (pud_none(*pu)) 970 if (pud_none(pud))
960 return NULL; 971 return NULL;
961 else if (pud_huge(*pu)) { 972 else if (pud_huge(pud)) {
962 ret_pte = (pte_t *) pu; 973 ret_pte = (pte_t *) pudp;
963 goto out; 974 goto out;
964 } else if (is_hugepd(pu)) 975 } else if (is_hugepd(&pud))
965 hpdp = (hugepd_t *)pu; 976 hpdp = (hugepd_t *)&pud;
966 else { 977 else {
967 pdshift = PMD_SHIFT; 978 pdshift = PMD_SHIFT;
968 pm = pmd_offset(pu, ea); 979 pmdp = pmd_offset(&pud, ea);
980 pmd = ACCESS_ONCE(*pmdp);
969 /* 981 /*
970 * A hugepage collapse is captured by pmd_none, because 982 * A hugepage collapse is captured by pmd_none, because
971 * it mark the pmd none and do a hpte invalidate. 983 * it mark the pmd none and do a hpte invalidate.
@@ -975,16 +987,16 @@ pte_t *find_linux_pte_or_hugepte(pgd_t *pgdir, unsigned long ea, unsigned *shift
975 * hpte invalidate 987 * hpte invalidate
976 * 988 *
977 */ 989 */
978 if (pmd_none(*pm) || pmd_trans_splitting(*pm)) 990 if (pmd_none(pmd) || pmd_trans_splitting(pmd))
979 return NULL; 991 return NULL;
980 992
981 if (pmd_huge(*pm) || pmd_large(*pm)) { 993 if (pmd_huge(pmd) || pmd_large(pmd)) {
982 ret_pte = (pte_t *) pm; 994 ret_pte = (pte_t *) pmdp;
983 goto out; 995 goto out;
984 } else if (is_hugepd(pm)) 996 } else if (is_hugepd(&pmd))
985 hpdp = (hugepd_t *)pm; 997 hpdp = (hugepd_t *)&pmd;
986 else 998 else
987 return pte_offset_kernel(pm, ea); 999 return pte_offset_kernel(&pmd, ea);
988 } 1000 }
989 } 1001 }
990 if (!hpdp) 1002 if (!hpdp)
@@ -1020,6 +1032,14 @@ int gup_hugepte(pte_t *ptep, unsigned long sz, unsigned long addr,
1020 if ((pte_val(pte) & mask) != mask) 1032 if ((pte_val(pte) & mask) != mask)
1021 return 0; 1033 return 0;
1022 1034
1035#ifdef CONFIG_TRANSPARENT_HUGEPAGE
1036 /*
1037 * check for splitting here
1038 */
1039 if (pmd_trans_splitting(pte_pmd(pte)))
1040 return 0;
1041#endif
1042
1023 /* hugepages are never "special" */ 1043 /* hugepages are never "special" */
1024 VM_BUG_ON(!pfn_valid(pte_pfn(pte))); 1044 VM_BUG_ON(!pfn_valid(pte_pfn(pte)));
1025 1045
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c
index 0988a26e0413..ccd49f9503a9 100644
--- a/arch/powerpc/mm/mem.c
+++ b/arch/powerpc/mm/mem.c
@@ -508,6 +508,10 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long address,
508 pte_t *ptep) 508 pte_t *ptep)
509{ 509{
510#ifdef CONFIG_PPC_STD_MMU 510#ifdef CONFIG_PPC_STD_MMU
511 /*
512 * We don't need to worry about _PAGE_PRESENT here because we are
513 * called with either mm->page_table_lock held or ptl lock held
514 */
511 unsigned long access = 0, trap; 515 unsigned long access = 0, trap;
512 516
513 /* We only want HPTEs for linux PTEs that have _PAGE_ACCESSED set */ 517 /* We only want HPTEs for linux PTEs that have _PAGE_ACCESSED set */