aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/mm
diff options
context:
space:
mode:
authorAneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>2013-06-20 05:00:17 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2013-06-21 02:01:54 -0400
commitac52ae4721233150a3c30e9732a1c1f4f68e7db7 (patch)
tree3639fe8131c6553dd3bb353c32b24ca6822d23e6 /arch/powerpc/mm
parent29409997f8d06d693d82127d200eeaf48989fdd2 (diff)
powerpc: Update find_linux_pte_or_hugepte to handle transparent hugepages
Reviewed-by: David Gibson <dwg@au1.ibm.com> Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc/mm')
-rw-r--r--arch/powerpc/mm/hugetlbpage.c32
1 files changed, 26 insertions, 6 deletions
diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c
index 2865077e0159..49282045ee96 100644
--- a/arch/powerpc/mm/hugetlbpage.c
+++ b/arch/powerpc/mm/hugetlbpage.c
@@ -936,30 +936,50 @@ pte_t *find_linux_pte_or_hugepte(pgd_t *pgdir, unsigned long ea, unsigned *shift
936 936
937 pg = pgdir + pgd_index(ea); 937 pg = pgdir + pgd_index(ea);
938 938
939 if (pgd_huge(*pg)) { 939 /*
940 * we should first check for none. That takes care of a
941 * a parallel hugetlb or THP pagefault moving none entries
942 * to respective types.
943 */
944 if (pgd_none(*pg))
945 return NULL;
946 else if (pgd_huge(*pg)) {
940 ret_pte = (pte_t *) pg; 947 ret_pte = (pte_t *) pg;
941 goto out; 948 goto out;
942 } else if (is_hugepd(pg)) 949 } else if (is_hugepd(pg))
943 hpdp = (hugepd_t *)pg; 950 hpdp = (hugepd_t *)pg;
944 else if (!pgd_none(*pg)) { 951 else {
945 pdshift = PUD_SHIFT; 952 pdshift = PUD_SHIFT;
946 pu = pud_offset(pg, ea); 953 pu = pud_offset(pg, ea);
947 954
948 if (pud_huge(*pu)) { 955 if (pud_none(*pu))
956 return NULL;
957 else if (pud_huge(*pu)) {
949 ret_pte = (pte_t *) pu; 958 ret_pte = (pte_t *) pu;
950 goto out; 959 goto out;
951 } else if (is_hugepd(pu)) 960 } else if (is_hugepd(pu))
952 hpdp = (hugepd_t *)pu; 961 hpdp = (hugepd_t *)pu;
953 else if (!pud_none(*pu)) { 962 else {
954 pdshift = PMD_SHIFT; 963 pdshift = PMD_SHIFT;
955 pm = pmd_offset(pu, ea); 964 pm = pmd_offset(pu, ea);
965 /*
966 * A hugepage collapse is captured by pmd_none, because
967 * it mark the pmd none and do a hpte invalidate.
968 *
969 * A hugepage split is captured by pmd_trans_splitting
970 * because we mark the pmd trans splitting and do a
971 * hpte invalidate
972 *
973 */
974 if (pmd_none(*pm) || pmd_trans_splitting(*pm))
975 return NULL;
956 976
957 if (pmd_huge(*pm)) { 977 if (pmd_huge(*pm) || pmd_large(*pm)) {
958 ret_pte = (pte_t *) pm; 978 ret_pte = (pte_t *) pm;
959 goto out; 979 goto out;
960 } else if (is_hugepd(pm)) 980 } else if (is_hugepd(pm))
961 hpdp = (hugepd_t *)pm; 981 hpdp = (hugepd_t *)pm;
962 else if (!pmd_none(*pm)) 982 else
963 return pte_offset_kernel(pm, ea); 983 return pte_offset_kernel(pm, ea);
964 } 984 }
965 } 985 }