FAILED: patch "[PATCH] mm/rmap: use huge_ptep_get() in try_to_migrate_one()" failed to apply to 6.12-stable tree
Subsystems (3)
[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 9be12ffa78cd087d41086f937a156435d4e588e9
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026090358-glandular-hardiness-9af2@gregkh' --subject-prefix 'PATCH 6.12.y' 'HEAD^..'
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 9be12ffa78cd087d41086f937a156435d4e588e9 Mon Sep 17 00:00:00 2001
From: Dev Jain <[email protected]>
Date: Fri, 3 Jul 2026 11:41:56 +0000
Subject: [PATCH] mm/rmap: use huge_ptep_get() in try_to_migrate_one()
try_to_migrate_one() is used by folio migration to replace a present mapping with a migration entry. For hugetlb folios, page_vma_mapped_walk() returns the pte pointer to the hugetlb folio in pvmw.pte, but the code reads the huge pte entry 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.
Use huge_ptep_get() to dereference a huge pte pointer.
Commit a98a2f0c8ce1 copied the bug from try_to_unmap_one into try_to_migrate_one.
mm/rmap.c +9 -6
@@ -2500,14 +2500,18 @@ static bool try_to_migrate_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);
@@ -2515,7 +2519,6 @@ static bool try_to_migrate_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: 9be12ffa78cd ("mm/rmap: use huge_ptep_get() in try_to_migrate_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 | 126 ++++++++++++++++----------------------- 7 files changed, 117 insertions(+), 104 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 +53 -73
191 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_migrate_one()
From: Dev Jain <[email protected]>
[ Upstream commit 9be12ffa78cd087d41086f937a156435d4e588e9 ]
try_to_migrate_one() is used by folio migration to replace a present mapping with a migration entry. For hugetlb folios, page_vma_mapped_walk() returns the pte pointer to the hugetlb folio in pvmw.pte, but the code reads the huge pte entry 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.
Use huge_ptep_get() to dereference a huge pte pointer.
Commit a98a2f0c8ce1 copied the bug from try_to_unmap_one into try_to_migrate_one.
--- mm/rmap.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-)
mm/rmap.c +9 -6
@@ -2070,14 +2070,18 @@ static bool try_to_migrate_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);
@@ -2085,7 +2089,6 @@ static bool try_to_migrate_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
Re: [PATCH 6.12.y 1/2] mm: avoid unnecessary use of is_swap_pmd()
In reply to Sasha LevinQuoted 510 lines · Sasha Levin
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 howis_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.
Link https://lkml.kernel.org/r/8a1704b36a009c18032d5bea4cb68e71448fbbe5.1762812360.git.lorenzo.stoakes@oracle.com open hereSigned-off-by Lorenzo Stoakes <[email protected]>Reviewed-by Vlastimil Babka <[email protected]>Cc Alexander Gordeev <[email protected]>Cc Alistair Popple <[email protected]>Cc Al Viro <[email protected]>Cc Arnd Bergmann <[email protected]>Cc Axel Rasmussen <[email protected]>Cc Baolin Wang <[email protected]>Cc Baoquan He <[email protected]>Cc Barry Song <[email protected]>Cc Byungchul Park <[email protected]>Cc Chengming Zhou <[email protected]>Cc Chris Li <[email protected]>Cc Christian Borntraeger <[email protected]>Cc Christian Brauner <[email protected]>Cc Claudio Imbrenda <[email protected]>Cc David Hildenbrand <[email protected]>Cc Dev Jain <[email protected]>Cc Gerald Schaefer <[email protected]>Cc Gregory Price <[email protected]>Cc Heiko Carstens <[email protected]>Cc "Huang, Ying" <[email protected]>Cc Hugh Dickins <[email protected]>Cc Jan Kara <[email protected]>Cc Jann Horn <[email protected]>Cc Janosch Frank <[email protected]>Cc Jason Gunthorpe <[email protected]>Cc Joshua Hahn <[email protected]>Cc Kairui Song <[email protected]>Cc Kemeng Shi <[email protected]>Cc Lance Yang <[email protected]>Cc Leon Romanovsky <[email protected]>Cc Liam Howlett <[email protected]>Cc Mathew Brost <[email protected]>Cc Matthew Wilcox (Oracle) <[email protected]>Cc Miaohe Lin <[email protected]>Cc Michal Hocko <[email protected]>Cc Mike Rapoport <[email protected]>Cc Muchun Song <[email protected]>Cc Naoya Horiguchi <[email protected]>Cc Nhat Pham <[email protected]>Cc Nico Pache <[email protected]>Cc Oscar Salvador <[email protected]>Cc Pasha Tatashin <[email protected]>Cc Peter Xu <[email protected]>Cc Rakie Kim <[email protected]>Cc Rik van Riel <[email protected]>Cc Ryan Roberts <[email protected]>Cc SeongJae Park <[email protected]>Cc Suren Baghdasaryan <[email protected]>Cc Sven Schnelle <[email protected]>Cc Vasily Gorbik <[email protected]>Cc Vlastimil Babka <[email protected]>Cc Wei Xu <[email protected]>Cc xu xin <[email protected]>Cc Yuanchu Xie <[email protected]>Cc Zi Yan <[email protected]>Signed-off-by Andrew Morton <[email protected]>Stable-dep-of:
9be12ffa78cd("mm/rmap: usehuge_ptep_get()intry_to_migrate_one()")Signed-off-by Sasha Levin <[email protected]>--- 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 | 126 ++++++++++++++++----------------------- 7 files changed, 117 insertions(+), 104 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@@ -5901,34 +5901,39 @@ static vm_fault_t __handle_mm_fault(struct vm_area_struct *vma, thp_vma_allowable_order(vma, vm_flags, TVA_IN_PF | TVA_ENFORCE_SYSFS, PMD_ORDER)) { ret =create_huge_pmd (&vmf); - if (!(ret & VM_FAULT_FALLBACK)) +if (ret &VM_FAULT_FALLBACK ) + goto fallback; +else return ret; - } else { - vmf.orig_pmd =pmdp_get_lockless (vmf.pmd); + } -if (unlikely (is_swap_pmd (vmf.orig_pmd))) { -VM_BUG_ON (thp_migration_supported () && - !is_pmd_migration_entry (vmf.orig_pmd)); -if (is_pmd_migration_entry (vmf.orig_pmd)) -pmd_migration_entry_wait (mm, vmf.pmd); -return 0 ; - } -if (pmd_trans_huge (vmf.orig_pmd) ||pmd_devmap (vmf.orig_pmd)) { -if (pmd_protnone (vmf.orig_pmd) &&vma_is_accessible (vma)) -return do_huge_pmd_numa_page (&vmf); + vmf.orig_pmd =pmdp_get_lockless (vmf.pmd); +if (pmd_none (vmf.orig_pmd)) + goto fallback; -if ((flags & (FAULT_FLAG_WRITE |FAULT_FLAG_UNSHARE )) && - !pmd_write (vmf.orig_pmd)) { - ret =wp_huge_pmd (&vmf); -if (!(ret &VM_FAULT_FALLBACK )) -return ret; - }else { -huge_pmd_set_accessed (&vmf); -return 0 ; - } +if (unlikely (!pmd_present (vmf.orig_pmd))) { +VM_BUG_ON (thp_migration_supported () && + !is_pmd_migration_entry (vmf.orig_pmd)); +if (is_pmd_migration_entry (vmf.orig_pmd)) +pmd_migration_entry_wait (mm, vmf.pmd); +return 0 ; + } +if (pmd_trans_huge (vmf.orig_pmd) ||pmd_devmap (vmf.orig_pmd)) { +if (pmd_protnone (vmf.orig_pmd) &&vma_is_accessible (vma)) +return do_huge_pmd_numa_page (&vmf); + +if ((flags & (FAULT_FLAG_WRITE |FAULT_FLAG_UNSHARE )) && + !pmd_write (vmf.orig_pmd)) { + ret =wp_huge_pmd (&vmf); +if (!(ret &VM_FAULT_FALLBACK )) +return ret; + }else { +huge_pmd_set_accessed (&vmf); +return 0 ; } } +fallback:return handle_pte_fault (&vmf); }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 +53
-73@@ -2001,9 +2001,9 @@ static bool try_to_migrate_one(struct folio *folio, struct vm_area_struct *vma, {struct mm_struct *mm = vma->vm_mm;DEFINE_FOLIO_VMA_WALK (pvmw, folio, vma, address,0 ); +bool anon_exclusive, writable, ret = true;pte_t pteval;struct page *subpage; -bool anon_exclusive, ret = true;struct mmu_notifier_range range;enum ttu_flags flags = (enum ttu_flags )(long )arg;unsigned long pfn;@@ -2070,24 +2070,21 @@ static bool try_to_migrate_one(struct folio *folio, struct vm_area_struct *vma,/* Unexpected PMD-mapped THP? */ VM_BUG_ON_FOLIO (!pvmw.pte, folio); - pfn =pte_pfn (ptep_get (pvmw.pte)); - -if (folio_is_zone_device (folio)) { -/* -* Our PTE is a non-present device exclusive entry and -* calculating the subpage as for the common case would -* result in an invalid pointer. -* -* Since only PAGE_SIZE pages can currently be -* migrated, just set it to page. This will need to be -* changed when hugepage migrations to device private -* memory are supported. -*/ -VM_BUG_ON_FOLIO (folio_nr_pages (folio) >1 , folio); - subpage = &folio->page; +/* +* Handle PFN swap PTEs, such as device-exclusive ones, that +* actually map pages. +*/ + pteval =ptep_get (pvmw.pte); +if (likely (pte_present (pteval))) { + pfn =pte_pfn (pteval); }else { - subpage =folio_page (folio, pfn -folio_pfn (folio)); +const softleaf_t entry =softleaf_from_pte (pteval); + + pfn =softleaf_to_pfn (entry); +VM_WARN_ON_FOLIO (folio_test_hugetlb (folio), folio); } + + subpage =folio_page (folio, pfn -folio_pfn (folio)); address = pvmw.address; anon_exclusive =folio_test_anon (folio) &&PageAnonExclusive (subpage);@@ -2141,7 +2138,10 @@ static bool try_to_migrate_one(struct folio *folio, struct vm_area_struct *vma, }/* Nuke the hugetlb page table entry */ pteval =huge_ptep_clear_flush (vma, address, pvmw.pte); - }else { +if (pte_dirty (pteval)) +folio_mark_dirty (folio); + writable =pte_write (pteval); + }else if (likely (pte_present (pteval))) {flush_cache_page (vma, address, pfn);/* Nuke the page table entry. */ if (should_defer_flush (mm, flags)) {@@ -2159,54 +2159,23 @@ static bool try_to_migrate_one(struct folio *folio, struct vm_area_struct *vma, }else { pteval =ptep_clear_flush (vma, address, pvmw.pte); } +if (pte_dirty (pteval)) +folio_mark_dirty (folio); + writable =pte_write (pteval); + }else { +pte_clear (mm, address, pvmw.pte); + writable =is_writable_device_private_entry (pte_to_swp_entry (pteval)); } -/* Set the dirty flag on the folio now the pte is gone. */ -if (pte_dirty (pteval)) -folio_mark_dirty (folio); +VM_WARN_ON_FOLIO (writable &&folio_test_anon (folio) && + !anon_exclusive, folio);/* Update high watermark before we lower rss */ update_hiwater_rss (mm); -if (folio_is_device_private (folio)) { -unsigned long pfn =folio_pfn (folio); -swp_entry_t entry; -pte_t swp_pte; - -if (anon_exclusive) -WARN_ON_ONCE (folio_try_share_anon_rmap_pte (folio, - subpage)); - -/* -* Store the pfn of the page in a special migration -* pte. do_swap_page() will wait until the migration -* pte is removed and then restart fault handling. -*/ - entry =pte_to_swp_entry (pteval); -if (is_writable_device_private_entry (entry)) - entry =make_writable_migration_entry (pfn); -else if (anon_exclusive) - entry =make_readable_exclusive_migration_entry (pfn); -else - entry =make_readable_migration_entry (pfn); - swp_pte =swp_entry_to_pte (entry); +if (PageHWPoison (subpage)) { +VM_WARN_ON_FOLIO (folio_is_device_private (folio), folio); -/* -* pteval maps a zone device page and is therefore -* a swap pte. -*/ -if (pte_swp_soft_dirty (pteval)) - swp_pte =pte_swp_mksoft_dirty (swp_pte); -if (pte_swp_uffd_wp (pteval)) - swp_pte =pte_swp_mkuffd_wp (swp_pte); -set_pte_at (mm, pvmw.address, pvmw.pte, swp_pte); -trace_set_migration_pte (pvmw.address,pte_val (swp_pte), -folio_order (folio)); -/* -* No need to invalidate here it will synchronize on -* against the special swap migration pte. -*/ - }else if (PageHWPoison (subpage)) { pteval =swp_entry_to_pte (make_hwpoison_entry (subpage));if (folio_test_hugetlb (folio)) {hugetlb_count_sub (folio_nr_pages (folio), mm);@@ -2216,8 +2185,8 @@ static bool try_to_migrate_one(struct folio *folio, struct vm_area_struct *vma,dec_mm_counter (mm,mm_counter (folio));set_pte_at (mm, address, pvmw.pte, pteval); } - - }else if (pte_unused (pteval) && !userfaultfd_armed (vma)) { + }else if (likely (pte_present (pteval)) &&pte_unused (pteval) && + !userfaultfd_armed (vma)) {/* * The guest indicated that the page content is of no * interest anymore. Simply discard the pte, vmscan @@ -2233,6 +2202,11 @@ static bool try_to_migrate_one(struct folio *folio, struct vm_area_struct *vma,swp_entry_t entry;pte_t swp_pte; +/* +* arch_unmap_one() is expected to be a NOP on +* architectures where we could have PFN swap PTEs, +* so we'll not check/care. +*/ if (arch_unmap_one (mm, vma, address, pteval) <0 ) {if (folio_test_hugetlb (folio)) set_huge_pte_at(mm, address, pvmw.pte,@@ -2243,8 +2217,6 @@ static bool try_to_migrate_one(struct folio *folio, struct vm_area_struct *vma,page_vma_mapped_walk_done (&pvmw);break ; } -VM_BUG_ON_PAGE (pte_write (pteval) &&folio_test_anon (folio) && - !anon_exclusive, subpage);/* See folio_try_share_anon_rmap_pte(): clear PTE first. */ if (folio_test_hugetlb (folio)) {@@ -2269,7 +2241,7 @@ static bool try_to_migrate_one(struct folio *folio, struct vm_area_struct *vma,* pte. do_swap_page() will wait until the migration * pte is removed and then restart fault handling. */ -if (pte_write (pteval)) +if (writable) entry =make_writable_migration_entry (page_to_pfn (subpage));else if (anon_exclusive)@@ -2278,15 +2250,23 @@ static bool try_to_migrate_one(struct folio *folio, struct vm_area_struct *vma,else entry =make_readable_migration_entry (page_to_pfn (subpage)); -if (pte_young (pteval)) - entry =make_migration_entry_young (entry); -if (pte_dirty (pteval)) - entry =make_migration_entry_dirty (entry); - swp_pte =swp_entry_to_pte (entry); -if (pte_soft_dirty (pteval)) - swp_pte =pte_swp_mksoft_dirty (swp_pte); -if (pte_uffd_wp (pteval)) - swp_pte =pte_swp_mkuffd_wp (swp_pte); +if (likely (pte_present (pteval))) { +if (pte_young (pteval)) + entry =make_migration_entry_young (entry); +if (pte_dirty (pteval)) + entry =make_migration_entry_dirty (entry); + swp_pte =swp_entry_to_pte (entry); +if (pte_soft_dirty (pteval)) + swp_pte =pte_swp_mksoft_dirty (swp_pte); +if (pte_uffd_wp (pteval)) + swp_pte =pte_swp_mkuffd_wp (swp_pte); + }else { + swp_pte =swp_entry_to_pte (entry); +if (pte_swp_soft_dirty (pteval)) + swp_pte =pte_swp_mksoft_dirty (swp_pte); +if (pte_swp_uffd_wp (pteval)) + swp_pte =pte_swp_mkuffd_wp (swp_pte); + }if (folio_test_hugetlb (folio))set_huge_pte_at (mm, address, pvmw.pte, swp_pte, hsz);Signature · 1 line
2.53.0
does not apply :(