Re: [PATCH] mm/arm: pgtable: remove young bit check for pte_valid_user

Russell King (Oracle)
2026-04-09T16:01:04Z

On Thu, Apr 09, 2026 at 06:17:36PM +0300, Brian Ruley wrote:
> However, in the case I describe, if VA_B is mapped immediately to pfn_q
> after it been has unmapped and freed for VA_A, then it's quite possible
> that the page is still indexed in the cache.

True.

> The hypothesis is that if
> VA_A and VA_B land in the same I-cache set and VA_A old cache entry
> still exists (tagged with pfn_q), then the CPU can fetch stale
> instructions because the tag will match. That's one reason why we need
> to invalidate the cache, but that will be skipped in the path:
>
> migrate_pages
> migrate_pages_batch
> migrate_folio_move
> remove_migration_ptes
> remove_migration_pte
> set_pte_at
> set_ptes
> __sync_icache_dcache (skipped if !young)
> set_pte_ext

In this case, if the old PTE was marked !young, then the new PTE will
have:
pte = pte_mkold(pte);

on it, which marks it !young. As you say, __sync_icache_dcache() will
be skipped. While a PTE entry will be set for the kernel, the code in
set_pte_ext() will *not* establish a hardware PTE entry. For the
2-level pte code:

tst r1, #L_PTE_YOUNG @ <- results in Z being set
tstne r1, #L_PTE_VALID @ <- not executed
eorne r1, r1, #L_PTE_NONE @ <- not executed
tstne r1, #L_PTE_NONE @ <- not executed
moveq r3, #0 @ <- hardware PTE value
ARM( str r3, [r0, #2048]! ) @ <- writes hardware PTE

So, for a !young PTE, the hardware PTE entry is written as zero,
which means accesses should fault, which will then cause the PTE to
be marked young.

For the 3-level case, the L_PTE_YOUNG bit corresponds with the AF bit
in the PTE, and there aren't split Linux / hardware PTE entries. AF
being clear should result in a page fault being generated for the
kernel to handle making the PTE young.

In both of these cases, set_ptes() will need to be called with the
updated PTE which will now be marked young, and that will result in
the I-cache being flushed.