|
@@ -839,6 +839,17 @@ pmd_t pmdp_get_and_clear(struct mm_struct *mm,
|
|
|
* hash fault look at them.
|
|
|
*/
|
|
|
memset(pgtable, 0, PTE_FRAG_SIZE);
|
|
|
+ /*
|
|
|
+ * Serialize against find_linux_pte_or_hugepte which does lock-less
|
|
|
+ * lookup in page tables with local interrupts disabled. For huge pages
|
|
|
+ * it casts pmd_t to pte_t. Since format of pte_t is different from
|
|
|
+ * pmd_t we want to prevent transit from pmd pointing to page table
|
|
|
+ * to pmd pointing to huge page (and back) while interrupts are disabled.
|
|
|
+ * We clear pmd to possibly replace it with page table pointer in
|
|
|
+ * different code paths. So make sure we wait for the parallel
|
|
|
+ * find_linux_pte_or_hugepage to finish.
|
|
|
+ */
|
|
|
+ kick_all_cpus_sync();
|
|
|
return old_pmd;
|
|
|
}
|
|
|
|