FAILED: patch "[PATCH] mm/rmap: use huge_ptep_get() in try_to_unmap_one()" failed to apply to 6.12-stable tree
Subsystems (4)
[email protected]
maintainerThe patch below does not apply to the 6.12-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.12.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 '2026090345-number-strenuous-f36b@gregkh' --subject-prefix 'PATCH 6.12.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 | 3 +++ include/linux/swapops.h | 12 ++++++++- mm/huge_memory.c | 4 ++- mm/memory.c | 49 ++++++++++++++++++++---------------- mm/page_table_check.c | 12 ++++++--- mm/rmap.c | 54 ++++++++++++++++++++++++++++++---------- 7 files changed, 105 insertions(+), 44 deletions(-)
fs/proc/task_mmu.c +12 -3
@@ -860,10 +860,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))
@@ -1786,6 +1788,9 @@ static int pagemap_pmd_range(pmd_t *pmdp, unsigned long addr, unsigned long end,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);
@@ -1798,7 +1803,7 @@ static int pagemap_pmd_range(pmd_t *pmdp, unsigned long addr, unsigned long end, frame =pmd_pfn (pmd) + idx; }#ifdef CONFIG_ARCH_ENABLE_THP_MIGRATION - else if (is_swap_pmd(pmd)) { + else {swp_entry_t entry =pmd_to_swp_entry (pmd);unsigned long offset;
@@ -1826,6 +1831,7 @@ static int pagemap_pmd_range(pmd_t *pmdp, unsigned long addr, unsigned long end, flags |=PM_FILE ; } +populate_pagemap:for (; addr != end; addr +=PAGE_SIZE , idx++) {u64 cur_flags = flags;pagemap_entry_t pme;
@@ -2172,6 +2178,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;
@@ -2189,7 +2198,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 +3 -0
@@ -283,6 +283,9 @@ typedef struct {unsigned long val; } swp_entry_t; +/* Transitional name used by newer MM fixes. */ +typedef swp_entry_t softleaf_t ; +/** * struct folio - Represents a contiguous set of bytes. * @flags: Identical to the page flags.
include/linux/swapops.h +11 -1
@@ -139,6 +139,10 @@ static inline swp_entry_t pte_to_swp_entry(pte_t pte)return swp_entry (__swp_type (arch_entry),__swp_offset (arch_entry)); } +/* Transitional softleaf spellings for the equivalent swap entry helpers. */ +#define softleaf_from_pte (pte) pte_to_swp_entry(pte) +#define softleaf_to_pfn (entry) swp_offset_pfn(entry) +/* * Convert the arch-independent representation of a swp_entry_t into the * arch-dependent pte representation.
@@ -569,7 +573,13 @@ static inline pmd_t swp_entry_to_pmd(swp_entry_t entry)static inline int is_pmd_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
@@ -2149,9 +2149,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
@@ -228,10 +228,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_pmd_set (struct mm_struct *mm,pmd_t *pmdp,pmd_t pmd)
mm/rmap.c +41 -13
104 lines not on this page · raw message
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
@@ -1235,6 +1235,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
@@ -1711,14 +1711,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);
@@ -1726,7 +1731,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