Re: [PATCH v3 09/47] mm/rmap: handle device-exclusive entries in folio_referenced_one()
From: Garg, Shivank
Date: Mon Nov 09 2026 - 05:47:49 EST
On Mon, 2026-11-09 at 10:51 +0100, David Hildenbrand (Arm) wrote:
> On 11/9/26 06:22, Garg, Shivank wrote:
> > On Sat, 2026-10-31 at 10:39 +0100, David Hildenbrand (Arm) wrote:
> > > page_vma_mapped_walk() can return non-present device-exclusive entries,
> > > but folio_referenced_one() passes them to PTE young-bit accessors that
> > > require present PTEs.
> > >
> > > We must neither call clear_flush_young_ptes_notify() nor
> > > folio_pte_batch() with non-present entries. For example, clearing the
> > > young bit on non-present PTEs can corrupt the entry: on arm64
> > > PTE_AF overlaps the swap type, so clearing it turns a device-exclusive
> > > entry into an ordinary swap entry.
> > >
> > > folio_pte_batch() will VM_WARN_ON_FOLIO.
> > >
> > > Apply the same approach as the previous fixes to e.g., damon_ptep_mkold():
> > > treat these entries as old from the CPU's perspective and obtain their
> > > young state through the MMU notifier.
> > >
> > > Skip PTE batching and MGLRU look-around for non-present entries, and
> > > don't modify non-present PTEs.
> > >
> > > Fixes: b756a3b5e7ea ("mm: device exclusive memory access")
> > > Reviewed-by: Lorenzo Stoakes (ARM) <ljs@xxxxxxxxxx>
> > > Cc: stable@xxxxxxxxxxxxxxx
> > > Reported-by: Josef Bacik <josef@xxxxxxxxxxxxxx>
> > > Reviewed-by: Harry Yoo (Meta) <harry@xxxxxxxxxx>
> > > Reviewed-by: Barry Song <baohua@xxxxxxxxxx>
> > > Reviewed-by: Dev Jain <dev.jain@xxxxxxx>
> > > Tested-by: Muhammad Usama Anjum <usama.anjum@xxxxxxx>
> > > Signed-off-by: David Hildenbrand (Arm) <david@xxxxxxxxxx>
> > > ---
> > > mm/rmap.c | 23 +++++++++++++++++++----
> > > 1 file changed, 19 insertions(+), 4 deletions(-)
> > >
> > > diff --git a/mm/rmap.c b/mm/rmap.c
> > > index 1131b76bbbc28..0faef46806e5c 100644
> > > --- a/mm/rmap.c
> > > +++ b/mm/rmap.c
> > > @@ -924,6 +924,7 @@ static bool folio_referenced_one(struct folio *folio,
> > > DEFINE_FOLIO_VMA_WALK(pvmw, folio, vma, address, 0);
> > > int ptes = 0, referenced = 0;
> > > unsigned int nr;
> > > + pte_t pteval;
> > >
> > > while (page_vma_mapped_walk(&pvmw)) {
> > > address = pvmw.address;
> > > @@ -968,10 +969,12 @@ static bool folio_referenced_one(struct folio *folio,
> > > return false;
> > > }
> > >
> > > - if (pvmw.pte && folio_test_large(folio)) {
> > > + if (pvmw.pte)
> > > + pteval = ptep_get(pvmw.pte);
> > > +
> > > + if (pvmw.pte && pte_present(pteval) && folio_test_large(folio)) {
> > > const unsigned long end_addr = pmd_addr_end(address, vma->vm_end);
> > > const unsigned int max_nr = (end_addr - address) >> PAGE_SHIFT;
> > > - pte_t pteval = ptep_get(pvmw.pte);
> > >
> > > nr = folio_pte_batch(folio, pvmw.pte, pteval, max_nr);
> > > }
> > > @@ -981,11 +984,23 @@ static bool folio_referenced_one(struct folio *folio,
> > > * are. —they could be on active/inactive lists or on MGLRU. So the
> > > * simplest approach is to disable this look-around optimization.
> > > */
> > > - if (lru_gen_enabled() && !lru_gen_switching() && pvmw.pte) {
> > > + if (lru_gen_enabled() && !lru_gen_switching() && pvmw.pte &&
> > > + pte_present(pteval)) {
> > > if (lru_gen_look_around(&pvmw, nr))
> > > referenced++;
> > > } else if (pvmw.pte) {
> > > - if (clear_flush_young_ptes_notify(vma, address, pvmw.pte, nr))
> >
> > This was the only caller of clear_flush_young_ptes_notify(), so this
> > leaves both definitions in mm/internal.h unused.
> >
> > Would you prefer to remove them, or keep them for company with their
> > still used test_and_clear_young_ptes_notify friend?
>
> Can you send a cleanup? Thanks!
Sure, thanks. Will do.
I'll include it in V2 of my previous series [1].
Do you have any comment on [1] now, before I send V2.
[1]
https://lore.kernel.org/linux-mm/20261026-unused-sym-v1-0-82ca2dceabe1@xxxxxxx
Thanks,
Shivank