| Seq | Timestamp | Type | Name | Duration |
|---|---|---|---|---|
| 0/0 | 2026/09/09 11:36 | flow | patch-triage |
0mArgs:null Results: {
"EnableConfigs": [
"TRANSPARENT_HUGEPAGE"
],
"FocusSymbols": [
"pudp_invalidate",
"change_huge_pud"
],
"KMSANReasoning": "The patch series introduces support for Transparent Huge Page (THP) PUDs and PUD PFNMAP on arm64, while consolidating the generic `pudp_invalidate()` implementation in `mm/pgtable-generic.c` across architectures (x86, riscv, powerpc).\n\nThese changes only manipulate architectural page table entries (PUD/PMD/PTE bit-flags, page table establishment, and TLB invalidation). The patch does not introduce new memory allocations, copy data to/from userspace, alter struct padding/initialization, or create paths where uninitialized stack/heap/page memory could be evaluated or leaked. Therefore, standard KASAN/debug builds are sufficient and a dedicated KMSAN session is not required.",
"NeedsKMSAN": false,
"Reasoning": "The patch introduces a generic implementation of pudp_invalidate() in mm/pgtable-generic.c (replacing architecture-specific implementations on x86 and riscv), which is used on amd64 when transparent huge pages at PUD level are enabled. This touches core memory management code and includes runtime assertions (VM_WARN_ON_ONCE) in reachable paths executed by change_huge_pud().",
"WorthFuzzing": true
} |
| 1/1 | 2026/09/09 11:36 | action | read-patch-diff |
0mArgs:null Results: {
"PatchDiff": "commit ed83d9c3feb51ce7a4f6f133908a6db01fc6e789\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate: Wed Sep 9 11:36:38 2026 +0000\n\n syz-cluster: applied patch under review\n\ndiff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig\nindex b5a51b0ef9440..8a7ca1863595a 100644\n--- a/arch/arm64/Kconfig\n+++ b/arch/arm64/Kconfig\n@@ -173,6 +173,7 @@ config ARM64\n \tselect HAVE_ARCH_THREAD_STRUCT_WHITELIST\n \tselect HAVE_ARCH_TRACEHOOK\n \tselect HAVE_ARCH_TRANSPARENT_HUGEPAGE\n+\tselect HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD if PAGE_SIZE_4KB\n \tselect HAVE_ARCH_VMAP_STACK\n \tselect HAVE_ARM_SMCCC\n \tselect HAVE_ASM_MODVERSIONS\ndiff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h\nindex 6000905a2e865..fdc338970934d 100644\n--- a/arch/arm64/include/asm/pgtable.h\n+++ b/arch/arm64/include/asm/pgtable.h\n@@ -243,18 +243,6 @@ static inline pte_t set_pte_bit(pte_t pte, pgprot_t prot)\n \treturn pte;\n }\n \n-static inline pmd_t clear_pmd_bit(pmd_t pmd, pgprot_t prot)\n-{\n-\tpmd_val(pmd) \u0026= ~pgprot_val(prot);\n-\treturn pmd;\n-}\n-\n-static inline pmd_t set_pmd_bit(pmd_t pmd, pgprot_t prot)\n-{\n-\tpmd_val(pmd) |= pgprot_val(prot);\n-\treturn pmd;\n-}\n-\n static inline pte_t pte_mkwrite_novma(pte_t pte)\n {\n \tpte = set_pte_bit(pte, __pgprot(PTE_WRITE));\n@@ -619,11 +607,13 @@ static inline pmd_t pmd_mkhuge(pmd_t pmd)\n }\n \n #ifdef CONFIG_ARCH_SUPPORTS_PMD_PFNMAP\n-#define pmd_special(pte)\t(!!((pmd_val(pte) \u0026 PTE_SPECIAL)))\n-static inline pmd_t pmd_mkspecial(pmd_t pmd)\n-{\n-\treturn set_pmd_bit(pmd, __pgprot(PTE_SPECIAL));\n-}\n+#define pmd_special(pmd)\tpte_special(pmd_pte(pmd))\n+#define pmd_mkspecial(pmd)\tpte_pmd(pte_mkspecial(pmd_pte(pmd)))\n+#endif\n+\n+#ifdef CONFIG_ARCH_SUPPORTS_PUD_PFNMAP\n+#define pud_special(pud)\tpte_special(pud_pte(pud))\n+#define pud_mkspecial(pud)\tpte_pud(pte_mkspecial(pud_pte(pud)))\n #endif\n \n #define __pmd_to_phys(pmd)\t__pte_to_phys(pmd_pte(pmd))\n@@ -634,8 +624,15 @@ static inline pmd_t pmd_mkspecial(pmd_t pmd)\n #define pud_young(pud)\t\tpte_young(pud_pte(pud))\n #define pud_mkyoung(pud)\tpte_pud(pte_mkyoung(pud_pte(pud)))\n #define pud_mkwrite_novma(pud)\tpte_pud(pte_mkwrite_novma(pud_pte(pud)))\n+#define pud_mkwrite(pud)\tpud_mkwrite_novma(pud)\n #define pud_mkvalid_k(pud)\tpte_pud(pte_mkvalid_k(pud_pte(pud)))\n #define pud_write(pud)\t\tpte_write(pud_pte(pud))\n+#define pud_dirty(pud)\t\tpte_dirty(pud_pte(pud))\n+#define pud_wrprotect(pud)\tpte_pud(pte_wrprotect(pud_pte(pud)))\n+#define pud_mkdirty(pud)\tpte_pud(pte_mkdirty(pud_pte(pud)))\n+#define pud_mkold(pud)\t\tpte_pud(pte_mkold(pud_pte(pud)))\n+#define pud_mkinvalid(pud)\tpte_pud(pte_mkinvalid(pud_pte(pud)))\n+#define pud_mkclean(pud)\tpte_pud(pte_mkclean(pud_pte(pud)))\n \n static inline pud_t pud_mkhuge(pud_t pud)\n {\n@@ -886,6 +883,13 @@ static inline bool pud_leaf(pud_t pud)\n #define pud_user(pud)\t\tpte_user(pud_pte(pud))\n #define pud_user_exec(pud)\tpte_user_exec(pud_pte(pud))\n \n+#ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD\n+static inline int pud_trans_huge(pud_t pud)\n+{\n+\treturn pud_present(pud) \u0026\u0026 !pud_table(__pud(pud_val(pud) | PTE_VALID));\n+}\n+#endif\n+\n static inline bool pgtable_l4_enabled(void);\n \n static inline void set_pud(pud_t *pudp, pud_t pud)\n@@ -1252,6 +1256,11 @@ static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot)\n \treturn pte_pmd(pte_modify(pmd_pte(pmd), newprot));\n }\n \n+static inline pud_t pud_modify(pud_t pud, pgprot_t newprot)\n+{\n+\treturn pte_pud(pte_modify(pud_pte(pud), newprot));\n+}\n+\n extern int __ptep_set_access_flags_anysz(struct vm_area_struct *vma,\n \t\t\t\t\t unsigned long address, pte_t *ptep,\n \t\t\t\t\t pte_t entry, int dirty,\n@@ -1276,6 +1285,16 @@ static inline int pmdp_set_access_flags(struct vm_area_struct *vma,\n }\n #endif\n \n+#ifdef CONFIG_ARCH_SUPPORTS_PUD_PFNMAP\n+static inline int pudp_set_access_flags(struct vm_area_struct *vma,\n+\t\t\t\t\tunsigned long address, pud_t *pudp,\n+\t\t\t\t\tpud_t entry, int dirty)\n+{\n+\treturn __ptep_set_access_flags_anysz(vma, address, (pte_t *)pudp,\n+\t\t\t\t\t pud_pte(entry), dirty, PUD_SIZE);\n+}\n+#endif\n+\n #ifdef CONFIG_PAGE_TABLE_CHECK\n static inline bool pte_user_accessible_page(struct mm_struct *mm, unsigned long addr, pte_t pte)\n {\n@@ -1350,6 +1369,14 @@ static inline bool pmdp_test_and_clear_young(struct vm_area_struct *vma,\n }\n #endif /* CONFIG_TRANSPARENT_HUGEPAGE || CONFIG_ARCH_HAS_NONLEAF_PMD_YOUNG */\n \n+#ifdef CONFIG_ARCH_SUPPORTS_PUD_PFNMAP\n+static inline bool pudp_test_and_clear_young(struct vm_area_struct *vma,\n+\t\tunsigned long address, pud_t *pudp)\n+{\n+\treturn __ptep_test_and_clear_young(vma, address, (pte_t *)pudp);\n+}\n+#endif\n+\n static inline pte_t __ptep_get_and_clear_anysz(struct mm_struct *mm,\n \t\t\t\t\t unsigned long address,\n \t\t\t\t\t pte_t *ptep,\n@@ -1512,6 +1539,15 @@ static inline pmd_t pmdp_establish(struct vm_area_struct *vma,\n }\n #endif\n \n+#ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD\n+static inline pud_t pudp_establish(struct vm_area_struct *vma,\n+\t\tunsigned long address, pud_t *pudp, pud_t pud)\n+{\n+\tpage_table_check_pud_set(vma-\u003evm_mm, address, pudp, pud);\n+\treturn __pud(xchg_relaxed(\u0026pud_val(*pudp), pud_val(pud)));\n+}\n+#endif\n+\n /*\n * Encode and decode a swap entry:\n *\tbits 0-1:\tpresent (must be zero)\n@@ -1586,6 +1622,7 @@ static inline void update_mmu_cache_range(struct vm_fault *vmf,\n #define update_mmu_cache(vma, addr, ptep) \\\n \tupdate_mmu_cache_range(NULL, vma, addr, ptep, 1)\n #define update_mmu_cache_pmd(vma, address, pmd) do { } while (0)\n+#define update_mmu_cache_pud(vma, address, pud) do { } while (0)\n \n #ifdef CONFIG_ARM64_PA_BITS_52\n #define phys_to_ttbr(addr)\t(((addr) | ((addr) \u003e\u003e 46)) \u0026 TTBR_BADDR_MASK_52)\ndiff --git a/arch/powerpc/include/asm/book3s/64/pgtable.h b/arch/powerpc/include/asm/book3s/64/pgtable.h\nindex f4db7d7fbd5c6..55d33c5537f13 100644\n--- a/arch/powerpc/include/asm/book3s/64/pgtable.h\n+++ b/arch/powerpc/include/asm/book3s/64/pgtable.h\n@@ -1419,6 +1419,7 @@ static inline pgtable_t pgtable_trans_huge_withdraw(struct mm_struct *mm,\n #define __HAVE_ARCH_PMDP_INVALIDATE\n extern pmd_t pmdp_invalidate(struct vm_area_struct *vma, unsigned long address,\n \t\t\t pmd_t *pmdp);\n+#define __HAVE_ARCH_PUDP_INVALIDATE\n extern pud_t pudp_invalidate(struct vm_area_struct *vma, unsigned long address,\n \t\t\t pud_t *pudp);\n \ndiff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h\nindex 40b1ed4f3ea89..327fa378032b7 100644\n--- a/arch/riscv/include/asm/pgtable.h\n+++ b/arch/riscv/include/asm/pgtable.h\n@@ -1159,9 +1159,6 @@ static inline pud_t pud_mkinvalid(pud_t pud)\n \treturn __pud(pud_val(pud) \u0026 ~(_PAGE_PRESENT | _PAGE_PROT_NONE));\n }\n \n-extern pud_t pudp_invalidate(struct vm_area_struct *vma, unsigned long address,\n-\t\t\t pud_t *pudp);\n-\n static inline pud_t pud_modify(pud_t pud, pgprot_t newprot)\n {\n \treturn pte_pud(pte_modify(pud_pte(pud), newprot));\ndiff --git a/arch/riscv/mm/pgtable.c b/arch/riscv/mm/pgtable.c\nindex 9c4427d0b1874..156e385e7db44 100644\n--- a/arch/riscv/mm/pgtable.c\n+++ b/arch/riscv/mm/pgtable.c\n@@ -154,15 +154,6 @@ pmd_t pmdp_collapse_flush(struct vm_area_struct *vma,\n \treturn pmd;\n }\n \n-pud_t pudp_invalidate(struct vm_area_struct *vma, unsigned long address,\n-\t\t pud_t *pudp)\n-{\n-\tVM_WARN_ON_ONCE(!pud_present(*pudp));\n-\tpud_t old = pudp_establish(vma, address, pudp, pud_mkinvalid(*pudp));\n-\n-\tflush_pud_tlb_range(vma, address, address + HPAGE_PUD_SIZE);\n-\treturn old;\n-}\n #endif /* CONFIG_TRANSPARENT_HUGEPAGE */\n \n pte_t pte_mkwrite(pte_t pte, struct vm_area_struct *vma)\ndiff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h\nindex d5f4917c1edcb..97051c02385e8 100644\n--- a/arch/x86/include/asm/pgtable.h\n+++ b/arch/x86/include/asm/pgtable.h\n@@ -1387,9 +1387,6 @@ static inline pud_t pudp_establish(struct vm_area_struct *vma,\n extern pmd_t pmdp_invalidate_ad(struct vm_area_struct *vma,\n \t\t\t\tunsigned long address, pmd_t *pmdp);\n \n-pud_t pudp_invalidate(struct vm_area_struct *vma, unsigned long address,\n-\t\t pud_t *pudp);\n-\n /*\n * Page table pages are page-aligned. The lower half of the top\n * level is used for userspace and the top half for the kernel.\ndiff --git a/arch/x86/mm/pgtable.c b/arch/x86/mm/pgtable.c\nindex cb03f5a2b2433..0945908631dc5 100644\n--- a/arch/x86/mm/pgtable.c\n+++ b/arch/x86/mm/pgtable.c\n@@ -519,18 +519,6 @@ pmd_t pmdp_invalidate_ad(struct vm_area_struct *vma, unsigned long address,\n }\n #endif\n \n-#if defined(CONFIG_TRANSPARENT_HUGEPAGE) \u0026\u0026 \\\n-\tdefined(CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD)\n-pud_t pudp_invalidate(struct vm_area_struct *vma, unsigned long address,\n-\t\t pud_t *pudp)\n-{\n-\tVM_WARN_ON_ONCE(!pud_present(*pudp));\n-\tpud_t old = pudp_establish(vma, address, pudp, pud_mkinvalid(*pudp));\n-\tflush_pud_tlb_range(vma, address, address + HPAGE_PUD_SIZE);\n-\treturn old;\n-}\n-#endif\n-\n /**\n * reserve_top_address - Reserve a hole in the top of the kernel address space\n * @reserve: Size of hole to reserve\ndiff --git a/include/linux/pgtable.h b/include/linux/pgtable.h\nindex 8c093c119e5a8..32173005b087f 100644\n--- a/include/linux/pgtable.h\n+++ b/include/linux/pgtable.h\n@@ -1318,6 +1318,13 @@ extern pmd_t pmdp_invalidate_ad(struct vm_area_struct *vma,\n \t\t\t\tunsigned long address, pmd_t *pmdp);\n #endif\n \n+#ifndef __HAVE_ARCH_PUDP_INVALIDATE\n+#ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD\n+extern pud_t pudp_invalidate(struct vm_area_struct *vma, unsigned long address,\n+\t\t\t pud_t *pudp);\n+#endif\n+#endif\n+\n #ifndef __HAVE_ARCH_PTE_SAME\n static inline int pte_same(pte_t pte_a, pte_t pte_b)\n {\ndiff --git a/mm/pgtable-generic.c b/mm/pgtable-generic.c\nindex b91b1a98029c7..ac1175d9a59a7 100644\n--- a/mm/pgtable-generic.c\n+++ b/mm/pgtable-generic.c\n@@ -217,6 +217,20 @@ pmd_t pmdp_invalidate_ad(struct vm_area_struct *vma, unsigned long address,\n }\n #endif\n \n+#ifndef __HAVE_ARCH_PUDP_INVALIDATE\n+#ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD\n+pud_t pudp_invalidate(struct vm_area_struct *vma, unsigned long address,\n+\t\t pud_t *pudp)\n+{\n+\tVM_WARN_ON_ONCE(!pud_present(*pudp));\n+\tpud_t old = pudp_establish(vma, address, pudp, pud_mkinvalid(*pudp));\n+\n+\tflush_pud_tlb_range(vma, address, address + HPAGE_PUD_SIZE);\n+\treturn old;\n+}\n+#endif\n+#endif\n+\n #ifndef pmdp_collapse_flush\n pmd_t pmdp_collapse_flush(struct vm_area_struct *vma, unsigned long address,\n \t\t\t pmd_t *pmdp)\n"
} |
| 2/1 | 2026/09/09 11:36 | agent | patch-evaluator |
0mModel:core Args: null Results: {
"EnableConfigs": [
"TRANSPARENT_HUGEPAGE"
],
"FocusSymbols": [
"pudp_invalidate",
"change_huge_pud"
],
"Reasoning": "The patch introduces a generic implementation of pudp_invalidate() in mm/pgtable-generic.c (replacing architecture-specific implementations on x86 and riscv), which is used on amd64 when transparent huge pages at PUD level are enabled. This touches core memory management code and includes runtime assertions (VM_WARN_ON_ONCE) in reachable paths executed by change_huge_pud().",
"WorthFuzzing": true
}Instruction: You are an expert Linux kernel maintainer and security engineer.
Your job is to review a provided patch series and evaluate whether it warrants fuzzing with syzkaller.
IMPORTANT: The changes have ALREADY been applied and committed as the HEAD commit in
your workspace. Do NOT rely on internal assumptions. You must actively use your code access
tools to inspect the actual source code, callers, and surrounding context.
================================================================================
1. CORE TRIAGE PHILOSOPHY
================================================================================
The goal of patch fuzzing is to discover crashes, regressions, exposed latent bugs,
and newly triggered assertions introduced by the patch series.
- REACHABILITY IS THE PRIMARY GATE:
Fuzzing can only discover bugs in code that can actually execute in standard virtualized
environments (GCE or QEMU, utilizing software-emulated devices like USB gadgets, netdev, tun/tap).
If the modified code is structurally unreachable (see Section 2), it MUST NOT be fuzzed,
regardless of whether it adds assertions or complex logic.
- DO NOT BLINDLY TRUST "NO FUNCTIONAL CHANGE" (NFCI) OR "REFACTORING" CLAIMS:
Patch authors routinely label changes as "cleanups", "refactorings", or state
"No functional change intended". Do NOT take these claims at face value.
Code refactorings that rearrange logic, introduce helper functions, or alter state management
in core subsystems frequently introduce subtle semantic shifts or uncover latent kernel bugs.
If reachable executable code is modified or refactored, it MUST be fuzzed.
- NEW OR MODIFIED ASSERTIONS IN REACHABLE CODE MUST BE FUZZED:
When a patch introduces or modifies runtime checks or assertions (e.g., WARN_ON*, VM_WARN_ON*,
BUG_ON*, lockdep_assert*) in reachable code paths, it enforces new or stricter invariants.
Even if the author believes the invariant always holds, fuzzing is essential to verify whether
an unusual sequence of operations can violate it.
================================================================================
2. WHEN TO RETURN WorthFuzzing=false (NEGATIVE CRITERIA)
================================================================================
Return WorthFuzzing=false ONLY IF all modified code falls strictly into one or more of these categories:
- Non-kernel and non-executable changes:
* Modifications to Documentation/, comments, or spelling fixes.
* User-space directories, self-tests, samples, or scripts (e.g., tools/, samples/, scripts/, usr/)
that do not affect the compiled kernel image (vmlinux) or kernel modules.
* Purely decorative logging (e.g., message strings in pr_err, printk, dev_info) or tracepoints
that do not alter control flow or data structures.
* Build system or Kconfig changes that do not alter compiled C logic.
- Structurally unreachable hardware:
* Vendor-specific PCIe switches, SmartNICs, or GPU drivers (e.g., mlxsw, pds_core, qed,
ionic, amdgpu) requiring physical ASIC/PCIe cards not emulated in standard QEMU.
- Unreachable execution paths:
* Driver teardown callbacks (.remove, .shutdown, pci_unregister_driver) executed only during
physical PCI hot-unplug or manual sysfs driver unbinding.
* Code paths exclusive to architectures other than the target architecture.
================================================================================
3. WHEN TO RETURN WorthFuzzing=true (POSITIVE CRITERIA)
================================================================================
Return WorthFuzzing=true whenever the patch touches reachable executable code, including:
- Core Subsystems:
* Any logic modifications in memory management (mm/), synchronization/locking (kernel/locking/),
BPF, scheduler, core networking, VFS, or syscall handling.
- Refactorings and Code Cleanups:
* Any restructuring of reachable data structures, helper abstractions, or algorithm flows.
- Runtime Assertions and Defensive Checks:
* Any introduction or alteration of assertions (WARN_ON*, VM_WARN_ON*, BUG_ON*, etc.) in reachable paths.
- Reachable Drivers and Protocols:
* Drivers accessible via virtual buses (virtio, USB gadget, loopback, netlink, binder, sockets, etc.).
================================================================================
4. EXTRACTING FocusSymbols (PREVENTING DILUTION)
================================================================================
When WorthFuzzing=true, you must extract specific kernel functions into FocusSymbols to guide the fuzzer:
- AVOID UBIQUITOUS LIFECYCLE HOT-PATHS:
Do NOT list generic, ubiquitous functions called by almost every program in the corpus
(including, but not limited to: general memory allocators and deallocators, page fault
and trap handlers, or core synchronization primitives; this is not an exhaustive list).
Listing ubiquitous functions causes the fuzzer to classify thousands of unrelated tests as "focused",
which severely dilutes fuzzing effort away from the actual changes.
- TARGET SPECIFIC FEATURE LOGIC AND ENTRYPOINTS:
List functions that specifically implement the logic being added or altered, or direct API entrypoints
for the subsystem feature under review.
- HANDLING STATIC INLINE FUNCTIONS IN HEADERS (.h):
Compiler-inlined static functions (such as static inlines in mm/*.h or include/linux/*.h) lack
distinct symbol addresses in vmlinux and cannot be targeted directly by symbol coverage filters.
If the changes are primarily in static inline helpers, identify non-static, feature-specific caller
functions in .c files that exercise them (avoiding ubiquitous lifecycle wrappers).
================================================================================
5. IDENTIFYING EnableConfigs
================================================================================
Identify any specific CONFIG_ options required to properly compile and reach the modified code:
- Inspect Kconfig files and #ifdef guards; do not make assumptions.
- Check "depends on" lines in Kconfig to include any non-standard parent subsystem configs needed.
- Strip any 'CONFIG_' prefix (e.g., return "NET_IPV4" instead of "CONFIG_NET_IPV4").
Prefer calling several tools at the same time to save round-trips.
Use set-results tool to provide results of the analysis.
It must be called exactly once before the final reply.
Ignore results of this tool.
Prompt: Target architecture: amd64
For your convenience, here is the diff of the changes:
commit ed83d9c3feb51ce7a4f6f133908a6db01fc6e789
Author: syz-cluster <triage@syzkaller.com>
Date: Wed Sep 9 11:36:38 2026 +0000
syz-cluster: applied patch under review
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index b5a51b0ef9440..8a7ca1863595a 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -173,6 +173,7 @@ config ARM64
select HAVE_ARCH_THREAD_STRUCT_WHITELIST
select HAVE_ARCH_TRACEHOOK
select HAVE_ARCH_TRANSPARENT_HUGEPAGE
+ select HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD if PAGE_SIZE_4KB
select HAVE_ARCH_VMAP_STACK
select HAVE_ARM_SMCCC
select HAVE_ASM_MODVERSIONS
diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
index 6000905a2e865..fdc338970934d 100644
--- a/arch/arm64/include/asm/pgtable.h
+++ b/arch/arm64/include/asm/pgtable.h
@@ -243,18 +243,6 @@ static inline pte_t set_pte_bit(pte_t pte, pgprot_t prot)
return pte;
}
-static inline pmd_t clear_pmd_bit(pmd_t pmd, pgprot_t prot)
-{
- pmd_val(pmd) &= ~pgprot_val(prot);
- return pmd;
-}
-
-static inline pmd_t set_pmd_bit(pmd_t pmd, pgprot_t prot)
-{
- pmd_val(pmd) |= pgprot_val(prot);
- return pmd;
-}
-
static inline pte_t pte_mkwrite_novma(pte_t pte)
{
pte = set_pte_bit(pte, __pgprot(PTE_WRITE));
@@ -619,11 +607,13 @@ static inline pmd_t pmd_mkhuge(pmd_t pmd)
}
#ifdef CONFIG_ARCH_SUPPORTS_PMD_PFNMAP
-#define pmd_special(pte) (!!((pmd_val(pte) & PTE_SPECIAL)))
-static inline pmd_t pmd_mkspecial(pmd_t pmd)
-{
- return set_pmd_bit(pmd, __pgprot(PTE_SPECIAL));
-}
+#define pmd_special(pmd) pte_special(pmd_pte(pmd))
+#define pmd_mkspecial(pmd) pte_pmd(pte_mkspecial(pmd_pte(pmd)))
+#endif
+
+#ifdef CONFIG_ARCH_SUPPORTS_PUD_PFNMAP
+#define pud_special(pud) pte_special(pud_pte(pud))
+#define pud_mkspecial(pud) pte_pud(pte_mkspecial(pud_pte(pud)))
#endif
#define __pmd_to_phys(pmd) __pte_to_phys(pmd_pte(pmd))
@@ -634,8 +624,15 @@ static inline pmd_t pmd_mkspecial(pmd_t pmd)
#define pud_young(pud) pte_young(pud_pte(pud))
#define pud_mkyoung(pud) pte_pud(pte_mkyoung(pud_pte(pud)))
#define pud_mkwrite_novma(pud) pte_pud(pte_mkwrite_novma(pud_pte(pud)))
+#define pud_mkwrite(pud) pud_mkwrite_novma(pud)
#define pud_mkvalid_k(pud) pte_pud(pte_mkvalid_k(pud_pte(pud)))
#define pud_write(pud) pte_write(pud_pte(pud))
+#define pud_dirty(pud) pte_dirty(pud_pte(pud))
+#define pud_wrprotect(pud) pte_pud(pte_wrprotect(pud_pte(pud)))
+#define pud_mkdirty(pud) pte_pud(pte_mkdirty(pud_pte(pud)))
+#define pud_mkold(pud) pte_pud(pte_mkold(pud_pte(pud)))
+#define pud_mkinvalid(pud) pte_pud(pte_mkinvalid(pud_pte(pud)))
+#define pud_mkclean(pud) pte_pud(pte_mkclean(pud_pte(pud)))
static inline pud_t pud_mkhuge(pud_t pud)
{
@@ -886,6 +883,13 @@ static inline bool pud_leaf(pud_t pud)
#define pud_user(pud) pte_user(pud_pte(pud))
#define pud_user_exec(pud) pte_user_exec(pud_pte(pud))
+#ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD
+static inline int pud_trans_huge(pud_t pud)
+{
+ return pud_present(pud) && !pud_table(__pud(pud_val(pud) | PTE_VALID));
+}
+#endif
+
static inline bool pgtable_l4_enabled(void);
static inline void set_pud(pud_t *pudp, pud_t pud)
@@ -1252,6 +1256,11 @@ static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot)
return pte_pmd(pte_modify(pmd_pte(pmd), newprot));
}
+static inline pud_t pud_modify(pud_t pud, pgprot_t newprot)
+{
+ return pte_pud(pte_modify(pud_pte(pud), newprot));
+}
+
extern int __ptep_set_access_flags_anysz(struct vm_area_struct *vma,
unsigned long address, pte_t *ptep,
pte_t entry, int dirty,
@@ -1276,6 +1285,16 @@ static inline int pmdp_set_access_flags(struct vm_area_struct *vma,
}
#endif
+#ifdef CONFIG_ARCH_SUPPORTS_PUD_PFNMAP
+static inline int pudp_set_access_flags(struct vm_area_struct *vma,
+ unsigned long address, pud_t *pudp,
+ pud_t entry, int dirty)
+{
+ return __ptep_set_access_flags_anysz(vma, address, (pte_t *)pudp,
+ pud_pte(entry), dirty, PUD_SIZE);
+}
+#endif
+
#ifdef CONFIG_PAGE_TABLE_CHECK
static inline bool pte_user_accessible_page(struct mm_struct *mm, unsigned long addr, pte_t pte)
{
@@ -1350,6 +1369,14 @@ static inline bool pmdp_test_and_clear_young(struct vm_area_struct *vma,
}
#endif /* CONFIG_TRANSPARENT_HUGEPAGE || CONFIG_ARCH_HAS_NONLEAF_PMD_YOUNG */
+#ifdef CONFIG_ARCH_SUPPORTS_PUD_PFNMAP
+static inline bool pudp_test_and_clear_young(struct vm_area_struct *vma,
+ unsigned long address, pud_t *pudp)
+{
+ return __ptep_test_and_clear_young(vma, address, (pte_t *)pudp);
+}
+#endif
+
static inline pte_t __ptep_get_and_clear_anysz(struct mm_struct *mm,
unsigned long address,
pte_t *ptep,
@@ -1512,6 +1539,15 @@ static inline pmd_t pmdp_establish(struct vm_area_struct *vma,
}
#endif
+#ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD
+static inline pud_t pudp_establish(struct vm_area_struct *vma,
+ unsigned long address, pud_t *pudp, pud_t pud)
+{
+ page_table_check_pud_set(vma->vm_mm, address, pudp, pud);
+ return __pud(xchg_relaxed(&pud_val(*pudp), pud_val(pud)));
+}
+#endif
+
/*
* Encode and decode a swap entry:
* bits 0-1: present (must be zero)
@@ -1586,6 +1622,7 @@ static inline void update_mmu_cache_range(struct vm_fault *vmf,
#define update_mmu_cache(vma, addr, ptep) \
update_mmu_cache_range(NULL, vma, addr, ptep, 1)
#define update_mmu_cache_pmd(vma, address, pmd) do { } while (0)
+#define update_mmu_cache_pud(vma, address, pud) do { } while (0)
#ifdef CONFIG_ARM64_PA_BITS_52
#define phys_to_ttbr(addr) (((addr) | ((addr) >> 46)) & TTBR_BADDR_MASK_52)
diff --git a/arch/powerpc/include/asm/book3s/64/pgtable.h b/arch/powerpc/include/asm/book3s/64/pgtable.h
index f4db7d7fbd5c6..55d33c5537f13 100644
--- a/arch/powerpc/include/asm/book3s/64/pgtable.h
+++ b/arch/powerpc/include/asm/book3s/64/pgtable.h
@@ -1419,6 +1419,7 @@ static inline pgtable_t pgtable_trans_huge_withdraw(struct mm_struct *mm,
#define __HAVE_ARCH_PMDP_INVALIDATE
extern pmd_t pmdp_invalidate(struct vm_area_struct *vma, unsigned long address,
pmd_t *pmdp);
+#define __HAVE_ARCH_PUDP_INVALIDATE
extern pud_t pudp_invalidate(struct vm_area_struct *vma, unsigned long address,
pud_t *pudp);
diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h
index 40b1ed4f3ea89..327fa378032b7 100644
--- a/arch/riscv/include/asm/pgtable.h
+++ b/arch/riscv/include/asm/pgtable.h
@@ -1159,9 +1159,6 @@ static inline pud_t pud_mkinvalid(pud_t pud)
return __pud(pud_val(pud) & ~(_PAGE_PRESENT | _PAGE_PROT_NONE));
}
-extern pud_t pudp_invalidate(struct vm_area_struct *vma, unsigned long address,
- pud_t *pudp);
-
static inline pud_t pud_modify(pud_t pud, pgprot_t newprot)
{
return pte_pud(pte_modify(pud_pte(pud), newprot));
diff --git a/arch/riscv/mm/pgtable.c b/arch/riscv/mm/pgtable.c
index 9c4427d0b1874..156e385e7db44 100644
--- a/arch/riscv/mm/pgtable.c
+++ b/arch/riscv/mm/pgtable.c
@@ -154,15 +154,6 @@ pmd_t pmdp_collapse_flush(struct vm_area_struct *vma,
return pmd;
}
-pud_t pudp_invalidate(struct vm_area_struct *vma, unsigned long address,
- pud_t *pudp)
-{
- VM_WARN_ON_ONCE(!pud_present(*pudp));
- pud_t old = pudp_establish(vma, address, pudp, pud_mkinvalid(*pudp));
-
- flush_pud_tlb_range(vma, address, address + HPAGE_PUD_SIZE);
- return old;
-}
#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
pte_t pte_mkwrite(pte_t pte, struct vm_area_struct *vma)
diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h
index d5f4917c1edcb..97051c02385e8 100644
--- a/arch/x86/include/asm/pgtable.h
+++ b/arch/x86/include/asm/pgtable.h
@@ -1387,9 +1387,6 @@ static inline pud_t pudp_establish(struct vm_area_struct *vma,
extern pmd_t pmdp_invalidate_ad(struct vm_area_struct *vma,
unsigned long address, pmd_t *pmdp);
-pud_t pudp_invalidate(struct vm_area_struct *vma, unsigned long address,
- pud_t *pudp);
-
/*
* Page table pages are page-aligned. The lower half of the top
* level is used for userspace and the top half for the kernel.
diff --git a/arch/x86/mm/pgtable.c b/arch/x86/mm/pgtable.c
index cb03f5a2b2433..0945908631dc5 100644
--- a/arch/x86/mm/pgtable.c
+++ b/arch/x86/mm/pgtable.c
@@ -519,18 +519,6 @@ pmd_t pmdp_invalidate_ad(struct vm_area_struct *vma, unsigned long address,
}
#endif
-#if defined(CONFIG_TRANSPARENT_HUGEPAGE) && \
- defined(CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD)
-pud_t pudp_invalidate(struct vm_area_struct *vma, unsigned long address,
- pud_t *pudp)
-{
- VM_WARN_ON_ONCE(!pud_present(*pudp));
- pud_t old = pudp_establish(vma, address, pudp, pud_mkinvalid(*pudp));
- flush_pud_tlb_range(vma, address, address + HPAGE_PUD_SIZE);
- return old;
-}
-#endif
-
/**
* reserve_top_address - Reserve a hole in the top of the kernel address space
* @reserve: Size of hole to reserve
diff --git a/include/linux/pgtable.h b/include/linux/pgtable.h
index 8c093c119e5a8..32173005b087f 100644
--- a/include/linux/pgtable.h
+++ b/include/linux/pgtable.h
@@ -1318,6 +1318,13 @@ extern pmd_t pmdp_invalidate_ad(struct vm_area_struct *vma,
unsigned long address, pmd_t *pmdp);
#endif
+#ifndef __HAVE_ARCH_PUDP_INVALIDATE
+#ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD
+extern pud_t pudp_invalidate(struct vm_area_struct *vma, unsigned long address,
+ pud_t *pudp);
+#endif
+#endif
+
#ifndef __HAVE_ARCH_PTE_SAME
static inline int pte_same(pte_t pte_a, pte_t pte_b)
{
diff --git a/mm/pgtable-generic.c b/mm/pgtable-generic.c
index b91b1a98029c7..ac1175d9a59a7 100644
--- a/mm/pgtable-generic.c
+++ b/mm/pgtable-generic.c
@@ -217,6 +217,20 @@ pmd_t pmdp_invalidate_ad(struct vm_area_struct *vma, unsigned long address,
}
#endif
+#ifndef __HAVE_ARCH_PUDP_INVALIDATE
+#ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD
+pud_t pudp_invalidate(struct vm_area_struct *vma, unsigned long address,
+ pud_t *pudp)
+{
+ VM_WARN_ON_ONCE(!pud_present(*pudp));
+ pud_t old = pudp_establish(vma, address, pudp, pud_mkinvalid(*pudp));
+
+ flush_pud_tlb_range(vma, address, address + HPAGE_PUD_SIZE);
+ return old;
+}
+#endif
+#endif
+
#ifndef pmdp_collapse_flush
pmd_t pmdp_collapse_flush(struct vm_area_struct *vma, unsigned long address,
pmd_t *pmdp)
|
| 3/2 | 2026/09/09 11:36 | llm | patch-evaluator |
0mModel:gemini-3.7-flash Args: null Results: null Tokens: input: 7168 output: 18 thoughts: 966 Thoughts: **Analyzing the `pudp_invalidate` Patch: A Deep Dive** Okay, let's break this down. First, the target is AMD64, which is crucial context. I need to understand the implications for that architecture. I see that this patch modifies several architecture-specific `pgtable.h` files and related implementations. The changes are focused on `pudp_invalidate`, which suggests a modification to how page table entries, specifically PUDs (Page Upper Directory), are handled and invalidated. Specifically, I note these key modifications: * The `arch/arm64/Kconfig` change: It selects `HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD` under certain `PAGE_SIZE_4KB` conditions. This is a crucial dependency for the new, generalized `pudp_invalidate` and implies some ARM64 systems will benefit from this generic implementation. * `arch/arm64/include/asm/pgtable.h` is changed significantly: It updates some macros/functions related to PUDs, defines and updates functions (e.g., `pud_mkwrite`, `pud_dirty`, `pudp_set_access_flags`). These additions are important to understand how they interact with the overall page table invalidation. The definition of `pud_trans_huge` is very relevant in the context of huge pages. * The removal of `pudp_invalidate` from RISC-V and x86 files. This is the core of the change: the architecture-specific implementations are being removed. * The addition of a generic implementation in `mm/pgtable-generic.c`: This implementation is guarded by both `!__HAVE_ARCH_PUDP_INVALIDATE` and `CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD`. This means the new generic implementation is now being used if no architecture-specific version is available *and* if THP (Transparent Huge Pages) is configured. This is highly relevant for AMD64, as THP is a common and important feature. Now, let's zoom in on the x86 changes. The patch explicitly moves `pudp_invalidate` from `arch/x86/mm/pgtable.c` to `mm/pgtable-generic.c`. The code itself looks functionally identical. This means x86 (AMD64) is now using the generic version, which makes sense because x86 has `CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD` enabled when `TRANSPARENT_HUGEPAGE` is enabled and the architecture is x86\_64. This generic implementation's inclusion means it's now being utilized. Now, I need to see *how* `pudp_invalidate` is used in the kernel and what configurations and symbols are relevant to it. That's the next step; I need to understand the call sites and the surrounding code to grasp the complete impact and ensure there are no regressions. I'll need to do a `grep` through the code base for this function and the configurations around it. This is a potentially significant change to page table management, and I need to assess it thoroughly. |
| 4/2 | 2026/09/09 11:36 | tool | grepper |
0mArgs:{
"Expression": "pudp_invalidate"
}Results: {
"Output": "arch/powerpc/include/asm/book3s/64/pgtable.h=1420=extern pmd_t pmdp_invalidate(struct vm_area_struct *vma, unsigned long address,\n--\narch/powerpc/include/asm/book3s/64/pgtable.h-1422-#define __HAVE_ARCH_PUDP_INVALIDATE\narch/powerpc/include/asm/book3s/64/pgtable.h:1423:extern pud_t pudp_invalidate(struct vm_area_struct *vma, unsigned long address,\narch/powerpc/include/asm/book3s/64/pgtable.h-1424-\t\t\t pud_t *pudp);\n--\narch/powerpc/mm/book3s64/pgtable.c=155=pmd_t pmdp_invalidate(struct vm_area_struct *vma, unsigned long address,\n--\narch/powerpc/mm/book3s64/pgtable.c-167-\narch/powerpc/mm/book3s64/pgtable.c:168:pud_t pudp_invalidate(struct vm_area_struct *vma, unsigned long address,\narch/powerpc/mm/book3s64/pgtable.c-169-\t\t pud_t *pudp)\n--\ninclude/linux/pgtable.h=1317=extern pmd_t pmdp_invalidate_ad(struct vm_area_struct *vma,\n--\ninclude/linux/pgtable.h-1322-#ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD\ninclude/linux/pgtable.h:1323:extern pud_t pudp_invalidate(struct vm_area_struct *vma, unsigned long address,\ninclude/linux/pgtable.h-1324-\t\t\t pud_t *pudp);\n--\nmm/huge_memory.c=2843=int change_huge_pud(struct mmu_gather *tlb, struct vm_area_struct *vma,\n--\nmm/huge_memory.c-2871-\t */\nmm/huge_memory.c:2872:\toldpud = pudp_invalidate(vma, addr, pudp);\nmm/huge_memory.c-2873-\tentry = pud_modify(oldpud, newprot);\n--\nmm/pgtable-generic.c=212=pmd_t pmdp_invalidate_ad(struct vm_area_struct *vma, unsigned long address,\n--\nmm/pgtable-generic.c-221-#ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD\nmm/pgtable-generic.c:222:pud_t pudp_invalidate(struct vm_area_struct *vma, unsigned long address,\nmm/pgtable-generic.c-223-\t\t pud_t *pudp)\n"
} |
| 5/2 | 2026/09/09 11:36 | llm | patch-evaluator |
0mModel:gemini-3.7-flash Args: null Results: null Tokens: input: 9588 output: 30 thoughts: 359 Thoughts: **My Fuzzing Audit Checklist** Okay, time to dive in. First things first: let's verify the scope of these changes. We're talking about kernel code, so the usual suspects apply. I need to pay close attention to anything that touches core subsystems: memory management (mm/), synchronization and locking (kernel/locking/), BPF, the scheduler, core networking, VFS, and system call handling. Those are the high-risk areas. Next up, refactorings and code cleanups. The rule is clear: *never* blindly trust claims of "no functional change" or "refactoring." If there's any modification to reachable executable code, I need to treat it as a potential bug source. Refactorings can introduce subtle, easily missed regressions. This is especially true when modifying structures, abstractions, or algorithm flows. If the code *can* be reached and executed, it's getting fuzzed. Now, the crucial point: *reachability is king*. Fuzzing is only effective if the code *can* actually run in a standard virtualized environment. The target architecture is amd64, so that's where I need to focus my efforts. Specifically, I'm looking at `mm/pgtable-generic.c` which, it seems, has a new implementation of `pudp_invalidate` that replaces the one in `arch/x86/mm/pgtable.c`. There are also arm64 changes, but I'm primarily concerned with the generic change that's in `mm/pgtable-generic.c` and `include/linux/pgtable.h`. Since amd64 *doesn't* define `__HAVE_ARCH_PUDP_INVALIDATE`, this generic implementation is what we'll be using. To confirm this, I need to check the definition of `HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD` on amd64. Let's start with a `grep` for that symbol, and see where we go from there. This will give me a better understanding of how the new generic implementation interacts with the existing amd64 setup. |
| 6/2 | 2026/09/09 11:36 | tool | grepper |
0mArgs:{
"Expression": "HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD"
}Results: {
"Output": "arch/Kconfig=1103=config HAVE_ARCH_TRANSPARENT_HUGEPAGE\n--\narch/Kconfig-1105-\narch/Kconfig:1106:config HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD\narch/Kconfig-1107-\tbool\n--\narch/arm64/Kconfig=2=config ARM64\n--\narch/arm64/Kconfig-175-\tselect HAVE_ARCH_TRANSPARENT_HUGEPAGE\narch/arm64/Kconfig:176:\tselect HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD if PAGE_SIZE_4KB\narch/arm64/Kconfig-177-\tselect HAVE_ARCH_VMAP_STACK\n--\narch/arm64/include/asm/pgtable.h=875=static inline bool pud_leaf(pud_t pud)\n--\narch/arm64/include/asm/pgtable.h-885-\narch/arm64/include/asm/pgtable.h:886:#ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD\narch/arm64/include/asm/pgtable.h-887-static inline int pud_trans_huge(pud_t pud)\n--\narch/arm64/include/asm/pgtable.h=1534=static inline pmd_t pmdp_establish(struct vm_area_struct *vma,\n--\narch/arm64/include/asm/pgtable.h-1541-\narch/arm64/include/asm/pgtable.h:1542:#ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD\narch/arm64/include/asm/pgtable.h-1543-static inline pud_t pudp_establish(struct vm_area_struct *vma,\n--\narch/powerpc/platforms/Kconfig.cputype=110=config PPC_THP\n--\narch/powerpc/platforms/Kconfig.cputype-114- select HAVE_ARCH_TRANSPARENT_HUGEPAGE\narch/powerpc/platforms/Kconfig.cputype:115: select HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD\narch/powerpc/platforms/Kconfig.cputype-116- select ARCH_HAS_PMD_SOFTLEAVES if TRANSPARENT_HUGEPAGE\n--\narch/riscv/Kconfig=13=config RISCV\n--\narch/riscv/Kconfig-152-\tselect HAVE_ARCH_TRANSPARENT_HUGEPAGE if 64BIT \u0026\u0026 MMU\narch/riscv/Kconfig:153:\tselect HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD if 64BIT \u0026\u0026 MMU\narch/riscv/Kconfig-154-\tselect HAVE_ARCH_USERFAULTFD_MINOR if 64BIT \u0026\u0026 USERFAULTFD\n--\narch/x86/Kconfig=58=config X86\n--\narch/x86/Kconfig-212-\tselect HAVE_ARCH_TRANSPARENT_HUGEPAGE\narch/x86/Kconfig:213:\tselect HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD if X86_64\narch/x86/Kconfig-214-\tselect HAVE_ARCH_USERFAULTFD_WP if X86_64 \u0026\u0026 USERFAULTFD\n--\narch/x86/include/asm/pgtable.h=297=static inline int pmd_trans_huge(pmd_t pmd)\n--\narch/x86/include/asm/pgtable.h-301-\narch/x86/include/asm/pgtable.h:302:#ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD\narch/x86/include/asm/pgtable.h-303-static inline int pud_trans_huge(pud_t pud)\n--\narch/x86/include/asm/pgtable.h=1357=static inline pmd_t pmdp_establish(struct vm_area_struct *vma,\n--\narch/x86/include/asm/pgtable.h-1370-\narch/x86/include/asm/pgtable.h:1371:#ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD\narch/x86/include/asm/pgtable.h-1372-static inline pud_t pudp_establish(struct vm_area_struct *vma,\n--\ndrivers/dax/dax-private.h=120=static inline bool dax_align_valid(unsigned long align)\ndrivers/dax/dax-private.h-121-{\ndrivers/dax/dax-private.h:122:\tif (align == PUD_SIZE \u0026\u0026 IS_ENABLED(CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD))\ndrivers/dax/dax-private.h-123-\t\treturn true;\n--\ndrivers/dax/device.c=120=static vm_fault_t __dev_dax_pmd_fault(struct dev_dax *dev_dax,\n--\ndrivers/dax/device.c-163-\ndrivers/dax/device.c:164:#ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD\ndrivers/dax/device.c-165-static vm_fault_t __dev_dax_pud_fault(struct dev_dax *dev_dax,\n--\ndrivers/dax/device.c=210=static vm_fault_t __dev_dax_pud_fault(struct dev_dax *dev_dax,\n--\ndrivers/dax/device.c-214-}\ndrivers/dax/device.c:215:#endif /* !CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD */\ndrivers/dax/device.c-216-\n--\ninclude/linux/huge_mm.h=15=int copy_huge_pud(struct mm_struct *dst_mm, struct mm_struct *src_mm,\n--\ninclude/linux/huge_mm.h-18-\ninclude/linux/huge_mm.h:19:#ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD\ninclude/linux/huge_mm.h-20-void huge_pud_set_accessed(struct vm_fault *vmf, pud_t orig_pud);\n--\ninclude/linux/huge_mm.h=483=static inline bool pud_is_huge(pud_t pud)\n--\ninclude/linux/huge_mm.h-492-\ninclude/linux/huge_mm.h:493:#ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD\ninclude/linux/huge_mm.h-494-int change_huge_pud(struct mmu_gather *tlb, struct vm_area_struct *vma,\n--\ninclude/linux/mm.h=2710=static inline pmd_t folio_mk_pmd(const struct folio *folio, pgprot_t pgprot)\n--\ninclude/linux/mm.h-2714-\ninclude/linux/mm.h:2715:#ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD\ninclude/linux/mm.h-2716-/**\n--\ninclude/linux/mm.h=2726=static inline pud_t folio_mk_pud(const struct folio *folio, pgprot_t pgprot)\n--\ninclude/linux/mm.h-2729-}\ninclude/linux/mm.h:2730:#endif /* CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD */\ninclude/linux/mm.h-2731-#endif /* CONFIG_TRANSPARENT_HUGEPAGE */\n--\ninclude/linux/pgtable.h=1225=static inline void pmdp_set_wrprotect(struct mm_struct *mm,\n--\ninclude/linux/pgtable.h-1232-#ifndef __HAVE_ARCH_PUDP_SET_WRPROTECT\ninclude/linux/pgtable.h:1233:#ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD\ninclude/linux/pgtable.h-1234-#ifdef CONFIG_TRANSPARENT_HUGEPAGE\n--\ninclude/linux/pgtable.h=1243=static inline void pudp_set_wrprotect(struct mm_struct *mm,\n--\ninclude/linux/pgtable.h-1248-#endif /* CONFIG_TRANSPARENT_HUGEPAGE */\ninclude/linux/pgtable.h:1249:#endif /* CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD */\ninclude/linux/pgtable.h-1250-#endif\n--\ninclude/linux/pgtable.h=1317=extern pmd_t pmdp_invalidate_ad(struct vm_area_struct *vma,\n--\ninclude/linux/pgtable.h-1321-#ifndef __HAVE_ARCH_PUDP_INVALIDATE\ninclude/linux/pgtable.h:1322:#ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD\ninclude/linux/pgtable.h-1323-extern pud_t pudp_invalidate(struct vm_area_struct *vma, unsigned long address,\n--\ninclude/linux/pgtable.h=2089=static inline int pud_write(pud_t pud)\n--\ninclude/linux/pgtable.h-2096-#if !defined(CONFIG_TRANSPARENT_HUGEPAGE) || \\\ninclude/linux/pgtable.h:2097:\t!defined(CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD)\ninclude/linux/pgtable.h-2098-static inline int pud_trans_huge(pud_t pud)\n--\ninclude/linux/pgtable.h=2104=static inline int pud_trans_unstable(pud_t *pud)\n--\ninclude/linux/pgtable.h-2106-#if defined(CONFIG_TRANSPARENT_HUGEPAGE) \u0026\u0026 \\\ninclude/linux/pgtable.h:2107:\tdefined(CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD)\ninclude/linux/pgtable.h-2108-\tpud_t pudval = pudp_get(pud);\n--\ninclude/linux/pgtable.h=2305=static inline const char *pgtable_level_to_str(enum pgtable_level level)\n--\ninclude/linux/pgtable.h-2342-#ifndef has_transparent_pud_hugepage\ninclude/linux/pgtable.h:2343:#define has_transparent_pud_hugepage() IS_BUILTIN(CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD)\ninclude/linux/pgtable.h-2344-#endif\n--\ninclude/linux/vm_event_item.h=34=enum vm_event_item { PGPGIN, PGPGOUT, PSWPIN, PSWPOUT,\n--\ninclude/linux/vm_event_item.h-103-\t\tTHP_SCAN_EXCEED_SHARED_PTE,\ninclude/linux/vm_event_item.h:104:#ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD\ninclude/linux/vm_event_item.h-105-\t\tTHP_SPLIT_PUD,\n--\nmm/Kconfig=1009=config HAVE_GIGANTIC_FOLIOS\nmm/Kconfig-1010-\tdef_bool (HUGETLB_PAGE \u0026\u0026 ARCH_HAS_GIGANTIC_PAGE) || \\\nmm/Kconfig:1011:\t\t (ZONE_DEVICE \u0026\u0026 HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD)\nmm/Kconfig-1012-\n--\nmm/Kconfig=1025=config ARCH_SUPPORTS_PUD_PFNMAP\nmm/Kconfig-1026-\tdef_bool y\nmm/Kconfig:1027:\tdepends on ARCH_SUPPORTS_HUGE_PFNMAP \u0026\u0026 HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD\nmm/Kconfig-1028-\n--\nmm/debug_vm_pgtable.c=282=static void __init pmd_leaf_tests(struct pgtable_debug_args *args)\n--\nmm/debug_vm_pgtable.c-298-\nmm/debug_vm_pgtable.c:299:#ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD\nmm/debug_vm_pgtable.c-300-static void __init pud_basic_tests(struct pgtable_debug_args *args, int idx)\n--\nmm/debug_vm_pgtable.c=405=static void __init pud_leaf_tests(struct pgtable_debug_args *args)\n--\nmm/debug_vm_pgtable.c-419-}\nmm/debug_vm_pgtable.c:420:#else /* !CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD */\nmm/debug_vm_pgtable.c-421-static void __init pud_basic_tests(struct pgtable_debug_args *args, int idx) { }\n--\nmm/debug_vm_pgtable.c=423=static void __init pud_leaf_tests(struct pgtable_debug_args *args) { }\nmm/debug_vm_pgtable.c:424:#endif /* CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD */\nmm/debug_vm_pgtable.c-425-#else /* !CONFIG_TRANSPARENT_HUGEPAGE */\n--\nmm/debug_vm_pgtable.c=905=static void __init pmd_thp_tests(struct pgtable_debug_args *args)\n--\nmm/debug_vm_pgtable.c-933-\nmm/debug_vm_pgtable.c:934:#ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD\nmm/debug_vm_pgtable.c-935-static void __init pud_thp_tests(struct pgtable_debug_args *args)\n--\nmm/debug_vm_pgtable.c-953-}\nmm/debug_vm_pgtable.c:954:#else /* !CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD */\nmm/debug_vm_pgtable.c-955-static void __init pud_thp_tests(struct pgtable_debug_args *args) { }\nmm/debug_vm_pgtable.c:956:#endif /* CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD */\nmm/debug_vm_pgtable.c-957-#else /* !CONFIG_TRANSPARENT_HUGEPAGE */\n--\nmm/hmm.c=403=static int hmm_vma_walk_pmd(pmd_t *pmdp,\n--\nmm/hmm.c-479-\nmm/hmm.c:480:#if defined(CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD)\nmm/hmm.c-481-static inline unsigned long pud_to_hmm_pfn_flags(struct hmm_range *range,\n--\nmm/huge_memory.c=1749=EXPORT_SYMBOL_GPL(vmf_insert_folio_pmd);\nmm/huge_memory.c-1750-\nmm/huge_memory.c:1751:#ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD\nmm/huge_memory.c-1752-static pud_t maybe_pud_mkwrite(pud_t pud, struct vm_area_struct *vma)\n--\nmm/huge_memory.c=1865=EXPORT_SYMBOL_GPL(vmf_insert_folio_pud);\nmm/huge_memory.c:1866:#endif /* CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD */\nmm/huge_memory.c-1867-\n--\nmm/huge_memory.c=1950=int copy_huge_pmd(struct mm_struct *dst_mm, struct mm_struct *src_mm,\n--\nmm/huge_memory.c-2061-\nmm/huge_memory.c:2062:#ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD\nmm/huge_memory.c-2063-void touch_pud(struct vm_area_struct *vma, unsigned long addr,\n--\nmm/huge_memory.c=2111=void huge_pud_set_accessed(struct vm_fault *vmf, pud_t orig_pud)\n--\nmm/huge_memory.c-2122-}\nmm/huge_memory.c:2123:#endif /* CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD */\nmm/huge_memory.c-2124-\n--\nmm/huge_memory.c=2734=int change_huge_pmd(struct mmu_gather *tlb, struct vm_area_struct *vma,\n--\nmm/huge_memory.c-2841- */\nmm/huge_memory.c:2842:#ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD\nmm/huge_memory.c-2843-int change_huge_pud(struct mmu_gather *tlb, struct vm_area_struct *vma,\n--\nmm/huge_memory.c=3033=spinlock_t *__pud_trans_huge_lock(pud_t *pud, struct vm_area_struct *vma)\n--\nmm/huge_memory.c-3043-\nmm/huge_memory.c:3044:#ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD\nmm/huge_memory.c-3045-int zap_huge_pud(struct mmu_gather *tlb, struct vm_area_struct *vma,\n--\nmm/huge_memory.c=3132=void __split_huge_pud(struct vm_area_struct *vma, pud_t *pud,\n--\nmm/huge_memory.c-3135-}\nmm/huge_memory.c:3136:#endif /* CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD */\nmm/huge_memory.c-3137-\n--\nmm/mapping_dirty_helpers.c=148=static int wp_clean_pud_entry(pud_t *pud, unsigned long addr, unsigned long end,\n--\nmm/mapping_dirty_helpers.c-150-{\nmm/mapping_dirty_helpers.c:151:#ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD\nmm/mapping_dirty_helpers.c-152-\tpud_t pudval = pudp_get(pud);\n--\nmm/memory.c=6421=static vm_fault_t create_huge_pud(struct vm_fault *vmf)\n--\nmm/memory.c-6423-#if defined(CONFIG_TRANSPARENT_HUGEPAGE) \u0026\u0026\t\t\t\\\nmm/memory.c:6424:\tdefined(CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD)\nmm/memory.c-6425-\tstruct vm_area_struct *vma = vmf-\u003evma;\n--\nmm/memory.c=6435=static vm_fault_t wp_huge_pud(struct vm_fault *vmf, pud_t orig_pud)\n--\nmm/memory.c-6437-#if defined(CONFIG_TRANSPARENT_HUGEPAGE) \u0026\u0026\t\t\t\\\nmm/memory.c:6438:\tdefined(CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD)\nmm/memory.c-6439-\tstruct vm_area_struct *vma = vmf-\u003evma;\n--\nmm/memory.c-6454-\t__split_huge_pud(vma, vmf-\u003epud, vmf-\u003eaddress);\nmm/memory.c:6455:#endif /* CONFIG_TRANSPARENT_HUGEPAGE \u0026\u0026 CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD */\nmm/memory.c-6456-\treturn VM_FAULT_FALLBACK;\n--\nmm/mremap.c=479=static inline bool move_normal_pud(struct pagetable_move_control *pmc,\n--\nmm/mremap.c-485-\nmm/mremap.c:486:#if defined(CONFIG_TRANSPARENT_HUGEPAGE) \u0026\u0026 defined(CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD)\nmm/mremap.c-487-static bool move_huge_pud(struct pagetable_move_control *pmc,\n--\nmm/pgtable-generic.c=141=pmd_t pmdp_huge_clear_flush(struct vm_area_struct *vma, unsigned long address,\n--\nmm/pgtable-generic.c-151-\nmm/pgtable-generic.c:152:#ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD\nmm/pgtable-generic.c-153-pud_t pudp_huge_clear_flush(struct vm_area_struct *vma, unsigned long address,\n--\nmm/pgtable-generic.c=212=pmd_t pmdp_invalidate_ad(struct vm_area_struct *vma, unsigned long address,\n--\nmm/pgtable-generic.c-220-#ifndef __HAVE_ARCH_PUDP_INVALIDATE\nmm/pgtable-generic.c:221:#ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD\nmm/pgtable-generic.c-222-pud_t pudp_invalidate(struct vm_area_struct *vma, unsigned long address,\n--\nmm/rmap.c=1771=void folio_add_file_rmap_pud(struct folio *folio, struct page *page,\n--\nmm/rmap.c-1774-#if defined(CONFIG_TRANSPARENT_HUGEPAGE) \u0026\u0026 \\\nmm/rmap.c:1775:\tdefined(CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD)\nmm/rmap.c-1776-\t__folio_add_file_rmap(folio, page, HPAGE_PUD_NR, vma, PGTABLE_LEVEL_PUD);\n--\nmm/rmap.c=1939=void folio_remove_rmap_pud(struct folio *folio, struct page *page,\n--\nmm/rmap.c-1942-#if defined(CONFIG_TRANSPARENT_HUGEPAGE) \u0026\u0026 \\\nmm/rmap.c:1943:\tdefined(CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD)\nmm/rmap.c-1944-\t__folio_remove_rmap(folio, page, HPAGE_PUD_NR, vma, PGTABLE_LEVEL_PUD);\n--\nmm/vmstat.c=1199=const char * const vmstat_text[] = {\n--\nmm/vmstat.c-1430-\t[I(THP_SCAN_EXCEED_SHARED_PTE)]\t\t= \"thp_scan_exceed_share_pte\",\nmm/vmstat.c:1431:#ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD\nmm/vmstat.c-1432-\t[I(THP_SPLIT_PUD)]\t\t\t= \"thp_split_pud\",\n"
} |
| 7/2 | 2026/09/09 11:36 | llm | patch-evaluator |
0mModel:gemini-3.7-flash Args: null Results: null Tokens: input: 16467 output: 28 thoughts: 560 Thoughts: **Analyzing This Patch for Fuzzing Potential** Okay, let's break this down from a fuzzing perspective. The patch affects a pretty broad swathe of architecture-specific page table code, specifically: ARM64, PowerPC, RISC-V, and x86, along with some core `pgtable` headers and generic code. It introduces a generic `pudp_invalidate` function into `mm/pgtable-generic.c`, which is significant. This means logic that used to be architecture-specific is now centralized. It also implies a fair amount of potential cross-architecture behavior that needs scrutiny. The introduction of `pudp_invalidate`, coupled with the removal of arch-specific versions, jumps out. This generic function *itself* contains `VM_WARN_ON_ONCE(!pud_present(*pudp));`, a critical runtime assertion. This is a very strong indicator, given the fuzzing rules: "Runtime Assertions and Defensive Checks: Any introduction or alteration of assertions (WARN_ON*, VM_WARN_ON*, BUG_ON*, etc.) in reachable paths." The check specifically targets page table entries, which could be very interesting for fuzzing. The rule set specifically calls out memory management code in `mm/` as worth fuzzing, and the patch touches that directory directly. The fact that the generic function is used in `mm/huge_memory.c` within `change_huge_pud` further reinforces the need to pay attention to that area. The use case is `change_huge_pud`, which is a key memory management function for handling THP (Transparent Huge Pages). Given all of this, I'm confident we need to fuzz. The `WorthFuzzing` flag is definitely `true`. Now, let's consider the details to determine the `FocusSymbols` and `EnableConfigs`. I need to dig into the calls to `pudp_invalidate` and see exactly where it's being used and how it interacts with other functions, particularly within `mm/huge_memory.c` and specifically around `change_huge_pud`. Understanding what calls that function, and what dependencies it might have is critical for effective fuzzing. |
| 8/2 | 2026/09/09 11:37 | tool | grepper |
0mArgs:{
"Expression": "change_huge_pud",
"PathPrefix": "mm/"
}Results: {
"Output": "mm/huge_memory.c=2734=int change_huge_pmd(struct mmu_gather *tlb, struct vm_area_struct *vma,\n--\nmm/huge_memory.c-2842-#ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD\nmm/huge_memory.c:2843:int change_huge_pud(struct mmu_gather *tlb, struct vm_area_struct *vma,\nmm/huge_memory.c-2844-\t\t pud_t *pudp, unsigned long addr, pgprot_t newprot,\n--\nmm/mprotect.c=574=static inline long change_pud_range(struct mmu_gather *tlb,\n--\nmm/mprotect.c-611-\t\t\t} else {\nmm/mprotect.c:612:\t\t\t\tret = change_huge_pud(tlb, vma, pudp,\nmm/mprotect.c-613-\t\t\t\t\t\t addr, newprot, cp_flags);\n"
} |
| 9/2 | 2026/09/09 11:37 | llm | patch-evaluator |
0mModel:gemini-3.7-flash Args: null Results: null Tokens: input: 17789 output: 30 thoughts: 386 Thoughts: **My Analysis of `pudp_invalidate`** Okay, let's dive into this. First, I need to understand `pudp_invalidate`, so I'll check its definition in `mm/pgtable-generic.c`. Alright, looks like it *is* a non-static symbol, which means it's exported and potentially callable from other parts of the kernel. Good. Now, examining the code block, it's defined conditionally: it uses an `#ifndef __HAVE_ARCH_PUDP_INVALIDATE` guard and an `#ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD`. I see a call to `flush_pud_tlb_range`, that's an important signal. And I see that `pudp_invalidate` is called within the `change_huge_pud` function, in `mm/huge_memory.c`, so I'm on the right track here. Next, I need to figure out the specific configuration dependencies for x86_64/amd64 architectures. Let's look at the Kconfig dependencies. `CONFIG_TRANSPARENT_HUGEPAGE` is definitely a requirement, that's clear. But the more crucial detail is that `CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD` is selected by `X86_64` (or rather when `HAVE_ARCH_TRANSPARENT_HUGEPAGE` is selected). The architecture part is key here. To be sure let's also examine `mm/Kconfig` around `TRANSPARENT_HUGEPAGE`. That should clear things up. |
| 10/2 | 2026/09/09 11:37 | tool | grepper |
0mArgs:{
"Expression": "config TRANSPARENT_HUGEPAGE",
"PathPrefix": "mm/"
}Results: {
"Output": "mm/Kconfig=832=config MM_ID\n--\nmm/Kconfig-834-\nmm/Kconfig:835:menuconfig TRANSPARENT_HUGEPAGE\nmm/Kconfig-836-\tbool \"Transparent Hugepage Support\"\n--\nmm/Kconfig=853=choice\n--\nmm/Kconfig-858-\nmm/Kconfig:859:\tconfig TRANSPARENT_HUGEPAGE_ALWAYS\nmm/Kconfig-860-\t\tbool \"always\"\n--\nmm/Kconfig-865-\nmm/Kconfig:866:\tconfig TRANSPARENT_HUGEPAGE_MADVISE\nmm/Kconfig-867-\t\tbool \"madvise\"\n--\nmm/Kconfig-874-\nmm/Kconfig:875:\tconfig TRANSPARENT_HUGEPAGE_NEVER\nmm/Kconfig-876-\t\tbool \"never\"\n--\nmm/Kconfig=882=choice\n--\nmm/Kconfig-891-\nmm/Kconfig:892:\tconfig TRANSPARENT_HUGEPAGE_SHMEM_HUGE_NEVER\nmm/Kconfig-893-\t\tbool \"never\"\n--\nmm/Kconfig-901-\nmm/Kconfig:902:\tconfig TRANSPARENT_HUGEPAGE_SHMEM_HUGE_ALWAYS\nmm/Kconfig-903-\t\tbool \"always\"\n--\nmm/Kconfig-909-\nmm/Kconfig:910:\tconfig TRANSPARENT_HUGEPAGE_SHMEM_HUGE_WITHIN_SIZE\nmm/Kconfig-911-\t\tbool \"within_size\"\n--\nmm/Kconfig-917-\nmm/Kconfig:918:\tconfig TRANSPARENT_HUGEPAGE_SHMEM_HUGE_ADVISE\nmm/Kconfig-919-\t\tbool \"advise\"\n--\nmm/Kconfig=927=choice\n--\nmm/Kconfig-936-\nmm/Kconfig:937:\tconfig TRANSPARENT_HUGEPAGE_TMPFS_HUGE_NEVER\nmm/Kconfig-938-\t\tbool \"never\"\n--\nmm/Kconfig-945-\nmm/Kconfig:946:\tconfig TRANSPARENT_HUGEPAGE_TMPFS_HUGE_ALWAYS\nmm/Kconfig-947-\t\tbool \"always\"\n--\nmm/Kconfig-953-\nmm/Kconfig:954:\tconfig TRANSPARENT_HUGEPAGE_TMPFS_HUGE_WITHIN_SIZE\nmm/Kconfig-955-\t\tbool \"within_size\"\n--\nmm/Kconfig-961-\nmm/Kconfig:962:\tconfig TRANSPARENT_HUGEPAGE_TMPFS_HUGE_ADVISE\nmm/Kconfig-963-\t\tbool \"advise\"\n"
} |
| 11/2 | 2026/09/09 11:37 | llm | patch-evaluator |
0mModel:gemini-3.7-flash Args: null Results: null Tokens: input: 19278 output: 26 thoughts: 22 Thoughts: Here's a summary of my thought process: **Diving into the Memory Management Makefile** Okay, time to dig in. I need to understand how `mm/pgtable-generic.c` is being compiled. First step? Navigate directly to the source of truth: the `mm/Makefile`. That's where all the build rules for this part of the memory management subsystem reside. I need to figure out exactly which flags, dependencies, and ultimately, which object files are generated from `pgtable-generic.c`. This is essential for understanding any potential issues in the build process or identifying how it interacts with other parts of the memory management code base. Let's see what the Makefile reveals. |
| 12/2 | 2026/09/09 11:37 | tool | grepper |
0mArgs:{
"Expression": "pgtable-generic",
"PathPrefix": "mm/"
}Results: {
"Output": "mm/Makefile=37=mmu-$(CONFIG_MMU)\t:= highmem.o memory.o mincore.o \\\n--\nmm/Makefile-39-\t\t\t msync.o page_vma_mapped.o pagewalk.o \\\nmm/Makefile:40:\t\t\t pgtable-generic.o rmap.o vmalloc.o vma.o vma_exec.o\nmm/Makefile-41-\n--\nmm/pgtable-generic.c-2-/*\nmm/pgtable-generic.c:3: * mm/pgtable-generic.c\nmm/pgtable-generic.c-4- *\n"
} |
| 13/2 | 2026/09/09 11:37 | llm | patch-evaluator |
0mModel:gemini-3.7-flash Args: null Results: null Tokens: input: 19637 output: 18 thoughts: 277 Thoughts: **My Analysis of Transparent Huge Page Configuration and Callers** Okay, let's dive into this. My initial thought is to confirm the enabling configuration for Transparent Huge Pages. I'll start by checking the `mm/Kconfig` file and the `TRANSPARENT_HUGEPAGE` option. Right, it looks like `TRANSPARENT_HUGEPAGE` depends on `HAVE_ARCH_TRANSPARENT_HUGEPAGE` and `MMU`. On an x86_64 system, which I'm assuming we're dealing with since it's an amd64 setup, `HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD` gets automatically selected if `X86_64` is defined. Therefore, `TRANSPARENT_HUGEPAGE` is the key configuration to enable this whole code path for Transparent Huge Pages. That's good to know. Now, I want to see where this is used, who calls it, and any other relevant configurations or callers. I'll move on to `mm/huge_memory.c` and specifically look for where `pudp_invalidate` is called. Ah, there it is! `change_huge_pud` calls `pudp_invalidate`. I see that `change_huge_pud` is in turn called within `mm/mprotect.c` from `change_pud_range`. And from the looks of it, `change_pud_range` is part of `change_protection_range`, which is used by `mprotect_fixup`, `do_mprotect_pkey` and ultimately, `sys_mprotect`. This implies that protection modifications on transparent huge pages, specifically at the PUD level, trigger `change_huge_pud`. Next, I'll broaden my search. I want to ensure I haven't missed anything. I'll check to see if `pudp_invalidate` or `change_huge_pud` are called from anywhere else in the code base. Gotta be thorough. |
| 14/2 | 2026/09/09 11:37 | tool | grepper |
0mArgs:{
"Expression": "pudp_invalidate"
}Results: {
"Output": "arch/powerpc/include/asm/book3s/64/pgtable.h=1420=extern pmd_t pmdp_invalidate(struct vm_area_struct *vma, unsigned long address,\n--\narch/powerpc/include/asm/book3s/64/pgtable.h-1422-#define __HAVE_ARCH_PUDP_INVALIDATE\narch/powerpc/include/asm/book3s/64/pgtable.h:1423:extern pud_t pudp_invalidate(struct vm_area_struct *vma, unsigned long address,\narch/powerpc/include/asm/book3s/64/pgtable.h-1424-\t\t\t pud_t *pudp);\n--\narch/powerpc/mm/book3s64/pgtable.c=155=pmd_t pmdp_invalidate(struct vm_area_struct *vma, unsigned long address,\n--\narch/powerpc/mm/book3s64/pgtable.c-167-\narch/powerpc/mm/book3s64/pgtable.c:168:pud_t pudp_invalidate(struct vm_area_struct *vma, unsigned long address,\narch/powerpc/mm/book3s64/pgtable.c-169-\t\t pud_t *pudp)\n--\ninclude/linux/pgtable.h=1317=extern pmd_t pmdp_invalidate_ad(struct vm_area_struct *vma,\n--\ninclude/linux/pgtable.h-1322-#ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD\ninclude/linux/pgtable.h:1323:extern pud_t pudp_invalidate(struct vm_area_struct *vma, unsigned long address,\ninclude/linux/pgtable.h-1324-\t\t\t pud_t *pudp);\n--\nmm/huge_memory.c=2843=int change_huge_pud(struct mmu_gather *tlb, struct vm_area_struct *vma,\n--\nmm/huge_memory.c-2871-\t */\nmm/huge_memory.c:2872:\toldpud = pudp_invalidate(vma, addr, pudp);\nmm/huge_memory.c-2873-\tentry = pud_modify(oldpud, newprot);\n--\nmm/pgtable-generic.c=212=pmd_t pmdp_invalidate_ad(struct vm_area_struct *vma, unsigned long address,\n--\nmm/pgtable-generic.c-221-#ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD\nmm/pgtable-generic.c:222:pud_t pudp_invalidate(struct vm_area_struct *vma, unsigned long address,\nmm/pgtable-generic.c-223-\t\t pud_t *pudp)\n"
} |
| 15/2 | 2026/09/09 11:37 | llm | patch-evaluator |
0mModel:gemini-3.7-flash Args: null Results: null Tokens: input: 21113 output: 20 thoughts: 14 Thoughts: Here's my take on those thoughts: **Analyzing `change_huge_pud` Callers** Alright, time to get down to brass tacks. The first order of business is definitely to audit the calls to that `change_huge_pud` function. I need a clear picture of *who* is using it and, more importantly, *how* they're using it. This isn't just about finding every single instance of the function call; it's about understanding the contexts. Are we talking about a simple modification within a controlled environment, or is this function being invoked from some deeply nested, performance-critical path? That's what I really need to know. The goal here is to get a baseline understanding. This helps me understand the impact this function can make and how its implementation may affect the larger system, and allows me to begin to get a better understanding of how any changes will ripple outwards. |
| 16/2 | 2026/09/09 11:37 | tool | grepper |
0mArgs:{
"Expression": "change_huge_pud"
}Results: {
"Output": "include/linux/huge_mm.h=483=static inline bool pud_is_huge(pud_t pud)\n--\ninclude/linux/huge_mm.h-493-#ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD\ninclude/linux/huge_mm.h:494:int change_huge_pud(struct mmu_gather *tlb, struct vm_area_struct *vma,\ninclude/linux/huge_mm.h-495-\t\t pud_t *pudp, unsigned long addr, pgprot_t newprot,\n--\ninclude/linux/huge_mm.h=498=static inline int\ninclude/linux/huge_mm.h:499:change_huge_pud(struct mmu_gather *tlb, struct vm_area_struct *vma,\ninclude/linux/huge_mm.h-500-\t\tpud_t *pudp, unsigned long addr, pgprot_t newprot,\n--\ninclude/linux/huge_mm.h=792=static inline void __split_huge_pud(struct vm_area_struct *vma, pud_t *pud,\n--\ninclude/linux/huge_mm.h-796-\ninclude/linux/huge_mm.h:797:static inline int change_huge_pud(struct mmu_gather *tlb,\ninclude/linux/huge_mm.h-798-\t\t\t\t struct vm_area_struct *vma, pud_t *pudp,\n--\nmm/huge_memory.c=2734=int change_huge_pmd(struct mmu_gather *tlb, struct vm_area_struct *vma,\n--\nmm/huge_memory.c-2842-#ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD\nmm/huge_memory.c:2843:int change_huge_pud(struct mmu_gather *tlb, struct vm_area_struct *vma,\nmm/huge_memory.c-2844-\t\t pud_t *pudp, unsigned long addr, pgprot_t newprot,\n--\nmm/mprotect.c=574=static inline long change_pud_range(struct mmu_gather *tlb,\n--\nmm/mprotect.c-611-\t\t\t} else {\nmm/mprotect.c:612:\t\t\t\tret = change_huge_pud(tlb, vma, pudp,\nmm/mprotect.c-613-\t\t\t\t\t\t addr, newprot, cp_flags);\n"
} |
| 17/2 | 2026/09/09 11:37 | llm | patch-evaluator |
0mModel:gemini-3.7-flash Args: null Results: null Tokens: input: 21982 output: 142 thoughts: 384 Thoughts: **My Analysis of the Code Modification** Okay, let's take a look at this. My initial focus is on the functions `pudp_invalidate` and `change_huge_pud`. I see that the target architecture is amd64 and that the core of the change lies within `mm/pgtable-generic.c`. This is particularly relevant because that file compiles for amd64 *when* `CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD` is enabled, which in turn is linked to `TRANSPARENT_HUGEPAGE`. Now, I'm noting that `pudp_invalidate` specifically deals with page table entry manipulation and TLB invalidation. It contains `VM_WARN_ON_ONCE(!pud_present(*pudp))`, which immediately catches my attention. Runtime assertions like this often indicate areas that are prone to subtle bugs or corner cases, especially when dealing with potentially complex memory management operations. Given the presence of `change_huge_pud`, which I understand handles huge page operations, it's clear these are interconnected. Based on this analysis, I'm going to flag this as "WorthFuzzing". The potential for unexpected behavior during operations like `change_huge_pud` is sufficiently high. The key elements to track are definitely `pudp_invalidate`, `change_huge_pud`, and the underlying `TRANSPARENT_HUGEPAGE` configuration. Now, let me assemble the JSON output for `set-results`. The structure is pretty straightforward: * `WorthFuzzing`: True * `FocusSymbols`: \["pudp\_invalidate", "change\_huge\_pud"] * `EnableConfigs`: \["TRANSPARENT\_HUGEPAGE"] * `Reasoning`: "The patch introduces a generic implementation of `pudp_invalidate()` in `mm/pgtable-generic.c` (used by x86/amd64 when transparent huge pages at PUD level are supported) replacing architecture-specific implementations. This modifies page table handling and includes runtime assertions (`VM_WARN_ON_ONCE`) reachable during huge PUD operations such as `change_huge_pud()` on transparent huge pages." Alright, with that information assembled, I'm ready to invoke `set-results`. This should provide enough detail for further investigation and fuzzing efforts. |
| 18/2 | 2026/09/09 11:37 | tool | set-results |
0mArgs:{
"EnableConfigs": [
"TRANSPARENT_HUGEPAGE"
],
"FocusSymbols": [
"pudp_invalidate",
"change_huge_pud"
],
"Reasoning": "The patch introduces a generic implementation of pudp_invalidate() in mm/pgtable-generic.c (replacing architecture-specific implementations on x86 and riscv), which is used on amd64 when transparent huge pages at PUD level are enabled. This touches core memory management code and includes runtime assertions (VM_WARN_ON_ONCE) in reachable paths executed by change_huge_pud().",
"WorthFuzzing": true
}Results: {
"EnableConfigs": [
"TRANSPARENT_HUGEPAGE"
],
"FocusSymbols": [
"pudp_invalidate",
"change_huge_pud"
],
"Reasoning": "The patch introduces a generic implementation of pudp_invalidate() in mm/pgtable-generic.c (replacing architecture-specific implementations on x86 and riscv), which is used on amd64 when transparent huge pages at PUD level are enabled. This touches core memory management code and includes runtime assertions (VM_WARN_ON_ONCE) in reachable paths executed by change_huge_pud().",
"WorthFuzzing": true
} |
| 19/1 | 2026/09/09 11:37 | action | If |
0mArgs:{
"WorthFuzzing": true
}Results: null |
| 20/2 | 2026/09/09 11:37 | agent | kmsan-evaluator |
0mModel:core Args: null Results: {
"KMSANReasoning": "The patch series introduces support for Transparent Huge Page (THP) PUDs and PUD PFNMAP on arm64, while consolidating the generic `pudp_invalidate()` implementation in `mm/pgtable-generic.c` across architectures (x86, riscv, powerpc).\n\nThese changes only manipulate architectural page table entries (PUD/PMD/PTE bit-flags, page table establishment, and TLB invalidation). The patch does not introduce new memory allocations, copy data to/from userspace, alter struct padding/initialization, or create paths where uninitialized stack/heap/page memory could be evaluated or leaked. Therefore, standard KASAN/debug builds are sufficient and a dedicated KMSAN session is not required.",
"NeedsKMSAN": false
}Instruction: You are an expert Linux kernel security engineer specializing in kernel memory
error detectors (KASAN and KMSAN). Your job is to review the provided patch series and
determine if the code changes justify spawning a dedicated KMSAN (KernelMemorySanitizer)
fuzzing session in addition to standard KASAN fuzzing.
CRITICAL DISTINCTION BETWEEN KASAN AND KMSAN:
- Standard KASAN kernel builds (upstream-apparmor-kasan.config) already enable
a comprehensive suite of debugging tools and sanitizers, including KASAN
(out-of-bounds accesses, use-after-free, double free, invalid free), LOCKDEP
(locking bugs and deadlocks), UB-sanitizers, and memory corruption checks.
- KMSAN (KernelMemorySanitizer) detects reads of UNINITIALIZED memory (stack, heap,
or page allocations) and kernel-to-user memory info-leaks.
Rule: THERE IS NO SENSE IN RUNNING A KMSAN SESSION IF A BUG CAN BE CAUGHT BY KASAN,
LOCKDEP, OR OTHER STANDARD BUG DETECTORS.
A dedicated KMSAN fuzzing session incurs significant resource costs. You must ONLY
set NeedsKMSAN=true if the code changes introduce or expose UNINITIALIZED MEMORY risks
that are detected ONLY by KMSAN.
Look holistically at the patch series and surrounding code. Even if no direct
uninitialized field accesses or new buffer allocations are added in the diff itself,
a patch may alter control flow, bounds checking, or data length calculations in ways
that change how the rest of the code operates on existing buffers (e.g. allowing
uninitialized stack/heap memory to be read, copied to user space, or used in control
flow). Do not hesitate to use your code access tools to inspect the surrounding code,
called functions, and callers.
Set NeedsKMSAN=true ONLY IF the patch introduces or modifies:
1. Kernel structures sent to user space (via copy_to_user, put_user, netlink skb
attributes, ioctl output arguments, socket options, or BPF buffers) where fields
or structure padding might not be fully initialized/zeroed.
2. Conditional logic or branching that depends on potentially uninitialized variables
or struct fields.
3. Allocation or initialization of complex data structures where uninitialized fields
could be read later in reachable code paths.
4. Bounds checks, lengths, or logic in a way that allows surrounding code to access
uninitialized bytes of existing buffers.
Set NeedsKMSAN=false IF:
- The code changes primarily risk out-of-bounds access, array overflows, NULL pointer
dereferences, locking deadlocks, or use-after-free bugs (these are already caught
by KASAN, LOCKDEP, or standard bug detectors).
- All stack/heap structures touched or introduced by the patch are fully zeroed
or initialized (e.g. using = {0}, memset, kzalloc) before being read or copied.
- The patch does not introduce any risk of uninitialized memory usage or info-leaks.
Use your code access tools to inspect the surrounding code if necessary, then provide
detailed KMSANReasoning contrasting KASAN vs KMSAN applicability for this patch.
Prefer calling several tools at the same time to save round-trips.
Use set-results tool to provide results of the analysis.
It must be called exactly once before the final reply.
Ignore results of this tool.
Prompt: Target architecture: amd64
For your convenience, here is the diff of the changes:
commit ed83d9c3feb51ce7a4f6f133908a6db01fc6e789
Author: syz-cluster <triage@syzkaller.com>
Date: Wed Sep 9 11:36:38 2026 +0000
syz-cluster: applied patch under review
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index b5a51b0ef9440..8a7ca1863595a 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -173,6 +173,7 @@ config ARM64
select HAVE_ARCH_THREAD_STRUCT_WHITELIST
select HAVE_ARCH_TRACEHOOK
select HAVE_ARCH_TRANSPARENT_HUGEPAGE
+ select HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD if PAGE_SIZE_4KB
select HAVE_ARCH_VMAP_STACK
select HAVE_ARM_SMCCC
select HAVE_ASM_MODVERSIONS
diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
index 6000905a2e865..fdc338970934d 100644
--- a/arch/arm64/include/asm/pgtable.h
+++ b/arch/arm64/include/asm/pgtable.h
@@ -243,18 +243,6 @@ static inline pte_t set_pte_bit(pte_t pte, pgprot_t prot)
return pte;
}
-static inline pmd_t clear_pmd_bit(pmd_t pmd, pgprot_t prot)
-{
- pmd_val(pmd) &= ~pgprot_val(prot);
- return pmd;
-}
-
-static inline pmd_t set_pmd_bit(pmd_t pmd, pgprot_t prot)
-{
- pmd_val(pmd) |= pgprot_val(prot);
- return pmd;
-}
-
static inline pte_t pte_mkwrite_novma(pte_t pte)
{
pte = set_pte_bit(pte, __pgprot(PTE_WRITE));
@@ -619,11 +607,13 @@ static inline pmd_t pmd_mkhuge(pmd_t pmd)
}
#ifdef CONFIG_ARCH_SUPPORTS_PMD_PFNMAP
-#define pmd_special(pte) (!!((pmd_val(pte) & PTE_SPECIAL)))
-static inline pmd_t pmd_mkspecial(pmd_t pmd)
-{
- return set_pmd_bit(pmd, __pgprot(PTE_SPECIAL));
-}
+#define pmd_special(pmd) pte_special(pmd_pte(pmd))
+#define pmd_mkspecial(pmd) pte_pmd(pte_mkspecial(pmd_pte(pmd)))
+#endif
+
+#ifdef CONFIG_ARCH_SUPPORTS_PUD_PFNMAP
+#define pud_special(pud) pte_special(pud_pte(pud))
+#define pud_mkspecial(pud) pte_pud(pte_mkspecial(pud_pte(pud)))
#endif
#define __pmd_to_phys(pmd) __pte_to_phys(pmd_pte(pmd))
@@ -634,8 +624,15 @@ static inline pmd_t pmd_mkspecial(pmd_t pmd)
#define pud_young(pud) pte_young(pud_pte(pud))
#define pud_mkyoung(pud) pte_pud(pte_mkyoung(pud_pte(pud)))
#define pud_mkwrite_novma(pud) pte_pud(pte_mkwrite_novma(pud_pte(pud)))
+#define pud_mkwrite(pud) pud_mkwrite_novma(pud)
#define pud_mkvalid_k(pud) pte_pud(pte_mkvalid_k(pud_pte(pud)))
#define pud_write(pud) pte_write(pud_pte(pud))
+#define pud_dirty(pud) pte_dirty(pud_pte(pud))
+#define pud_wrprotect(pud) pte_pud(pte_wrprotect(pud_pte(pud)))
+#define pud_mkdirty(pud) pte_pud(pte_mkdirty(pud_pte(pud)))
+#define pud_mkold(pud) pte_pud(pte_mkold(pud_pte(pud)))
+#define pud_mkinvalid(pud) pte_pud(pte_mkinvalid(pud_pte(pud)))
+#define pud_mkclean(pud) pte_pud(pte_mkclean(pud_pte(pud)))
static inline pud_t pud_mkhuge(pud_t pud)
{
@@ -886,6 +883,13 @@ static inline bool pud_leaf(pud_t pud)
#define pud_user(pud) pte_user(pud_pte(pud))
#define pud_user_exec(pud) pte_user_exec(pud_pte(pud))
+#ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD
+static inline int pud_trans_huge(pud_t pud)
+{
+ return pud_present(pud) && !pud_table(__pud(pud_val(pud) | PTE_VALID));
+}
+#endif
+
static inline bool pgtable_l4_enabled(void);
static inline void set_pud(pud_t *pudp, pud_t pud)
@@ -1252,6 +1256,11 @@ static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot)
return pte_pmd(pte_modify(pmd_pte(pmd), newprot));
}
+static inline pud_t pud_modify(pud_t pud, pgprot_t newprot)
+{
+ return pte_pud(pte_modify(pud_pte(pud), newprot));
+}
+
extern int __ptep_set_access_flags_anysz(struct vm_area_struct *vma,
unsigned long address, pte_t *ptep,
pte_t entry, int dirty,
@@ -1276,6 +1285,16 @@ static inline int pmdp_set_access_flags(struct vm_area_struct *vma,
}
#endif
+#ifdef CONFIG_ARCH_SUPPORTS_PUD_PFNMAP
+static inline int pudp_set_access_flags(struct vm_area_struct *vma,
+ unsigned long address, pud_t *pudp,
+ pud_t entry, int dirty)
+{
+ return __ptep_set_access_flags_anysz(vma, address, (pte_t *)pudp,
+ pud_pte(entry), dirty, PUD_SIZE);
+}
+#endif
+
#ifdef CONFIG_PAGE_TABLE_CHECK
static inline bool pte_user_accessible_page(struct mm_struct *mm, unsigned long addr, pte_t pte)
{
@@ -1350,6 +1369,14 @@ static inline bool pmdp_test_and_clear_young(struct vm_area_struct *vma,
}
#endif /* CONFIG_TRANSPARENT_HUGEPAGE || CONFIG_ARCH_HAS_NONLEAF_PMD_YOUNG */
+#ifdef CONFIG_ARCH_SUPPORTS_PUD_PFNMAP
+static inline bool pudp_test_and_clear_young(struct vm_area_struct *vma,
+ unsigned long address, pud_t *pudp)
+{
+ return __ptep_test_and_clear_young(vma, address, (pte_t *)pudp);
+}
+#endif
+
static inline pte_t __ptep_get_and_clear_anysz(struct mm_struct *mm,
unsigned long address,
pte_t *ptep,
@@ -1512,6 +1539,15 @@ static inline pmd_t pmdp_establish(struct vm_area_struct *vma,
}
#endif
+#ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD
+static inline pud_t pudp_establish(struct vm_area_struct *vma,
+ unsigned long address, pud_t *pudp, pud_t pud)
+{
+ page_table_check_pud_set(vma->vm_mm, address, pudp, pud);
+ return __pud(xchg_relaxed(&pud_val(*pudp), pud_val(pud)));
+}
+#endif
+
/*
* Encode and decode a swap entry:
* bits 0-1: present (must be zero)
@@ -1586,6 +1622,7 @@ static inline void update_mmu_cache_range(struct vm_fault *vmf,
#define update_mmu_cache(vma, addr, ptep) \
update_mmu_cache_range(NULL, vma, addr, ptep, 1)
#define update_mmu_cache_pmd(vma, address, pmd) do { } while (0)
+#define update_mmu_cache_pud(vma, address, pud) do { } while (0)
#ifdef CONFIG_ARM64_PA_BITS_52
#define phys_to_ttbr(addr) (((addr) | ((addr) >> 46)) & TTBR_BADDR_MASK_52)
diff --git a/arch/powerpc/include/asm/book3s/64/pgtable.h b/arch/powerpc/include/asm/book3s/64/pgtable.h
index f4db7d7fbd5c6..55d33c5537f13 100644
--- a/arch/powerpc/include/asm/book3s/64/pgtable.h
+++ b/arch/powerpc/include/asm/book3s/64/pgtable.h
@@ -1419,6 +1419,7 @@ static inline pgtable_t pgtable_trans_huge_withdraw(struct mm_struct *mm,
#define __HAVE_ARCH_PMDP_INVALIDATE
extern pmd_t pmdp_invalidate(struct vm_area_struct *vma, unsigned long address,
pmd_t *pmdp);
+#define __HAVE_ARCH_PUDP_INVALIDATE
extern pud_t pudp_invalidate(struct vm_area_struct *vma, unsigned long address,
pud_t *pudp);
diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h
index 40b1ed4f3ea89..327fa378032b7 100644
--- a/arch/riscv/include/asm/pgtable.h
+++ b/arch/riscv/include/asm/pgtable.h
@@ -1159,9 +1159,6 @@ static inline pud_t pud_mkinvalid(pud_t pud)
return __pud(pud_val(pud) & ~(_PAGE_PRESENT | _PAGE_PROT_NONE));
}
-extern pud_t pudp_invalidate(struct vm_area_struct *vma, unsigned long address,
- pud_t *pudp);
-
static inline pud_t pud_modify(pud_t pud, pgprot_t newprot)
{
return pte_pud(pte_modify(pud_pte(pud), newprot));
diff --git a/arch/riscv/mm/pgtable.c b/arch/riscv/mm/pgtable.c
index 9c4427d0b1874..156e385e7db44 100644
--- a/arch/riscv/mm/pgtable.c
+++ b/arch/riscv/mm/pgtable.c
@@ -154,15 +154,6 @@ pmd_t pmdp_collapse_flush(struct vm_area_struct *vma,
return pmd;
}
-pud_t pudp_invalidate(struct vm_area_struct *vma, unsigned long address,
- pud_t *pudp)
-{
- VM_WARN_ON_ONCE(!pud_present(*pudp));
- pud_t old = pudp_establish(vma, address, pudp, pud_mkinvalid(*pudp));
-
- flush_pud_tlb_range(vma, address, address + HPAGE_PUD_SIZE);
- return old;
-}
#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
pte_t pte_mkwrite(pte_t pte, struct vm_area_struct *vma)
diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h
index d5f4917c1edcb..97051c02385e8 100644
--- a/arch/x86/include/asm/pgtable.h
+++ b/arch/x86/include/asm/pgtable.h
@@ -1387,9 +1387,6 @@ static inline pud_t pudp_establish(struct vm_area_struct *vma,
extern pmd_t pmdp_invalidate_ad(struct vm_area_struct *vma,
unsigned long address, pmd_t *pmdp);
-pud_t pudp_invalidate(struct vm_area_struct *vma, unsigned long address,
- pud_t *pudp);
-
/*
* Page table pages are page-aligned. The lower half of the top
* level is used for userspace and the top half for the kernel.
diff --git a/arch/x86/mm/pgtable.c b/arch/x86/mm/pgtable.c
index cb03f5a2b2433..0945908631dc5 100644
--- a/arch/x86/mm/pgtable.c
+++ b/arch/x86/mm/pgtable.c
@@ -519,18 +519,6 @@ pmd_t pmdp_invalidate_ad(struct vm_area_struct *vma, unsigned long address,
}
#endif
-#if defined(CONFIG_TRANSPARENT_HUGEPAGE) && \
- defined(CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD)
-pud_t pudp_invalidate(struct vm_area_struct *vma, unsigned long address,
- pud_t *pudp)
-{
- VM_WARN_ON_ONCE(!pud_present(*pudp));
- pud_t old = pudp_establish(vma, address, pudp, pud_mkinvalid(*pudp));
- flush_pud_tlb_range(vma, address, address + HPAGE_PUD_SIZE);
- return old;
-}
-#endif
-
/**
* reserve_top_address - Reserve a hole in the top of the kernel address space
* @reserve: Size of hole to reserve
diff --git a/include/linux/pgtable.h b/include/linux/pgtable.h
index 8c093c119e5a8..32173005b087f 100644
--- a/include/linux/pgtable.h
+++ b/include/linux/pgtable.h
@@ -1318,6 +1318,13 @@ extern pmd_t pmdp_invalidate_ad(struct vm_area_struct *vma,
unsigned long address, pmd_t *pmdp);
#endif
+#ifndef __HAVE_ARCH_PUDP_INVALIDATE
+#ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD
+extern pud_t pudp_invalidate(struct vm_area_struct *vma, unsigned long address,
+ pud_t *pudp);
+#endif
+#endif
+
#ifndef __HAVE_ARCH_PTE_SAME
static inline int pte_same(pte_t pte_a, pte_t pte_b)
{
diff --git a/mm/pgtable-generic.c b/mm/pgtable-generic.c
index b91b1a98029c7..ac1175d9a59a7 100644
--- a/mm/pgtable-generic.c
+++ b/mm/pgtable-generic.c
@@ -217,6 +217,20 @@ pmd_t pmdp_invalidate_ad(struct vm_area_struct *vma, unsigned long address,
}
#endif
+#ifndef __HAVE_ARCH_PUDP_INVALIDATE
+#ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD
+pud_t pudp_invalidate(struct vm_area_struct *vma, unsigned long address,
+ pud_t *pudp)
+{
+ VM_WARN_ON_ONCE(!pud_present(*pudp));
+ pud_t old = pudp_establish(vma, address, pudp, pud_mkinvalid(*pudp));
+
+ flush_pud_tlb_range(vma, address, address + HPAGE_PUD_SIZE);
+ return old;
+}
+#endif
+#endif
+
#ifndef pmdp_collapse_flush
pmd_t pmdp_collapse_flush(struct vm_area_struct *vma, unsigned long address,
pmd_t *pmdp)
|
| 21/3 | 2026/09/09 11:37 | llm | kmsan-evaluator |
0mModel:gemini-3.7-flash Args: null Results: null Tokens: input: 6380 output: 183 thoughts: 759 Thoughts: **Analyzing a Patch for amd64 Architecture** Okay, so the target architecture is amd64, and I need to analyze this patch. Let's break down what's happening. First, it looks like there's some configuration being added for ARM64: selecting `HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD` based on `PAGE_SIZE_4KB`. That's a conditional setting, and expected. Then, a bunch of ARM64-specific helper functions for PUD-level Transparent Huge Pages (THP) and Physical Frame Number Map (PFNMAP) are added. This seems reasonable for supporting THP at that level. Next, I see a bit of cleanup. PowerPC is defining `__HAVE_ARCH_PUDP_INVALIDATE` and externs a function. RISC-V and x86 are removing duplicate arch-specific implementations of `pudp_invalidate`. Ah, so it looks like that function is being generalized. The core of the generalization is happening in `include/linux/pgtable.h` and `mm/pgtable-generic.c`. The generic declaration of `pudp_invalidate` is added if the architecture *doesn't* have its own definition, and if `HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD` is configured. Then a generic implementation is provided in `mm/pgtable-generic.c`. This makes sense – consolidate the code, reduce duplication, and provide a standard interface. Now, the important part: is this safe? Does this introduce any potential memory issues? The changes are *primarily* about PUD-level THP helpers and the `pudp_invalidate` generalization. From what I see, `pudp_invalidate` is essentially just being moved from x86 and RISC-V to the generic code. ARM64 is getting new THP/PFNMAP support at the PUD level, which is what the helpers are doing. There's no indication of uninitialized memory being exposed. We're dealing with page table operations. I'm focusing on those bit patterns (pte/pmd/pud values) that are bitwise-manipulated. There's nothing here that looks like it is writing to user space or conditional logic around uninitialized data. These are typically bitwise ops and atomic exchanges, which would not normally expose any security issues. So, let's go deeper and compare it to both KASAN and KMSAN checks: 1. Kernel structures sent to user space where fields or structure padding might not be fully initialized/zeroed? No. This patch doesn't look like it deals with this. 2. Conditional logic or branching that depends on potentially uninitialized variables? Nope. It's just helper functions and consolidation. 3. Allocation or initialization of complex data structures where uninitialized fields could be read later? Not that I can see. We're mainly just working with page table structures. 4. Bounds checks, lengths, or logic in a way that allows surrounding code to access uninitialized bytes of existing buffers? Nope. Based on all of that, it looks like `NeedsKMSAN` should definitely be `false`. Okay, I'm confident in that analysis. Time to use the `set-results` tool and explain the rationale. |
| 22/3 | 2026/09/09 11:37 | tool | set-results |
0mArgs:{
"KMSANReasoning": "The patch series introduces support for Transparent Huge Page (THP) PUDs and PUD PFNMAP on arm64, while consolidating the generic `pudp_invalidate()` implementation in `mm/pgtable-generic.c` across architectures (x86, riscv, powerpc).\n\nThese changes only manipulate architectural page table entries (PUD/PMD/PTE bit-flags, page table establishment, and TLB invalidation). The patch does not introduce new memory allocations, copy data to/from userspace, alter struct padding/initialization, or create paths where uninitialized stack/heap/page memory could be evaluated or leaked. Therefore, standard KASAN/debug builds are sufficient and a dedicated KMSAN session is not required.",
"NeedsKMSAN": false
}Results: {
"KMSANReasoning": "The patch series introduces support for Transparent Huge Page (THP) PUDs and PUD PFNMAP on arm64, while consolidating the generic `pudp_invalidate()` implementation in `mm/pgtable-generic.c` across architectures (x86, riscv, powerpc).\n\nThese changes only manipulate architectural page table entries (PUD/PMD/PTE bit-flags, page table establishment, and TLB invalidation). The patch does not introduce new memory allocations, copy data to/from userspace, alter struct padding/initialization, or create paths where uninitialized stack/heap/page memory could be evaluated or leaked. Therefore, standard KASAN/debug builds are sufficient and a dedicated KMSAN session is not required.",
"NeedsKMSAN": false
} |
| Total Calls | Total Tokens | Avg Tokens | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|
| Total Calls | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|