Merge tag 'v3.10.61' into linux-linaro-lsk
[firefly-linux-kernel-4.4.55.git] / arch / arm / mm / fault.c
index 160da6d655467cb68ed837433b4d74fae3f33086..54fcddafec155b9a8bb9950c2a63d2f75c7d0af1 100644 (file)
@@ -449,8 +449,16 @@ do_translation_fault(unsigned long addr, unsigned int fsr,
 
        if (pud_none(*pud_k))
                goto bad_area;
-       if (!pud_present(*pud))
+       if (!pud_present(*pud)) {
                set_pud(pud, *pud_k);
+               /*
+                * There is a small window during free_pgtables() where the
+                * user *pud entry is 0 but the TLB has not been invalidated
+                * and we get a level 2 (pmd) translation fault caused by the
+                * intermediate TLB caching of the old level 1 (pud) entry.
+                */
+               flush_tlb_kernel_page(addr);
+       }
 
        pmd = pmd_offset(pud, addr);
        pmd_k = pmd_offset(pud_k, addr);
@@ -473,8 +481,9 @@ do_translation_fault(unsigned long addr, unsigned int fsr,
 #endif
        if (pmd_none(pmd_k[index]))
                goto bad_area;
+       if (!pmd_present(pmd[index]))
+               copy_pmd(pmd, pmd_k);
 
-       copy_pmd(pmd, pmd_k);
        return 0;
 
 bad_area: