mirror of
https://github.com/torvalds/linux.git
synced 2026-09-12 20:53:03 +02:00
mm: decouple protnone helpers from CONFIG_NUMA_BALANCING
Patch series "userfaultfd: working set tracking for VM guest memory", v10. This series adds userfaultfd support for tracking the working set of VM guest memory, so a VMM can identify hot pages and reclaim cold ones to tiered or remote storage. This patch (of 15): pte_protnone() and pmd_protnone() detect present-but-inaccessible page table entries. This capability is useful beyond NUMA balancing -- for example, userfaultfd working set tracking uses protnone PTEs to track page access without unmapping pages. Introduce CONFIG_ARCH_HAS_PTE_PROTNONE to decouple the protnone PTE infrastructure from CONFIG_NUMA_BALANCING. The six architectures that support protnone PTEs (x86_64, arm64, powerpc, s390, riscv, loongarch) now select this option, and CONFIG_NUMA_BALANCING depends on it. No functional change -- the same set of architectures continues to have working protnone support, but the infrastructure is now available independently of NUMA balancing. Link: https://lore.kernel.org/20260708111417.173443-1-kirill@shutemov.name Link: https://lore.kernel.org/20260708111417.173443-2-kirill@shutemov.name Signed-off-by: Kiryl Shutsemau (Meta) <kas@kernel.org> Assisted-by: Claude:claude-opus-4-6 Acked-by: SeongJae Park <sj@kernel.org> Acked-by: Mike Rapoport (Microsoft) <rppt@kernel.org> Cc: Andrea Arcangeli <aarcange@redhat.com> Cc: David Hildenbrand <david@kernel.org> Cc: James Houghton <jthoughton@google.com> Cc: Jonathan Corbet <corbet@lwn.net> Cc: Liam Howlett <liam@infradead.org> Cc: Lorenzo Stoakes <ljs@kernel.org> Cc: Paolo Bonzini <pbonzini@redhat.com> Cc: Peter Xu <peterx@redhat.com> Cc: Sean Christopherson <seanjc@google.com> Cc: Suren Baghdasaryan <surenb@google.com> Cc: Vlastimil Babka <vbabka@kernel.org> Cc: Zi Yan <ziy@nvidia.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
This commit is contained in:
parent
889d3783ae
commit
c6f11553c0
|
|
@ -78,6 +78,7 @@ config ARM64
|
|||
select ARCH_SUPPORTS_CFI
|
||||
select ARCH_SUPPORTS_ATOMIC_RMW
|
||||
select ARCH_SUPPORTS_INT128 if CC_HAS_INT128
|
||||
select ARCH_HAS_PTE_PROTNONE
|
||||
select ARCH_SUPPORTS_NUMA_BALANCING
|
||||
select ARCH_SUPPORTS_PAGE_TABLE_CHECK
|
||||
select ARCH_SUPPORTS_PER_VMA_LOCK
|
||||
|
|
|
|||
|
|
@ -553,10 +553,7 @@ static inline pte_t pte_swp_clear_uffd_wp(pte_t pte)
|
|||
}
|
||||
#endif /* CONFIG_HAVE_ARCH_USERFAULTFD_WP */
|
||||
|
||||
#ifdef CONFIG_NUMA_BALANCING
|
||||
/*
|
||||
* See the comment in include/linux/pgtable.h
|
||||
*/
|
||||
#ifdef CONFIG_ARCH_HAS_PTE_PROTNONE
|
||||
static inline int pte_protnone(pte_t pte)
|
||||
{
|
||||
/*
|
||||
|
|
@ -575,7 +572,7 @@ static inline int pmd_protnone(pmd_t pmd)
|
|||
{
|
||||
return pte_protnone(pmd_pte(pmd));
|
||||
}
|
||||
#endif
|
||||
#endif /* CONFIG_ARCH_HAS_PTE_PROTNONE */
|
||||
|
||||
#define pmd_present(pmd) pte_present(pmd_pte(pmd))
|
||||
#define pmd_dirty(pmd) pte_dirty(pmd_pte(pmd))
|
||||
|
|
|
|||
|
|
@ -67,6 +67,7 @@ config LOONGARCH
|
|||
select ARCH_SUPPORTS_LTO_CLANG
|
||||
select ARCH_SUPPORTS_LTO_CLANG_THIN
|
||||
select ARCH_SUPPORTS_MSEAL_SYSTEM_MAPPINGS
|
||||
select ARCH_HAS_PTE_PROTNONE if 64BIT
|
||||
select ARCH_SUPPORTS_NUMA_BALANCING if NUMA
|
||||
select ARCH_SUPPORTS_PER_VMA_LOCK
|
||||
select ARCH_SUPPORTS_RT
|
||||
|
|
|
|||
|
|
@ -623,7 +623,7 @@ static inline pmd_t pmdp_huge_get_and_clear(struct mm_struct *mm,
|
|||
|
||||
#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
|
||||
|
||||
#ifdef CONFIG_NUMA_BALANCING
|
||||
#ifdef CONFIG_ARCH_HAS_PTE_PROTNONE
|
||||
static inline long pte_protnone(pte_t pte)
|
||||
{
|
||||
return (pte_val(pte) & _PAGE_PROTNONE);
|
||||
|
|
@ -633,7 +633,7 @@ static inline long pmd_protnone(pmd_t pmd)
|
|||
{
|
||||
return (pmd_val(pmd) & _PAGE_PROTNONE);
|
||||
}
|
||||
#endif /* CONFIG_NUMA_BALANCING */
|
||||
#endif /* CONFIG_ARCH_HAS_PTE_PROTNONE */
|
||||
|
||||
#define pmd_leaf(pmd) ((pmd_val(pmd) & _PAGE_HUGE) != 0)
|
||||
#define pud_leaf(pud) ((pud_val(pud) & _PAGE_HUGE) != 0)
|
||||
|
|
|
|||
|
|
@ -490,13 +490,13 @@ static inline pte_t pte_clear_soft_dirty(pte_t pte)
|
|||
}
|
||||
#endif /* CONFIG_HAVE_ARCH_SOFT_DIRTY */
|
||||
|
||||
#ifdef CONFIG_NUMA_BALANCING
|
||||
#ifdef CONFIG_ARCH_HAS_PTE_PROTNONE
|
||||
static inline int pte_protnone(pte_t pte)
|
||||
{
|
||||
return (pte_raw(pte) & cpu_to_be64(_PAGE_PRESENT | _PAGE_PTE | _PAGE_RWX)) ==
|
||||
cpu_to_be64(_PAGE_PRESENT | _PAGE_PTE);
|
||||
}
|
||||
#endif /* CONFIG_NUMA_BALANCING */
|
||||
#endif /* CONFIG_ARCH_HAS_PTE_PROTNONE */
|
||||
|
||||
static inline bool pte_hw_valid(pte_t pte)
|
||||
{
|
||||
|
|
@ -1067,12 +1067,12 @@ static inline pte_t *pmdp_ptep(pmd_t *pmd)
|
|||
#endif
|
||||
#endif /* CONFIG_HAVE_ARCH_SOFT_DIRTY */
|
||||
|
||||
#ifdef CONFIG_NUMA_BALANCING
|
||||
#ifdef CONFIG_ARCH_HAS_PTE_PROTNONE
|
||||
static inline int pmd_protnone(pmd_t pmd)
|
||||
{
|
||||
return pte_protnone(pmd_pte(pmd));
|
||||
}
|
||||
#endif /* CONFIG_NUMA_BALANCING */
|
||||
#endif /* CONFIG_ARCH_HAS_PTE_PROTNONE */
|
||||
|
||||
#define pmd_write(pmd) pte_write(pmd_pte(pmd))
|
||||
|
||||
|
|
|
|||
|
|
@ -87,6 +87,7 @@ config PPC_BOOK3S_64
|
|||
select ARCH_ENABLE_HUGEPAGE_MIGRATION if HUGETLB_PAGE && MIGRATION
|
||||
select ARCH_ENABLE_SPLIT_PMD_PTLOCK
|
||||
select ARCH_SUPPORTS_HUGETLBFS
|
||||
select ARCH_HAS_PTE_PROTNONE
|
||||
select ARCH_SUPPORTS_NUMA_BALANCING
|
||||
select HAVE_MOVE_PMD
|
||||
select HAVE_MOVE_PUD
|
||||
|
|
|
|||
|
|
@ -71,6 +71,7 @@ config RISCV
|
|||
select ARCH_SUPPORTS_MSEAL_SYSTEM_MAPPINGS if 64BIT && MMU
|
||||
select ARCH_SUPPORTS_PAGE_TABLE_CHECK if MMU
|
||||
select ARCH_SUPPORTS_PER_VMA_LOCK if MMU
|
||||
select ARCH_HAS_PTE_PROTNONE if MMU
|
||||
select ARCH_SUPPORTS_RT
|
||||
select ARCH_SUPPORTS_SHADOW_CALL_STACK if HAVE_SHADOW_CALL_STACK
|
||||
select ARCH_SUPPORTS_SCHED_MC if SMP
|
||||
|
|
|
|||
|
|
@ -534,10 +534,7 @@ static inline pte_t pte_swp_clear_soft_dirty(pte_t pte)
|
|||
PAGE_SIZE)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NUMA_BALANCING
|
||||
/*
|
||||
* See the comment in include/asm-generic/pgtable.h
|
||||
*/
|
||||
#ifdef CONFIG_ARCH_HAS_PTE_PROTNONE
|
||||
static inline int pte_protnone(pte_t pte)
|
||||
{
|
||||
return (pte_val(pte) & (_PAGE_PRESENT | _PAGE_PROT_NONE)) == _PAGE_PROT_NONE;
|
||||
|
|
@ -547,7 +544,7 @@ static inline int pmd_protnone(pmd_t pmd)
|
|||
{
|
||||
return pte_protnone(pmd_pte(pmd));
|
||||
}
|
||||
#endif
|
||||
#endif /* CONFIG_ARCH_HAS_PTE_PROTNONE */
|
||||
|
||||
/* Modify page protection bits */
|
||||
static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
|
||||
|
|
|
|||
|
|
@ -148,6 +148,7 @@ config S390
|
|||
select ARCH_SUPPORTS_HUGETLBFS
|
||||
select ARCH_SUPPORTS_INT128 if CC_HAS_INT128 && CC_IS_CLANG
|
||||
select ARCH_SUPPORTS_MSEAL_SYSTEM_MAPPINGS
|
||||
select ARCH_HAS_PTE_PROTNONE
|
||||
select ARCH_SUPPORTS_NUMA_BALANCING
|
||||
select ARCH_SUPPORTS_PAGE_TABLE_CHECK
|
||||
select ARCH_SUPPORTS_PER_VMA_LOCK
|
||||
|
|
|
|||
|
|
@ -842,7 +842,7 @@ static inline int pte_same(pte_t a, pte_t b)
|
|||
return pte_val(a) == pte_val(b);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NUMA_BALANCING
|
||||
#ifdef CONFIG_ARCH_HAS_PTE_PROTNONE
|
||||
static inline int pte_protnone(pte_t pte)
|
||||
{
|
||||
return pte_present(pte) && !(pte_val(pte) & _PAGE_READ);
|
||||
|
|
@ -853,7 +853,7 @@ static inline int pmd_protnone(pmd_t pmd)
|
|||
/* pmd_leaf(pmd) implies pmd_present(pmd) */
|
||||
return pmd_leaf(pmd) && !(pmd_val(pmd) & _SEGMENT_ENTRY_READ);
|
||||
}
|
||||
#endif
|
||||
#endif /* CONFIG_ARCH_HAS_PTE_PROTNONE */
|
||||
|
||||
static inline bool pte_swp_exclusive(pte_t pte)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -124,6 +124,7 @@ config X86
|
|||
select ARCH_SUPPORTS_DEBUG_PAGEALLOC
|
||||
select ARCH_SUPPORTS_HUGETLBFS
|
||||
select ARCH_SUPPORTS_PAGE_TABLE_CHECK if X86_64
|
||||
select ARCH_HAS_PTE_PROTNONE if X86_64
|
||||
select ARCH_SUPPORTS_NUMA_BALANCING if X86_64
|
||||
select ARCH_SUPPORTS_KMAP_LOCAL_FORCE_MAP if NR_CPUS <= 4096
|
||||
select ARCH_SUPPORTS_CFI if X86_64
|
||||
|
|
|
|||
|
|
@ -985,11 +985,7 @@ static inline int pmd_present(pmd_t pmd)
|
|||
return pmd_flags(pmd) & (_PAGE_PRESENT | _PAGE_PROTNONE | _PAGE_PSE);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NUMA_BALANCING
|
||||
/*
|
||||
* These work without NUMA balancing but the kernel does not care. See the
|
||||
* comment in include/linux/pgtable.h
|
||||
*/
|
||||
#ifdef CONFIG_ARCH_HAS_PTE_PROTNONE
|
||||
static inline int pte_protnone(pte_t pte)
|
||||
{
|
||||
return (pte_flags(pte) & (_PAGE_PROTNONE | _PAGE_PRESENT))
|
||||
|
|
@ -1001,7 +997,7 @@ static inline int pmd_protnone(pmd_t pmd)
|
|||
return (pmd_flags(pmd) & (_PAGE_PROTNONE | _PAGE_PRESENT))
|
||||
== _PAGE_PROTNONE;
|
||||
}
|
||||
#endif /* CONFIG_NUMA_BALANCING */
|
||||
#endif /* CONFIG_ARCH_HAS_PTE_PROTNONE */
|
||||
|
||||
static inline int pmd_none(pmd_t pmd)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2110,18 +2110,26 @@ static inline int pud_trans_unstable(pud_t *pud)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_NUMA_BALANCING
|
||||
#ifndef CONFIG_ARCH_HAS_PTE_PROTNONE
|
||||
/*
|
||||
* In an inaccessible (PROT_NONE) VMA, pte_protnone() may indicate "yes". It is
|
||||
* perfectly valid to indicate "no" in that case, which is why our default
|
||||
* implementation defaults to "always no".
|
||||
* In an inaccessible (PROT_NONE) VMA, pte_protnone() may indicate "yes". It
|
||||
* is perfectly valid to indicate "no" in that case, which is why our
|
||||
* default implementation defaults to "always no".
|
||||
*
|
||||
* In an accessible VMA, however, pte_protnone() reliably indicates PROT_NONE
|
||||
* page protection due to NUMA hinting. NUMA hinting faults only apply in
|
||||
* accessible VMAs.
|
||||
* In an accessible VMA, pte_protnone() reliably indicates a present
|
||||
* PROT_NONE page protection. Today the kernel uses such PTEs for two
|
||||
* purposes: NUMA hinting faults, and userfaultfd RWP tracking on
|
||||
* VM_UFFD_RWP VMAs. The two are distinguished by the uffd PTE bit and
|
||||
* the VMA flag; see include/linux/userfaultfd_k.h.
|
||||
*
|
||||
* So, to reliably identify PROT_NONE PTEs that require a NUMA hinting fault,
|
||||
* looking at the VMA accessibility is sufficient.
|
||||
* So, to reliably identify PROT_NONE PTEs that require kernel handling,
|
||||
* looking at the VMA accessibility (and the uffd bit on RWP VMAs) is
|
||||
* sufficient.
|
||||
*
|
||||
* Architectures without CONFIG_ARCH_HAS_PTE_PROTNONE get the always-zero
|
||||
* stubs below; PAGE_NONE references that survive to runtime fire the
|
||||
* BUILD_BUG() fallback, since callers should have folded such paths to
|
||||
* dead code via IS_ENABLED(CONFIG_ARCH_HAS_PTE_PROTNONE).
|
||||
*/
|
||||
static inline int pte_protnone(pte_t pte)
|
||||
{
|
||||
|
|
@ -2132,7 +2140,11 @@ static inline int pmd_protnone(pmd_t pmd)
|
|||
{
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_NUMA_BALANCING */
|
||||
|
||||
#ifndef PAGE_NONE
|
||||
#define PAGE_NONE ({ BUILD_BUG(); (pgprot_t){0}; })
|
||||
#endif
|
||||
#endif /* CONFIG_ARCH_HAS_PTE_PROTNONE */
|
||||
|
||||
#endif /* CONFIG_MMU */
|
||||
|
||||
|
|
|
|||
|
|
@ -947,6 +947,13 @@ config SCHED_PROXY_EXEC
|
|||
|
||||
endmenu
|
||||
|
||||
#
|
||||
# For architectures that support present-but-inaccessible (PROT_NONE) page
|
||||
# table entries detectable via pte_protnone() / pmd_protnone():
|
||||
#
|
||||
config ARCH_HAS_PTE_PROTNONE
|
||||
bool
|
||||
|
||||
#
|
||||
# For architectures that want to enable the support for NUMA-affine scheduler
|
||||
# balancing logic:
|
||||
|
|
@ -1013,6 +1020,7 @@ config ARCH_WANT_NUMA_VARIABLE_LOCALITY
|
|||
config NUMA_BALANCING
|
||||
bool "Memory placement aware NUMA scheduler"
|
||||
depends on ARCH_SUPPORTS_NUMA_BALANCING
|
||||
depends on ARCH_HAS_PTE_PROTNONE
|
||||
depends on !ARCH_WANT_NUMA_VARIABLE_LOCALITY
|
||||
depends on SMP && NUMA_MIGRATION && !PREEMPT_RT
|
||||
help
|
||||
|
|
|
|||
|
|
@ -672,7 +672,7 @@ static void __init pte_protnone_tests(struct pgtable_debug_args *args)
|
|||
{
|
||||
pte_t pte = pfn_pte(args->fixed_pte_pfn, args->page_prot_none);
|
||||
|
||||
if (!IS_ENABLED(CONFIG_NUMA_BALANCING))
|
||||
if (!IS_ENABLED(CONFIG_ARCH_HAS_PTE_PROTNONE))
|
||||
return;
|
||||
|
||||
pr_debug("Validating PTE protnone\n");
|
||||
|
|
@ -685,7 +685,7 @@ static void __init pmd_protnone_tests(struct pgtable_debug_args *args)
|
|||
{
|
||||
pmd_t pmd;
|
||||
|
||||
if (!IS_ENABLED(CONFIG_NUMA_BALANCING))
|
||||
if (!IS_ENABLED(CONFIG_ARCH_HAS_PTE_PROTNONE))
|
||||
return;
|
||||
|
||||
if (!has_transparent_hugepage())
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user