* [PATCH 1/2] mm/mempolicy: use vm_normal_folio_pmd() in queue_folios_pmd() [not found] <20260821144947.167382-1-gourry@gourry.net> @ 2026-08-21 14:49 ` Gregory Price 2026-08-27 17:05 ` David Hildenbrand (Arm) 2026-08-21 14:49 ` [PATCH 2/2] mm/madvise: use vm_normal_folio_pmd() in cold/pageout PMD range Gregory Price 1 sibling, 1 reply; 6+ messages in thread From: Gregory Price @ 2026-08-21 14:49 UTC (permalink / raw) To: linux-mm Cc: linux-kernel, kernel-team, akpm, liam, ljs, david, vbabka, jannh, ziy, matthew.brost, joshua.hahnjy, rakie.kim, byungchul, gourry, ying.huang, apopple, peterx, jgg, sashiko-bot, stable mmap a VM_PFNMAP region whose ->huge_fault installs a PMD through vmf_insert_pfn_pmd() - a vfio-pci MMIO BAR does this - then mbind(p, len, MPOL_BIND, &mask, maxnode, MPOL_MF_STRICT); With a stand-in module for the driver: BUG: unable to handle page fault for address: fffff96dc0000008 RIP: 0010:queue_folios_pte_range+0xaf/0x440 walk_pgd_range+0x52b/0xaf0 __walk_page_range+0x6a/0x1d0 walk_page_range_mm_unsafe+0x193/0x230 queue_pages_range+0x64/0xa0 do_mbind+0x25e/0x640 queue_folios_pmd(), inlined above, calls pmd_folio() on that PMD. The pfn is raw MMIO with no memmap entry, so the folio lands in unpopulated vmemmap. Neither guard stops the walk: walk_page_test() skips VM_PFNMAP, but queue_pages_walk_ops supplies ->test_walk, so it never runs queue_pages_test_walk() honours vma_migratable(), but only while MPOL_MF_STRICT is clear A VM_MIXEDMAP vma needs neither flag, being vma_migratable(), so plain mbind(MPOL_MF_MOVE) reaches this too - and there the bad folio carries on into migrate_folio_add() and folio_isolate_lru(). mshv_vtl_low is such a mapping. Use vm_normal_folio_pmd() and skip on NULL, as the PTE loop in queue_folios_pte_range() already does with vm_normal_folio(). The huge zero PMD moves ahead of the lookup, since vm_normal_folio_pmd() returns NULL for it and its ACTION_CONTINUE would be lost. mbind(MPOL_MF_STRICT) over a PMD mapped VM_PFNMAP region now returns 0 rather than -EIO. The PTE loop already returned 0 there. Fixes: 3c8e44c9b369 ("mm: mark special bits for huge pfn mappings when inject") Reported-by: sashiko-bot <sashiko-bot@kernel.org> Closes: https://sashiko.dev/#/patchset/20260817220810.1175596-1-gourry%40gourry.net Cc: stable@vger.kernel.org Assisted-by: Claude:claude-opus-5 Signed-off-by: Gregory Price (Meta) <gourry@gourry.net> --- mm/mempolicy.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/mm/mempolicy.c b/mm/mempolicy.c index f1aba551f9f1..85803c845965 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -650,7 +650,8 @@ static inline bool queue_folio_required(struct folio *folio, return node_isset(nid, *qp->nmask) == !(flags & MPOL_MF_INVERT); } -static void queue_folios_pmd(pmd_t *pmd, struct mm_walk *walk) +static void queue_folios_pmd(pmd_t *pmd, unsigned long addr, + struct mm_walk *walk) { struct folio *folio; struct queue_pages *qp = walk->private; @@ -661,13 +662,15 @@ static void queue_folios_pmd(pmd_t *pmd, struct mm_walk *walk) qp->nr_failed++; return; } - folio = pmd_folio(pmdval); - if (folio_is_zone_device(folio)) - return; - if (is_huge_zero_folio(folio)) { + if (is_huge_zero_pmd(pmdval)) { walk->action = ACTION_CONTINUE; return; } + folio = vm_normal_folio_pmd(walk->vma, addr, pmdval); + if (!folio) + return; + if (folio_is_zone_device(folio)) + return; if (!queue_folio_required(folio, qp)) return; if (!(qp->flags & (MPOL_MF_MOVE | MPOL_MF_MOVE_ALL)) || @@ -700,7 +703,7 @@ static int queue_folios_pte_range(pmd_t *pmd, unsigned long addr, ptl = pmd_trans_huge_lock(pmd, vma); if (ptl) { - queue_folios_pmd(pmd, walk); + queue_folios_pmd(pmd, addr, walk); spin_unlock(ptl); goto out; } -- 2.55.0 ^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH 1/2] mm/mempolicy: use vm_normal_folio_pmd() in queue_folios_pmd() 2026-08-21 14:49 ` [PATCH 1/2] mm/mempolicy: use vm_normal_folio_pmd() in queue_folios_pmd() Gregory Price @ 2026-08-27 17:05 ` David Hildenbrand (Arm) 2026-08-27 18:48 ` Gregory Price 0 siblings, 1 reply; 6+ messages in thread From: David Hildenbrand (Arm) @ 2026-08-27 17:05 UTC (permalink / raw) To: Gregory Price, linux-mm Cc: linux-kernel, kernel-team, akpm, liam, ljs, vbabka, jannh, ziy, matthew.brost, joshua.hahnjy, rakie.kim, byungchul, ying.huang, apopple, peterx, jgg, sashiko-bot, stable On 8/21/26 16:49, Gregory Price wrote: > mmap a VM_PFNMAP region whose ->huge_fault installs a PMD through > vmf_insert_pfn_pmd() - a vfio-pci MMIO BAR does this - then > > mbind(p, len, MPOL_BIND, &mask, maxnode, MPOL_MF_STRICT); > > With a stand-in module for the driver: > > BUG: unable to handle page fault for address: fffff96dc0000008 > RIP: 0010:queue_folios_pte_range+0xaf/0x440 > walk_pgd_range+0x52b/0xaf0 > __walk_page_range+0x6a/0x1d0 > walk_page_range_mm_unsafe+0x193/0x230 > queue_pages_range+0x64/0xa0 > do_mbind+0x25e/0x640 > > queue_folios_pmd(), inlined above, calls pmd_folio() on that PMD. The pfn > is raw MMIO with no memmap entry, so the folio lands in unpopulated > vmemmap. Neither guard stops the walk: > > walk_page_test() skips VM_PFNMAP, but queue_pages_walk_ops > supplies ->test_walk, so it never runs > queue_pages_test_walk() honours vma_migratable(), but only while > MPOL_MF_STRICT is clear > > A VM_MIXEDMAP vma needs neither flag, being vma_migratable(), so plain > mbind(MPOL_MF_MOVE) reaches this too - and there the bad folio carries on > into migrate_folio_add() and folio_isolate_lru(). mshv_vtl_low is such a > mapping. > > Use vm_normal_folio_pmd() and skip on NULL, as the PTE loop in > queue_folios_pte_range() already does with vm_normal_folio(). The huge > zero PMD moves ahead of the lookup, since vm_normal_folio_pmd() returns > NULL for it and its ACTION_CONTINUE would be lost. > > mbind(MPOL_MF_STRICT) over a PMD mapped VM_PFNMAP region now returns 0 > rather than -EIO. The PTE loop already returned 0 there. > > Fixes: 3c8e44c9b369 ("mm: mark special bits for huge pfn mappings when inject") > Reported-by: sashiko-bot <sashiko-bot@kernel.org> > Closes: https://sashiko.dev/#/patchset/20260817220810.1175596-1-gourry%40gourry.net > Cc: stable@vger.kernel.org > Assisted-by: Claude:claude-opus-5 > Signed-off-by: Gregory Price (Meta) <gourry@gourry.net> > --- > mm/mempolicy.c | 15 +++++++++------ > 1 file changed, 9 insertions(+), 6 deletions(-) > > diff --git a/mm/mempolicy.c b/mm/mempolicy.c > index f1aba551f9f1..85803c845965 100644 > --- a/mm/mempolicy.c > +++ b/mm/mempolicy.c > @@ -650,7 +650,8 @@ static inline bool queue_folio_required(struct folio *folio, > return node_isset(nid, *qp->nmask) == !(flags & MPOL_MF_INVERT); > } > > -static void queue_folios_pmd(pmd_t *pmd, struct mm_walk *walk) > +static void queue_folios_pmd(pmd_t *pmd, unsigned long addr, > + struct mm_walk *walk) > { > struct folio *folio; > struct queue_pages *qp = walk->private; > @@ -661,13 +662,15 @@ static void queue_folios_pmd(pmd_t *pmd, struct mm_walk *walk) > qp->nr_failed++; > return; > } > - folio = pmd_folio(pmdval); > - if (folio_is_zone_device(folio)) > - return; > - if (is_huge_zero_folio(folio)) { > + if (is_huge_zero_pmd(pmdval)) { > walk->action = ACTION_CONTINUE; > return; > } > + folio = vm_normal_folio_pmd(walk->vma, addr, pmdval); > + if (!folio) > + return I think this is best written as: folio = vm_normal_folio_pmd(walk->vma, addr, pmdval); if (!folio) { if (is_huge_zero_pmd(pmdval)) { walk->action = ACTION_CONTINUE; return; } return; } That way we minimize checks on the expected path. Acked-by: David Hildenbrand (Arm) <david@kernel.org> -- Cheers, David ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 1/2] mm/mempolicy: use vm_normal_folio_pmd() in queue_folios_pmd() 2026-08-27 17:05 ` David Hildenbrand (Arm) @ 2026-08-27 18:48 ` Gregory Price 0 siblings, 0 replies; 6+ messages in thread From: Gregory Price @ 2026-08-27 18:48 UTC (permalink / raw) To: David Hildenbrand (Arm) Cc: linux-mm, linux-kernel, kernel-team, akpm, liam, ljs, vbabka, jannh, ziy, matthew.brost, joshua.hahnjy, rakie.kim, byungchul, ying.huang, apopple, peterx, jgg, sashiko-bot, stable On Thu, Aug 27, 2026 at 07:05:21PM +0200, David Hildenbrand (Arm) wrote: > > } > > + folio = vm_normal_folio_pmd(walk->vma, addr, pmdval); > > + if (!folio) > > + return > > > I think this is best written as: > > folio = vm_normal_folio_pmd(walk->vma, addr, pmdval); > if (!folio) { > if (is_huge_zero_pmd(pmdval)) { > walk->action = ACTION_CONTINUE; > return; > } > return; > } > That way we minimize checks on the expected path. > Sure, i'll spin a v2 > Acked-by: David Hildenbrand (Arm) <david@kernel.org> > Thanks! ~Gregory ^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 2/2] mm/madvise: use vm_normal_folio_pmd() in cold/pageout PMD range [not found] <20260821144947.167382-1-gourry@gourry.net> 2026-08-21 14:49 ` [PATCH 1/2] mm/mempolicy: use vm_normal_folio_pmd() in queue_folios_pmd() Gregory Price @ 2026-08-21 14:49 ` Gregory Price 2026-08-27 17:07 ` David Hildenbrand (Arm) 1 sibling, 1 reply; 6+ messages in thread From: Gregory Price @ 2026-08-21 14:49 UTC (permalink / raw) To: linux-mm Cc: linux-kernel, kernel-team, akpm, liam, ljs, david, vbabka, jannh, ziy, matthew.brost, joshua.hahnjy, rakie.kim, byungchul, gourry, ying.huang, apopple, peterx, jgg, sashiko-bot, stable mmap a VM_MIXEDMAP region whose ->huge_fault installs a PMD through vmf_insert_pfn_pmd() - mshv_vtl_low does this, and needs CAP_SYS_ADMIN to open - then madvise(p, PMD_SIZE, MADV_PAGEOUT); With a stand-in module for the driver: BUG: unable to handle page fault for address: fffff587c0000008 RIP: 0010:madvise_cold_or_pageout_pte_range+0x410/0x9b0 walk_pgd_range+0x52b/0xaf0 __walk_page_range+0x6a/0x1d0 walk_page_range_vma_unsafe+0x8e/0x120 madvise_pageout+0xb2/0x180 madvise_vma_behavior+0x46b/0xa90 do_madvise+0x108/0x190 __x64_sys_madvise+0x26/0x30 Nothing validates the pfn on the way in: can_madv_lru_vma() rejects VM_PFNMAP, but not VM_MIXEDMAP can_fault() *pfn = vmf->pgoff & ~(mask >> PAGE_SHIFT); vmf_insert_pfn_pmd() no pfn_valid() check pmd_folio() pfn_to_page() -> unpopulated vmemmap Even with a valid pfn the path is wrong. The mapping carries no rmap, so folio_maybe_mapped_shared() sees mapcount 0, and the walker goes on to folio_deactivate(), or folio_isolate_lru() plus reclaim_pages(), against a folio this mapping does not own. Use vm_normal_folio_pmd() and skip on NULL, as the PTE half of this same walker already does with vm_normal_folio(). The huge zero PMD is already handled further up by is_huge_zero_pmd(). Fixes: 3c8e44c9b369 ("mm: mark special bits for huge pfn mappings when inject") Reported-by: sashiko-bot <sashiko-bot@kernel.org> Closes: https://sashiko.dev/#/patchset/20260817220810.1175596-1-gourry%40gourry.net Cc: <stable@vger.kernel.org> # v6.19+ Assisted-by: Claude:claude-opus-5 Signed-off-by: Gregory Price (Meta) <gourry@gourry.net> --- mm/madvise.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mm/madvise.c b/mm/madvise.c index ffd6a68320a8..ab362bc482a5 100644 --- a/mm/madvise.c +++ b/mm/madvise.c @@ -393,7 +393,9 @@ static int madvise_cold_or_pageout_pte_range(pmd_t *pmd, goto huge_unlock; } - folio = pmd_folio(orig_pmd); + folio = vm_normal_folio_pmd(vma, addr, orig_pmd); + if (!folio) + goto huge_unlock; if (folio_is_zone_device(folio)) goto huge_unlock; -- 2.55.0 ^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH 2/2] mm/madvise: use vm_normal_folio_pmd() in cold/pageout PMD range 2026-08-21 14:49 ` [PATCH 2/2] mm/madvise: use vm_normal_folio_pmd() in cold/pageout PMD range Gregory Price @ 2026-08-27 17:07 ` David Hildenbrand (Arm) 2026-08-27 18:50 ` Gregory Price 0 siblings, 1 reply; 6+ messages in thread From: David Hildenbrand (Arm) @ 2026-08-27 17:07 UTC (permalink / raw) To: Gregory Price, linux-mm Cc: linux-kernel, kernel-team, akpm, liam, ljs, vbabka, jannh, ziy, matthew.brost, joshua.hahnjy, rakie.kim, byungchul, ying.huang, apopple, peterx, jgg, sashiko-bot, stable On 8/21/26 16:49, Gregory Price wrote: > mmap a VM_MIXEDMAP region whose ->huge_fault installs a PMD through > vmf_insert_pfn_pmd() - mshv_vtl_low does this, and needs CAP_SYS_ADMIN to > open - then > > madvise(p, PMD_SIZE, MADV_PAGEOUT); > > With a stand-in module for the driver: > > BUG: unable to handle page fault for address: fffff587c0000008 > RIP: 0010:madvise_cold_or_pageout_pte_range+0x410/0x9b0 > walk_pgd_range+0x52b/0xaf0 > __walk_page_range+0x6a/0x1d0 > walk_page_range_vma_unsafe+0x8e/0x120 > madvise_pageout+0xb2/0x180 > madvise_vma_behavior+0x46b/0xa90 > do_madvise+0x108/0x190 > __x64_sys_madvise+0x26/0x30 > > Nothing validates the pfn on the way in: > > can_madv_lru_vma() rejects VM_PFNMAP, but not VM_MIXEDMAP > can_fault() *pfn = vmf->pgoff & ~(mask >> PAGE_SHIFT); > vmf_insert_pfn_pmd() no pfn_valid() check > pmd_folio() pfn_to_page() -> unpopulated vmemmap > > Even with a valid pfn the path is wrong. The mapping carries no rmap, so > folio_maybe_mapped_shared() sees mapcount 0, and the walker goes on to > folio_deactivate(), or folio_isolate_lru() plus reclaim_pages(), against a > folio this mapping does not own. > > Use vm_normal_folio_pmd() and skip on NULL, as the PTE half of this same > walker already does with vm_normal_folio(). The huge zero PMD is already > handled further up by is_huge_zero_pmd(). The last part doesn't make sense, see below. > > Fixes: 3c8e44c9b369 ("mm: mark special bits for huge pfn mappings when inject") > Reported-by: sashiko-bot <sashiko-bot@kernel.org> > Closes: https://sashiko.dev/#/patchset/20260817220810.1175596-1-gourry%40gourry.net > Cc: <stable@vger.kernel.org> # v6.19+ > Assisted-by: Claude:claude-opus-5 > Signed-off-by: Gregory Price (Meta) <gourry@gourry.net> > --- > mm/madvise.c | 4 +++- > 1 file changed, 3 insertions(+), 1 deletion(-) > > diff --git a/mm/madvise.c b/mm/madvise.c > index ffd6a68320a8..ab362bc482a5 100644 > --- a/mm/madvise.c > +++ b/mm/madvise.c > @@ -393,7 +393,9 @@ static int madvise_cold_or_pageout_pte_range(pmd_t *pmd, > goto huge_unlock; > } > > - folio = pmd_folio(orig_pmd); > + folio = vm_normal_folio_pmd(vma, addr, orig_pmd); > + if (!folio) > + goto huge_unlock; I think you can now drop the is_huge_zero_pmd() check, because !vm_normal_folio_pmd() includes the huge zero folio. -- Cheers, David ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 2/2] mm/madvise: use vm_normal_folio_pmd() in cold/pageout PMD range 2026-08-27 17:07 ` David Hildenbrand (Arm) @ 2026-08-27 18:50 ` Gregory Price 0 siblings, 0 replies; 6+ messages in thread From: Gregory Price @ 2026-08-27 18:50 UTC (permalink / raw) To: David Hildenbrand (Arm) Cc: linux-mm, linux-kernel, kernel-team, akpm, liam, ljs, vbabka, jannh, ziy, matthew.brost, joshua.hahnjy, rakie.kim, byungchul, ying.huang, apopple, peterx, jgg, sashiko-bot, stable On Thu, Aug 27, 2026 at 07:07:38PM +0200, David Hildenbrand (Arm) wrote: > On 8/21/26 16:49, Gregory Price wrote: > > > > Fixes: 3c8e44c9b369 ("mm: mark special bits for huge pfn mappings when inject") > > Reported-by: sashiko-bot <sashiko-bot@kernel.org> > > Closes: https://sashiko.dev/#/patchset/20260817220810.1175596-1-gourry%40gourry.net > > Cc: <stable@vger.kernel.org> # v6.19+ > > Assisted-by: Claude:claude-opus-5 > > Signed-off-by: Gregory Price (Meta) <gourry@gourry.net> > > --- > > mm/madvise.c | 4 +++- > > 1 file changed, 3 insertions(+), 1 deletion(-) > > > > diff --git a/mm/madvise.c b/mm/madvise.c > > index ffd6a68320a8..ab362bc482a5 100644 > > --- a/mm/madvise.c > > +++ b/mm/madvise.c > > @@ -393,7 +393,9 @@ static int madvise_cold_or_pageout_pte_range(pmd_t *pmd, > > goto huge_unlock; > > } > > > > - folio = pmd_folio(orig_pmd); > > + folio = vm_normal_folio_pmd(vma, addr, orig_pmd); > > + if (!folio) > > + goto huge_unlock; > I think you can now drop the is_huge_zero_pmd() check, because > !vm_normal_folio_pmd() includes the huge zero folio. > I was err'ing on the side of not removing existing checks, but I can take a look. Trivilially - I think you are right. ~Gregory ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-08-27 18:50 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <20260821144947.167382-1-gourry@gourry.net>
2026-08-21 14:49 ` [PATCH 1/2] mm/mempolicy: use vm_normal_folio_pmd() in queue_folios_pmd() Gregory Price
2026-08-27 17:05 ` David Hildenbrand (Arm)
2026-08-27 18:48 ` Gregory Price
2026-08-21 14:49 ` [PATCH 2/2] mm/madvise: use vm_normal_folio_pmd() in cold/pageout PMD range Gregory Price
2026-08-27 17:07 ` David Hildenbrand (Arm)
2026-08-27 18:50 ` Gregory Price
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox