|
@@ -6,17 +6,6 @@
|
|
|
|
|
|
#include "internal.h"
|
|
#include "internal.h"
|
|
|
|
|
|
-static inline bool check_pmd(struct page_vma_mapped_walk *pvmw)
|
|
|
|
-{
|
|
|
|
- pmd_t pmde;
|
|
|
|
- /*
|
|
|
|
- * Make sure we don't re-load pmd between present and !trans_huge check.
|
|
|
|
- * We need a consistent view.
|
|
|
|
- */
|
|
|
|
- pmde = READ_ONCE(*pvmw->pmd);
|
|
|
|
- return pmd_present(pmde) && !pmd_trans_huge(pmde);
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
static inline bool not_found(struct page_vma_mapped_walk *pvmw)
|
|
static inline bool not_found(struct page_vma_mapped_walk *pvmw)
|
|
{
|
|
{
|
|
page_vma_mapped_walk_done(pvmw);
|
|
page_vma_mapped_walk_done(pvmw);
|
|
@@ -116,6 +105,7 @@ bool page_vma_mapped_walk(struct page_vma_mapped_walk *pvmw)
|
|
pgd_t *pgd;
|
|
pgd_t *pgd;
|
|
p4d_t *p4d;
|
|
p4d_t *p4d;
|
|
pud_t *pud;
|
|
pud_t *pud;
|
|
|
|
+ pmd_t pmde;
|
|
|
|
|
|
/* The only possible pmd mapping has been handled on last iteration */
|
|
/* The only possible pmd mapping has been handled on last iteration */
|
|
if (pvmw->pmd && !pvmw->pte)
|
|
if (pvmw->pmd && !pvmw->pte)
|
|
@@ -148,7 +138,13 @@ restart:
|
|
if (!pud_present(*pud))
|
|
if (!pud_present(*pud))
|
|
return false;
|
|
return false;
|
|
pvmw->pmd = pmd_offset(pud, pvmw->address);
|
|
pvmw->pmd = pmd_offset(pud, pvmw->address);
|
|
- if (pmd_trans_huge(*pvmw->pmd) || is_pmd_migration_entry(*pvmw->pmd)) {
|
|
|
|
|
|
+ /*
|
|
|
|
+ * Make sure the pmd value isn't cached in a register by the
|
|
|
|
+ * compiler and used as a stale value after we've observed a
|
|
|
|
+ * subsequent update.
|
|
|
|
+ */
|
|
|
|
+ pmde = READ_ONCE(*pvmw->pmd);
|
|
|
|
+ if (pmd_trans_huge(pmde) || is_pmd_migration_entry(pmde)) {
|
|
pvmw->ptl = pmd_lock(mm, pvmw->pmd);
|
|
pvmw->ptl = pmd_lock(mm, pvmw->pmd);
|
|
if (likely(pmd_trans_huge(*pvmw->pmd))) {
|
|
if (likely(pmd_trans_huge(*pvmw->pmd))) {
|
|
if (pvmw->flags & PVMW_MIGRATION)
|
|
if (pvmw->flags & PVMW_MIGRATION)
|
|
@@ -174,9 +170,8 @@ restart:
|
|
spin_unlock(pvmw->ptl);
|
|
spin_unlock(pvmw->ptl);
|
|
pvmw->ptl = NULL;
|
|
pvmw->ptl = NULL;
|
|
}
|
|
}
|
|
- } else {
|
|
|
|
- if (!check_pmd(pvmw))
|
|
|
|
- return false;
|
|
|
|
|
|
+ } else if (!pmd_present(pmde)) {
|
|
|
|
+ return false;
|
|
}
|
|
}
|
|
if (!map_pte(pvmw))
|
|
if (!map_pte(pvmw))
|
|
goto next_pte;
|
|
goto next_pte;
|