FAILED: patch "[PATCH] mm/rmap: use huge_ptep_get() in try_to_unmap_one()" failed to apply to 6.18-stable tree
Subsystems (4)
[email protected]
maintainerThe patch below does not apply to the 6.18-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.18.y
git checkout FETCH_HEAD
git cherry-pick -x f5407e9b697c940e78b27ff63c6e14d8d171adc3
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026090344-unusual-yippee-a1d0@gregkh' --subject-prefix 'PATCH 6.18.y' 'HEAD^..'
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From f5407e9b697c940e78b27ff63c6e14d8d171adc3 Mon Sep 17 00:00:00 2001
From: Dev Jain <[email protected]>
Date: Fri, 3 Jul 2026 11:41:55 +0000
Subject: [PATCH] mm/rmap: use huge_ptep_get() in try_to_unmap_one()
Patch series "Fix incorrect access of hugetlb pte entries", v3.
There are various places which use ptep_get() to get the pte entry corresponding to a hugetlb folio. Some arches (like s390) have special handling to compute the pteval, so they provide huge_ptep_get(). Use this helper consistently.
Additionally, some code paths may provide huge_ptep_get with an unaligned address. This is a problem on arm64 (I checked other arches and it looks fine for them), which is fixed in patch 1. The fix is made to be
backport-friendly: the cleaner fix would be to perhaps pass the hstate to huge_ptep_get() - that is wider churn and we can do that later.
This patch (of 5):
try_to_unmap_one() handles hugetlb folios when memory failure needs to replace a poisoned hugetlb mapping with a hwpoison entry. In that case page_vma_mapped_walk() returns the pte pointer to the hugetlb folio in pvmw.pte, but the code reads it with ptep_get().
On arches which provide their own huge_ptep_get() to dereference a huge pte pointer, accessing via ptep_get() would cause pte_pfn(), pte_present() etc to misbehave.
It is not clear whether this has a trivially visible effect to userspace.
Just use huge_ptep_get() for dereferencing a huge pte pointer.
include/linux/hugetlb.h +2 -0
@@ -1270,6 +1270,8 @@ static inline void hugetlb_count_sub(long l, struct mm_struct *mm) { } +pte_t huge_ptep_get (struct mm_struct *mm,unsigned long addr,pte_t *ptep); +static inline pte_t huge_ptep_clear_flush (struct vm_area_struct *vma,unsigned long addr,pte_t *ptep) {
mm/rmap.c +10 -6
@@ -2095,14 +2095,19 @@ static bool try_to_unmap_one(struct folio *folio, struct vm_area_struct *vma,/* Unexpected PMD-mapped THP? */ VM_BUG_ON_FOLIO (!pvmw.pte, folio); -/* -* Handle PFN swap PTEs, such as device-exclusive ones, that -* actually map pages. -*/ - pteval =ptep_get (pvmw.pte); + address = pvmw.address; +if (folio_test_hugetlb (folio)) { + pteval =huge_ptep_get (mm, address, pvmw.pte); + }else { + pteval =ptep_get (pvmw.pte); + }if (likely (pte_present (pteval))) { pfn =pte_pfn (pteval); }else { +/* +* Handle PFN swap PTEs, such as device-exclusive ones, +* that actually map pages. +*/ const softleaf_t entry =softleaf_from_pte (pteval); pfn =softleaf_to_pfn (entry);
@@ -2110,7 +2115,6 @@ static bool try_to_unmap_one(struct folio *folio, struct vm_area_struct *vma, } subpage =folio_page (folio, pfn -folio_pfn (folio)); - address = pvmw.address; anon_exclusive =folio_test_anon (folio) &&PageAnonExclusive (subpage);
Sasha Levin
maintainerPATCH 1/2 mm: avoid unnecessary use of is_swap_pmd()
From: Lorenzo Stoakes <[email protected]>
[ Upstream commit aa62204cb680d8ff32497181fc9e0dac4956f7e5 ]
PMD 'non-swap' swap entries are currently used for PMD-level migration entries and device private entries.
To add to the confusion in this terminology we use is_swap_pmd() in an inconsistent way similar to how is_swap_pte() was being used - sometimes adopting the convention that !pmd_none(), !pmd_present() implies PMD 'swap' entry, sometimes not.
This patch handles the low-hanging fruit of cases where we can simply substitute other predicates for is_swap_pmd().
No functional change intended.
Stable-dep-of: f5407e9b697c ("mm/rmap: use huge_ptep_get() in try_to_unmap_one()")
--- fs/proc/task_mmu.c | 15 +++++++++--- include/linux/mm_types.h | 2 ++ include/linux/swapops.h | 12 +++++++++- mm/huge_memory.c | 4 +++- mm/memory.c | 49 ++++++++++++++++++++++------------------ mm/page_table_check.c | 12 ++++++---- mm/rmap.c | 4 +++- 7 files changed, 66 insertions(+), 32 deletions(-)
fs/proc/task_mmu.c +12 -3
@@ -1073,10 +1073,12 @@ static void smaps_pmd_entry(pmd_t *pmd, unsigned long addr,bool present = false;struct folio *folio; +if (pmd_none (*pmd)) +return ;if (pmd_present (*pmd)) { page =vm_normal_page_pmd (vma, addr, *pmd); present = true; - }else if (unlikely (thp_migration_supported () &&is_swap_pmd (*pmd))) { + }else if (unlikely (thp_migration_supported ())) {swp_entry_t entry =pmd_to_swp_entry (*pmd);if (is_pfn_swap_entry (entry))
@@ -2004,6 +2006,9 @@ static int pagemap_pmd_range_thp(pmd_t *pmdp, unsigned long addr,if (vma->vm_flags &VM_SOFTDIRTY ) flags |=PM_SOFT_DIRTY ; +if (pmd_none (pmd)) + goto populate_pagemap; +if (pmd_present (pmd)) { page =pmd_page (pmd);
@@ -2014,7 +2019,7 @@ static int pagemap_pmd_range_thp(pmd_t *pmdp, unsigned long addr, flags |=PM_UFFD_WP ;if (pm->show_pfn) frame =pmd_pfn (pmd) + idx; - }else if (thp_migration_supported () &&is_swap_pmd (pmd)) { + }else if (thp_migration_supported ()) {swp_entry_t entry =pmd_to_swp_entry (pmd);unsigned long offset;
@@ -2041,6 +2046,7 @@ static int pagemap_pmd_range_thp(pmd_t *pmdp, unsigned long addr, flags |=PM_FILE ; } +populate_pagemap:for (; addr != end; addr +=PAGE_SIZE , idx++) {u64 cur_flags = flags;pagemap_entry_t pme;
@@ -2411,6 +2417,9 @@ static unsigned long pagemap_thp_category(struct pagemap_scan_private *p, {unsigned long categories =PAGE_IS_HUGE ; +if (pmd_none (pmd)) +return categories; +if (pmd_present (pmd)) {struct page *page;
@@ -2428,7 +2437,7 @@ static unsigned long pagemap_thp_category(struct pagemap_scan_private *p, categories |=PAGE_IS_PFNZERO ;if (pmd_soft_dirty (pmd)) categories |=PAGE_IS_SOFT_DIRTY ; - }else if (is_swap_pmd (pmd)) { + }else {swp_entry_t swp; categories |=PAGE_IS_SWAPPED ;
include/linux/mm_types.h +2 -0
@@ -285,6 +285,8 @@ typedef struct {unsigned long val; } swp_entry_t; +typedef swp_entry_t softleaf_t ; +#if defined(CONFIG_MEMCG ) || defined(CONFIG_SLAB_OBJ_EXT )/* We have some extra room after the refcount in tail pages. */ #define NR_PAGES_IN_LARGE_FOLIO
include/linux/swapops.h +11 -1
@@ -120,6 +120,8 @@ static inline unsigned long swp_offset_pfn(swp_entry_t entry)return swp_offset (entry) &SWP_PFN_MASK ; } +#define softleaf_to_pfn swp_offset_pfn +/* check whether a pte points to a swap entry */ static inline int is_swap_pte (pte_t pte) {
@@ -139,6 +141,8 @@ static inline swp_entry_t pte_to_swp_entry(pte_t pte)return swp_entry (__swp_type (arch_entry),__swp_offset (arch_entry)); } +#define softleaf_from_pte pte_to_swp_entry +/* * Convert the arch-independent representation of a swp_entry_t into the * arch-dependent pte representation.
@@ -572,7 +576,13 @@ static inline pmd_t swp_entry_to_pmd(swp_entry_t entry)static inline int pmd_is_migration_entry (pmd_t pmd) { -return is_swap_pmd (pmd) &&is_migration_entry (pmd_to_swp_entry (pmd)); +swp_entry_t entry; + +if (pmd_present (pmd)) +return 0 ; + + entry =pmd_to_swp_entry (pmd); +return is_migration_entry (entry); }#else /* CONFIG_ARCH_ENABLE_THP_MIGRATION */ static inline int set_pmd_migration_entry(struct page_vma_mapped_walk *pvmw,
mm/huge_memory.c +3 -1
@@ -2293,9 +2293,11 @@ static pmd_t move_soft_dirty_pmd(pmd_t pmd)static pmd_t clear_uffd_wp_pmd (pmd_t pmd) { +if (pmd_none (pmd)) +return pmd;if (pmd_present (pmd)) pmd =pmd_clear_uffd_wp (pmd); -else if (is_swap_pmd (pmd)) +else pmd =pmd_swp_clear_uffd_wp (pmd);return pmd;
mm/memory.c +27 -22
61 lines not on this page · raw message
mm/page_table_check.c +8 -4
@@ -223,10 +223,14 @@ EXPORT_SYMBOL(__page_table_check_ptes_set);static inline void page_table_check_pmd_flags (pmd_t pmd) { -if (pmd_present (pmd) &&pmd_uffd_wp (pmd)) -WARN_ON_ONCE (pmd_write (pmd)); -else if (is_swap_pmd (pmd) &&pmd_swp_uffd_wp (pmd)) -WARN_ON_ONCE (swap_cached_writable (pmd_to_swp_entry (pmd))); +if (pmd_present (pmd)) { +if (pmd_uffd_wp (pmd)) +WARN_ON_ONCE (pmd_write (pmd)); + }else if (pmd_swp_uffd_wp (pmd)) { +swp_entry_t entry =pmd_to_swp_entry (pmd); + +WARN_ON_ONCE (swap_cached_writable (entry)); + } } void __page_table_check_pmds_set(struct mm_struct *mm, pmd_t *pmdp, pmd_t pmd,
mm/rmap.c +3 -1
@@ -1991,7 +1991,9 @@ static bool try_to_unmap_one(struct folio *folio, struct vm_area_struct *vma,if (likely (pte_present (pteval))) { pfn =pte_pfn (pteval); }else { - pfn =swp_offset_pfn (pte_to_swp_entry (pteval)); +const softleaf_t entry =softleaf_from_pte (pteval); + + pfn =softleaf_to_pfn (entry);VM_WARN_ON_FOLIO (folio_test_hugetlb (folio), folio); }
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 2/2 mm/rmap: use huge_ptep_get() in try_to_unmap_one()
From: Dev Jain <[email protected]>
[ Upstream commit f5407e9b697c940e78b27ff63c6e14d8d171adc3 ]
Patch series "Fix incorrect access of hugetlb pte entries", v3.
There are various places which use ptep_get() to get the pte entry corresponding to a hugetlb folio. Some arches (like s390) have special handling to compute the pteval, so they provide huge_ptep_get(). Use this helper consistently.
Additionally, some code paths may provide huge_ptep_get with an unaligned address. This is a problem on arm64 (I checked other arches and it looks fine for them), which is fixed in patch 1. The fix is made to be
backport-friendly: the cleaner fix would be to perhaps pass the hstate to huge_ptep_get() - that is wider churn and we can do that later.
This patch (of 5):
try_to_unmap_one() handles hugetlb folios when memory failure needs to replace a poisoned hugetlb mapping with a hwpoison entry. In that case page_vma_mapped_walk() returns the pte pointer to the hugetlb folio in pvmw.pte, but the code reads it with ptep_get().
On arches which provide their own huge_ptep_get() to dereference a huge pte pointer, accessing via ptep_get() would cause pte_pfn(), pte_present() etc to misbehave.
It is not clear whether this has a trivially visible effect to userspace.
Just use huge_ptep_get() for dereferencing a huge pte pointer.
--- include/linux/hugetlb.h | 2 ++ mm/rmap.c | 16 ++++++++++------ 2 files changed, 12 insertions(+), 6 deletions(-)
include/linux/hugetlb.h +2 -0
@@ -1277,6 +1277,8 @@ static inline void hugetlb_count_sub(long l, struct mm_struct *mm) { } +pte_t huge_ptep_get (struct mm_struct *mm,unsigned long addr,pte_t *ptep); +static inline pte_t huge_ptep_clear_flush (struct vm_area_struct *vma,unsigned long addr,pte_t *ptep) {
mm/rmap.c +10 -6
@@ -1983,14 +1983,19 @@ static bool try_to_unmap_one(struct folio *folio, struct vm_area_struct *vma,/* Unexpected PMD-mapped THP? */ VM_BUG_ON_FOLIO (!pvmw.pte, folio); -/* -* Handle PFN swap PTEs, such as device-exclusive ones, that -* actually map pages. -*/ - pteval =ptep_get (pvmw.pte); + address = pvmw.address; +if (folio_test_hugetlb (folio)) { + pteval =huge_ptep_get (mm, address, pvmw.pte); + }else { + pteval =ptep_get (pvmw.pte); + }if (likely (pte_present (pteval))) { pfn =pte_pfn (pteval); }else { +/* +* Handle PFN swap PTEs, such as device-exclusive ones, +* that actually map pages. +*/ const softleaf_t entry =softleaf_from_pte (pteval); pfn =softleaf_to_pfn (entry);
@@ -1998,7 +2003,6 @@ static bool try_to_unmap_one(struct folio *folio, struct vm_area_struct *vma, } subpage =folio_page (folio, pfn -folio_pfn (folio)); - address = pvmw.address; anon_exclusive =folio_test_anon (folio) &&PageAnonExclusive (subpage);
Signature · 1 line
2.53.0