Re: [PATCH v3 09/47] mm/rmap: handle device-exclusive entries in folio_referenced_one()
From: David Hildenbrand (Arm)
Date: Mon Nov 09 2026 - 04:57:21 EST
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!
--
Cheers,
David