diff options
author | Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> | 2013-06-20 05:00:17 -0400 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2013-06-21 02:01:54 -0400 |
commit | ac52ae4721233150a3c30e9732a1c1f4f68e7db7 (patch) | |
tree | 3639fe8131c6553dd3bb353c32b24ca6822d23e6 /arch/powerpc/mm | |
parent | 29409997f8d06d693d82127d200eeaf48989fdd2 (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.c | 32 |
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 | } |