AI Trajectory


Trajectory: (Expand/Collapse All)
Seq Timestamp Type Name Duration
0/0 2026/09/07 12:08 flow patch-triage
0m Args:
null

Results:
{
  "EnableConfigs": null,
  "FocusSymbols": [],
  "KMSANReasoning": "",
  "NeedsKMSAN": false,
  "Reasoning": "The patch only modifies user-space selftest code under tools/testing/selftests/mm/ and does not affect the compiled kernel image (vmlinux) or kernel modules.",
  "WorthFuzzing": false
}

1/1 2026/09/07 12:08 action read-patch-diff
0m Args:
null

Results:
{
  "PatchDiff": "commit cd3a94af5cb668b3a3e4ddf70e951fc99781c46c\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate:   Mon Sep 7 12:08:34 2026 +0000\n\n    syz-cluster: applied patch under review\n\ndiff --git a/tools/testing/selftests/mm/pagemap_ioctl.c b/tools/testing/selftests/mm/pagemap_ioctl.c\nindex eadc7159ca5b9..7ed5b8fb3b252 100644\n--- a/tools/testing/selftests/mm/pagemap_ioctl.c\n+++ b/tools/testing/selftests/mm/pagemap_ioctl.c\n@@ -792,9 +792,9 @@ void *gethugepage(int map_size)\n \tint ret;\n \tchar *map;\n \n-\tmap = memalign(hpage_size, map_size);\n+\tmap = alloc_isolated_mem(hpage_size, map_size);\n \tif (!map)\n-\t\tksft_exit_fail_msg(\"memalign failed %d %s\\n\", errno, strerror(errno));\n+\t\tksft_exit_fail_msg(\"alloc_isolated_mem failed %d %s\\n\", errno, strerror(errno));\n \n \tret = madvise(map, map_size, MADV_HUGEPAGE);\n \tif (ret)\n@@ -856,7 +856,7 @@ int hpage_unit_tests(void)\n \n \t\t/* 4. only middle page written */\n \t\twp_free(map, map_size);\n-\t\tfree(map);\n+\t\tfree_isolated_mem(map, map_size);\n \t\tmap = gethugepage(map_size);\n \t\twp_init(map, map_size);\n \t\twp_addr_range(map, map_size);\n@@ -871,7 +871,7 @@ int hpage_unit_tests(void)\n \t\t\t\t \"%s only middle page written\\n\", __func__);\n \n \t\twp_free(map, map_size);\n-\t\tfree(map);\n+\t\tfree_isolated_mem(map, map_size);\n \t} else {\n \t\tksft_test_result_skip(\"%s all new huge page must be written\\n\", __func__);\n \t\tksft_test_result_skip(\"%s all the huge page must not be written\\n\", __func__);\n@@ -898,7 +898,7 @@ int hpage_unit_tests(void)\n \t\t\t\t vec[0].start == (uintptr_t)(map + map_size/2),\n \t\t\t\t \"%s clear first half of huge page\\n\", __func__);\n \t\twp_free(map, map_size);\n-\t\tfree(map);\n+\t\tfree_isolated_mem(map, map_size);\n \t} else {\n \t\tksft_test_result_skip(\"%s clear first half of huge page\\n\", __func__);\n \t}\n@@ -927,7 +927,7 @@ int hpage_unit_tests(void)\n \t\t\t\t \"%s clear first half of huge page with limited buffer\\n\",\n \t\t\t\t __func__);\n \t\twp_free(map, map_size);\n-\t\tfree(map);\n+\t\tfree_isolated_mem(map, map_size);\n \t} else {\n \t\tksft_test_result_skip(\"%s clear first half of huge page with limited buffer\\n\",\n \t\t\t\t      __func__);\n@@ -955,7 +955,7 @@ int hpage_unit_tests(void)\n \t\tksft_test_result(ret == 1 \u0026\u0026 LEN(vec[0]) == vec_size/2,\n \t\t\t\t \"%s clear second half huge page\\n\", __func__);\n \t\twp_free(map, map_size);\n-\t\tfree(map);\n+\t\tfree_isolated_mem(map, map_size);\n \t} else {\n \t\tksft_test_result_skip(\"%s clear second half huge page\\n\", __func__);\n \t}\n@@ -988,7 +988,7 @@ int hpage_unit_tests(void)\n \t\t\t\t \"%s get half huge page\\n\", __func__);\n \n \t\twp_free(map, map_size);\n-\t\tfree(map);\n+\t\tfree_isolated_mem(map, map_size);\n \t} else {\n \t\tksft_test_result_skip(\"%s get half huge page\\n\", __func__);\n \t\tksft_test_result_skip(\"%s get half huge page\\n\", __func__);\n@@ -1702,7 +1702,7 @@ int main(int __attribute__((unused)) argc, char *argv[])\n \t\twp_addr_range(map, hpage_size);\n \t\tbase_tests(\"Huge page testing:\", map, hpage_size, 0);\n \t\twp_free(map, hpage_size);\n-\t\tfree(map);\n+\t\tfree_isolated_mem(map, hpage_size);\n \t} else {\n \t\tbase_tests(\"Huge page testing:\", NULL, 0, 1);\n \t}\ndiff --git a/tools/testing/selftests/mm/soft-dirty.c b/tools/testing/selftests/mm/soft-dirty.c\nindex 5f278913c4d75..b6fad38c8beee 100644\n--- a/tools/testing/selftests/mm/soft-dirty.c\n+++ b/tools/testing/selftests/mm/soft-dirty.c\n@@ -92,9 +92,9 @@ static void test_hugepage(int pagemap_fd, int pagesize)\n \tif (!hpage_len)\n \t\tksft_exit_fail_msg(\"Reading PMD pagesize failed\");\n \n-\tmap = memalign(hpage_len, hpage_len);\n+\tmap = alloc_isolated_mem(hpage_len, hpage_len);\n \tif (!map)\n-\t\tksft_exit_fail_msg(\"memalign failed\\n\");\n+\t\tksft_exit_fail_msg(\"alloc_isolated_mem failed\\n\");\n \n \tret = madvise(map, hpage_len, MADV_HUGEPAGE);\n \tif (ret)\n@@ -130,7 +130,7 @@ static void test_hugepage(int pagemap_fd, int pagesize)\n \t\tksft_test_result_skip(\"Test %s huge page allocation\\n\", __func__);\n \t\tksft_test_result_skip(\"Test %s huge page dirty bit\\n\", __func__);\n \t}\n-\tfree(map);\n+\tfree_isolated_mem(map, hpage_len);\n }\n \n static void test_mprotect(int pagemap_fd, int pagesize, bool anon)\ndiff --git a/tools/testing/selftests/mm/split_huge_page_test.c b/tools/testing/selftests/mm/split_huge_page_test.c\nindex c01d227d7fd6d..7865b0bab011b 100644\n--- a/tools/testing/selftests/mm/split_huge_page_test.c\n+++ b/tools/testing/selftests/mm/split_huge_page_test.c\n@@ -153,7 +153,7 @@ static char *allocate_zero_filled_hugepage(size_t len)\n \tchar *result;\n \tsize_t i;\n \n-\tresult = memalign(pmd_pagesize, len);\n+\tresult = alloc_isolated_mem(pmd_pagesize, len);\n \tif (!result) {\n \t\tprintf(\"Fail to allocate memory\\n\");\n \t\texit(EXIT_FAILURE);\n@@ -167,6 +167,18 @@ static char *allocate_zero_filled_hugepage(size_t len)\n \treturn result;\n }\n \n+static void disable_khugepaged(void *addr, size_t len)\n+{\n+\t/*\n+\t * Disables khugepaged from collapsing THPs in range, existing THP\n+\t * pages remain.\n+\t */\n+\tif (!madvise(addr, len, MADV_NOHUGEPAGE))\n+\t\treturn;\n+\n+\tksft_exit_fail_msg(\"MADV_NOHUGEPAGE failed, err=%d\\n\", errno);\n+}\n+\n static void verify_rss_anon_split_huge_page_all_zeroes(char *one_page, int nr_hpages, size_t len)\n {\n \tunsigned long rss_anon_before, rss_anon_after;\n@@ -179,6 +191,8 @@ static void verify_rss_anon_split_huge_page_all_zeroes(char *one_page, int nr_hp\n \tif (!rss_anon_before)\n \t\tksft_exit_fail_msg(\"No RssAnon is allocated before split\\n\");\n \n+\tdisable_khugepaged(one_page, len);\n+\n \t/* split all THPs */\n \twrite_debugfs(PID_FMT, getpid(), (uint64_t)one_page,\n \t\t      (uint64_t)one_page + len, 0);\n@@ -205,7 +219,7 @@ static void split_pmd_zero_pages(void)\n \tone_page = allocate_zero_filled_hugepage(len);\n \tverify_rss_anon_split_huge_page_all_zeroes(one_page, nr_hpages, len);\n \tksft_test_result_pass(\"Split zero filled huge pages successful\\n\");\n-\tfree(one_page);\n+\tfree_isolated_mem(one_page, len);\n }\n \n static void split_pmd_thp_to_order(int order)\n@@ -214,7 +228,7 @@ static void split_pmd_thp_to_order(int order)\n \tsize_t len = 4 * pmd_pagesize;\n \tsize_t i;\n \n-\tone_page = memalign(pmd_pagesize, len);\n+\tone_page = alloc_isolated_mem(pmd_pagesize, len);\n \tif (!one_page)\n \t\tksft_exit_fail_msg(\"Fail to allocate memory: %s\\n\", strerror(errno));\n \n@@ -226,6 +240,8 @@ static void split_pmd_thp_to_order(int order)\n \tif (!check_huge_anon(one_page, 4 * pmd_pagesize, 4, pmd_pagesize))\n \t\tksft_exit_fail_msg(\"No THP is allocated\\n\");\n \n+\tdisable_khugepaged(one_page, len);\n+\n \t/* split all THPs */\n \twrite_debugfs(PID_FMT, getpid(), (uint64_t)one_page,\n \t\t(uint64_t)one_page + len, order);\n@@ -246,7 +262,7 @@ static void split_pmd_thp_to_order(int order)\n \t\tksft_exit_fail_msg(\"Still AnonHugePages not split\\n\");\n \n \tksft_test_result_pass(\"Split huge pages to order %d successful\\n\", order);\n-\tfree(one_page);\n+\tfree_isolated_mem(one_page, len);\n }\n \n static void split_pte_mapped_thp(void)\n@@ -274,6 +290,8 @@ static void split_pte_mapped_thp(void)\n \t\tgoto out;\n \t}\n \n+\tdisable_khugepaged(thp_area, thp_area_size);\n+\n \t/*\n \t * To challenge spitting code, we will mremap a single page of each\n \t * THP (page[i] of thp[i]) in the thp_area into page_area. This will\n@@ -541,6 +559,7 @@ static int create_pagecache_thp_and_fd(const char *testfile, size_t fd_size,\n \t\tksft_test_result_skip(\"Pagecache folio split skipped\\n\");\n \t\treturn -2;\n \t}\n+\tdisable_khugepaged(*addr, fd_size);\n \treturn 0;\n err_out_close:\n \tclose(*fd);\ndiff --git a/tools/testing/selftests/mm/vm_util.c b/tools/testing/selftests/mm/vm_util.c\nindex 4821a35630363..159d627ae3b05 100644\n--- a/tools/testing/selftests/mm/vm_util.c\n+++ b/tools/testing/selftests/mm/vm_util.c\n@@ -19,6 +19,11 @@\n #define KPAGEFLAGS_PATH \"/proc/kpageflags\"\n #define MAX_NR_ORDERS 20\n \n+#define ALIGN(x, a)\t\t(((x) + (a - 1)) \u0026 (~((a) - 1)))\n+#define ALIGN_PTR(p, a)\t\t((typeof(p))ALIGN((unsigned long)(p), a))\n+#define IS_ALIGNED(x, a)\t(((x) \u0026 ((typeof(x))(a) - 1)) == 0)\n+#define PTR_ALIGNED(p, a)\t(IS_ALIGNED((unsigned long)(p), a))\n+\n unsigned int __page_size;\n unsigned int __page_shift;\n \n@@ -351,31 +356,13 @@ char *__get_smap_entry(void *addr, const char *pattern, char *buf, size_t len)\n \treturn entry;\n }\n \n-static bool __check_pmd_huge(void *addr, char *pattern, int nr_hpages,\n-\t\t  uint64_t hpage_size)\n-{\n-\tchar buffer[MAX_LINE_LENGTH];\n-\tuint64_t thp = -1;\n-\tchar *entry;\n-\n-\tentry = __get_smap_entry(addr, pattern, buffer, sizeof(buffer));\n-\tif (!entry)\n-\t\tgoto err_out;\n-\n-\tif (sscanf(entry, \"%9\" SCNu64 \" kB\", \u0026thp) != 1)\n-\t\tksft_exit_fail_msg(\"Reading smap error\\n\");\n-\n-err_out:\n-\treturn thp == (nr_hpages * (hpage_size \u003e\u003e 10));\n-}\n-\n-static bool check_large_folios(void *addr, size_t len, int nr_hpages,\n-\t\tuint64_t hpage_size)\n+static bool check_large_folios(int pagemap_fd, int kpageflags_fd,\n+\t\t\t       void *addr, size_t len, int nr_hpages,\n+\t\t\t       uint64_t hpage_size)\n {\n \tint order = 0, pagesize = getpagesize();\n \tunsigned int nr_pages = hpage_size / pagesize;\n \tint orders[MAX_NR_ORDERS], status;\n-\tint pagemap_fd, kpageflags_fd;\n \tbool ret = false;\n \n \tif (!nr_pages)\n@@ -386,15 +373,6 @@ static bool check_large_folios(void *addr, size_t len, int nr_hpages,\n \t\tksft_exit_fail_msg(\"invalid order\\n\");\n \n \tmemset(orders, 0, sizeof(int) * MAX_NR_ORDERS);\n-\tpagemap_fd = open(PAGEMAP_PATH, O_RDONLY);\n-\tif (pagemap_fd == -1)\n-\t\tksft_exit_fail_msg(\"read pagemap fail\\n\");\n-\n-\tkpageflags_fd = open(KPAGEFLAGS_PATH, O_RDONLY);\n-\tif (kpageflags_fd == -1) {\n-\t\tclose(pagemap_fd);\n-\t\tksft_exit_fail_msg(\"read kpageflags fail\\n\");\n-\t}\n \n \tstatus = gather_folio_orders(addr, len, pagemap_fd,\n \t\t\tkpageflags_fd, orders, MAX_NR_ORDERS);\n@@ -405,48 +383,112 @@ static bool check_large_folios(void *addr, size_t len, int nr_hpages,\n \t\tret = true;\n \n out:\n-\tclose(pagemap_fd);\n-\tclose(kpageflags_fd);\n \treturn ret;\n }\n \n-bool check_huge_anon(void *addr, size_t len, int nr_hpages, uint64_t hpage_size)\n-{\n-\tuint64_t pmd_pagesize = read_pmd_pagesize();\n-\n-\tif (!pmd_pagesize)\n-\t\tksft_exit_fail_msg(\"reading PMD pagesize failed\\n\");\n+enum check_huge_type {\n+\tCHECK_HUGE_ANON,\n+\tCHECK_HUGE_FILE,\n+\tCHECK_HUGE_SHMEM,\n+};\n \n-\tif (hpage_size == pmd_pagesize)\n-\t\treturn __check_pmd_huge(addr, \"AnonHugePages: \", nr_hpages, hpage_size);\n+static bool check_huge_type(uint64_t categories, uint64_t kpageflags,\n+\t\t\t    enum check_huge_type type)\n+{\n+\tconst bool file = categories \u0026 PAGE_IS_FILE;\n+\tconst bool swapbacked = kpageflags \u0026 KPF_SWAPBACKED;\n+\n+\tswitch (type) {\n+\tcase CHECK_HUGE_ANON:\n+\t\treturn !file;\n+\tcase CHECK_HUGE_FILE:\n+\t\treturn file \u0026\u0026 !swapbacked;\n+\tcase CHECK_HUGE_SHMEM:\n+\t\treturn file \u0026 swapbacked;\n+\t}\n \n-\treturn check_large_folios(addr, len, nr_hpages, hpage_size);\n+\treturn false;\n }\n \n-bool check_huge_file(void *addr, size_t len, int nr_hpages, uint64_t hpage_size)\n+static bool __check_huge(void *addr, size_t len, int nr_hpages,\n+\t\t\t uint64_t hpage_size, enum check_huge_type type)\n {\n-\tuint64_t pmd_pagesize = read_pmd_pagesize();\n+\tbool ret = false;\n+\tint pagemap_fd, kpageflags_fd;\n+\tint nr_pmd_mappings = 0;\n+\tuint64_t pmd_pagesize, scan_mapping_size;\n+\tuint64_t categories, kpf;\n+\tunsigned long pfn;\n+\tbool check_pmd_mapping, allow_nonpresent;\n+\tchar *start = addr;\n+\tchar *end = start + len;\n \n+\tpmd_pagesize = read_pmd_pagesize();\n \tif (!pmd_pagesize)\n \t\tksft_exit_fail_msg(\"reading PMD pagesize failed\\n\");\n \n-\tif (hpage_size == pmd_pagesize)\n-\t\treturn __check_pmd_huge(addr, \"FilePmdMapped:\", nr_hpages, hpage_size);\n+\tcheck_pmd_mapping = (hpage_size == pmd_pagesize);\n+\tscan_mapping_size = (nr_hpages \u003e 0) ? hpage_size : psize();\n+\t/* Some mTHP tests check a partially populated PMD-sized range. */\n+\tallow_nonpresent = (uint64_t)nr_hpages * hpage_size \u003c len;\n+\n+\tpagemap_fd = open(PAGEMAP_PATH, O_RDONLY);\n+\tif (pagemap_fd \u003c 0)\n+\t\tksft_exit_fail_msg(\"open pagemap fail\\n\");\n+\n+\tkpageflags_fd = open(KPAGEFLAGS_PATH, O_RDONLY);\n+\tif (kpageflags_fd \u003c 0) {\n+\t\tclose(pagemap_fd);\n+\t\tksft_exit_fail_msg(\"open kpageflags fail\\n\");\n+\t}\n+\n+\tif (!check_pmd_mapping \u0026\u0026\n+\t    !check_large_folios(pagemap_fd, kpageflags_fd,\n+\t\t\t\taddr, len, nr_hpages, hpage_size))\n+\t\tgoto out;\n \n-\treturn check_large_folios(addr, len, nr_hpages, hpage_size);\n+\tfor (; start \u003c end; start += scan_mapping_size) {\n+\t\tcategories = pagemap_scan_get_categories(pagemap_fd, start);\n+\t\tpfn = pagemap_get_pfn(pagemap_fd, start);\n+\t\tif (pfn == -1UL) {\n+\t\t\tif (!allow_nonpresent)\n+\t\t\t\tgoto out;\n+\t\t\telse\n+\t\t\t\tcontinue;\n+\t\t}\n+\t\tif (pageflags_get(pfn, kpageflags_fd, \u0026kpf))\n+\t\t\tksft_exit_fail_msg(\"read kpageflags: %s\\n\", strerror(errno));\n+\t\tif (check_pmd_mapping \u0026\u0026 (categories \u0026 PAGE_IS_HUGE))\n+\t\t\tnr_pmd_mappings++;\n+\t\tif (kpf \u0026 KPF_COMPOUND_TAIL)\n+\t\t\tcontinue;\n+\t\tif (!check_huge_type(categories, kpf, type))\n+\t\t\tgoto out;\n+\t}\n+\n+\tif (check_pmd_mapping \u0026\u0026 (nr_pmd_mappings != nr_hpages))\n+\t\tgoto out;\n+\tret = true;\n+\n+out:\n+\tclose(pagemap_fd);\n+\tclose(kpageflags_fd);\n+\treturn ret;\n }\n \n-bool check_huge_shmem(void *addr, size_t len, int nr_hpages, uint64_t hpage_size)\n+bool check_huge_anon(void *addr, size_t len, int nr_hpages, uint64_t hpage_size)\n {\n-\tuint64_t pmd_pagesize = read_pmd_pagesize();\n-\n-\tif (!pmd_pagesize)\n-\t\tksft_exit_fail_msg(\"reading PMD pagesize failed\\n\");\n+\treturn __check_huge(addr, len, nr_hpages, hpage_size, CHECK_HUGE_ANON);\n+}\n \n-\tif (hpage_size == pmd_pagesize)\n-\t\treturn __check_pmd_huge(addr, \"ShmemPmdMapped:\", nr_hpages, hpage_size);\n+bool check_huge_file(void *addr, size_t len, int nr_hpages, uint64_t hpage_size)\n+{\n+\treturn __check_huge(addr, len, nr_hpages, hpage_size, CHECK_HUGE_FILE);\n+}\n \n-\treturn check_large_folios(addr, len, nr_hpages, hpage_size);\n+bool check_huge_shmem(void *addr, size_t len, int nr_hpages, uint64_t hpage_size)\n+{\n+\treturn __check_huge(addr, len, nr_hpages, hpage_size, CHECK_HUGE_SHMEM);\n }\n \n int64_t allocate_transhuge(void *ptr, int pagemap_fd)\n@@ -477,6 +519,61 @@ int64_t allocate_transhuge(void *ptr, int pagemap_fd)\n \treturn -1;\n }\n \n+void *alloc_isolated_mem(size_t align, size_t size)\n+{\n+\tchar *ptr, *guard, *addr_align;\n+\tsize_t map_size, guard_size, page_size = psize();\n+\tsize_t padding;\n+\n+\tif (__builtin_popcountll((unsigned long)align) \u003e 1)\n+\t\treturn NULL;\n+\n+\talign = (align \u003e page_size) ? align : page_size;\n+\tguard_size = page_size;\n+\tsize = ALIGN(size, page_size);\n+\tmap_size = size + align + guard_size;\n+\n+\tptr = mmap(NULL, map_size, PROT_READ | PROT_WRITE,\n+\t\t   MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);\n+\tif (ptr == MAP_FAILED)\n+\t\treturn NULL;\n+\n+\taddr_align = PTR_ALIGNED(ptr, align) ? ptr + align : ALIGN_PTR(ptr, align);\n+\tpadding = addr_align - guard_size - ptr;\n+\tif (padding) {\n+\t\tmunmap(ptr, padding);\n+\t\tmap_size -= padding;\n+\t\tptr += padding;\n+\t}\n+\n+\tguard = ptr;\n+\tif (mprotect(guard, guard_size, PROT_NONE))\n+\t\tgoto err_out;\n+\n+\tguard = addr_align + size;\n+\tif (mprotect(guard, guard_size, PROT_NONE))\n+\t\tgoto err_out;\n+\n+\tpadding = (ptr + map_size) - (guard + guard_size);\n+\tif (padding)\n+\t\tmunmap(guard + guard_size, padding);\n+\n+\treturn addr_align;\n+\n+err_out:\n+\tmunmap(ptr, map_size);\n+\treturn NULL;\n+}\n+\n+void free_isolated_mem(void *addr, size_t size)\n+{\n+\tint guard_size, page_size = psize();\n+\n+\tguard_size = page_size;\n+\tmunmap((char *)addr - guard_size,\n+\t       guard_size * 2 + ALIGN(size, page_size));\n+}\n+\n int pageflags_get(unsigned long pfn, int kpageflags_fd, uint64_t *flags)\n {\n \tsize_t count;\n@@ -581,13 +678,12 @@ bool softdirty_supported(void)\n \tconst size_t pagesize = getpagesize();\n \n \t/* New mappings are expected to be marked with VM_SOFTDIRTY (sd). */\n-\taddr = mmap(0, pagesize, PROT_READ | PROT_WRITE,\n-\t\t    MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);\n-\tif (addr == MAP_FAILED)\n+\taddr = alloc_isolated_mem(pagesize, pagesize);\n+\tif (!addr)\n \t\tksft_exit_fail_msg(\"mmap failed\\n\");\n \n \tsupported = check_vmflag(addr, \"sd\");\n-\tmunmap(addr, pagesize);\n+\tfree_isolated_mem(addr, pagesize);\n \treturn supported;\n }\n \ndiff --git a/tools/testing/selftests/mm/vm_util.h b/tools/testing/selftests/mm/vm_util.h\nindex 9a49af88702e4..ce1da9a553108 100644\n--- a/tools/testing/selftests/mm/vm_util.h\n+++ b/tools/testing/selftests/mm/vm_util.h\n@@ -18,6 +18,7 @@\n #define PM_SWAP                       BIT_ULL(62)\n #define PM_PRESENT                    BIT_ULL(63)\n \n+#define KPF_SWAPBACKED                BIT_ULL(14)\n #define KPF_COMPOUND_HEAD             BIT_ULL(15)\n #define KPF_COMPOUND_TAIL             BIT_ULL(16)\n #define KPF_HWPOISON                  BIT_ULL(19)\n@@ -94,6 +95,8 @@ bool check_huge_anon(void *addr, size_t len, int nr_hpages, uint64_t hpage_size)\n bool check_huge_file(void *addr, size_t len, int nr_hpages, uint64_t hpage_size);\n bool check_huge_shmem(void *addr, size_t len, int nr_hpages, uint64_t hpage_size);\n int64_t allocate_transhuge(void *ptr, int pagemap_fd);\n+void *alloc_isolated_mem(size_t align, size_t size);\n+void free_isolated_mem(void *addr, size_t size);\n int pageflags_get(unsigned long pfn, int kpageflags_fd, uint64_t *flags);\n int gather_folio_orders(char *vaddr_start, size_t len,\n \t\tint pagemap_fd, int kpageflags_fd, int orders[], int nr_orders);\n"
}

2/1 2026/09/07 12:08 agent patch-evaluator
0m Model:
core

Args:
null

Results:
{
  "EnableConfigs": null,
  "FocusSymbols": [],
  "Reasoning": "The patch only modifies user-space selftest code under tools/testing/selftests/mm/ and does not affect the compiled kernel image (vmlinux) or kernel modules.",
  "WorthFuzzing": false
}

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 cd3a94af5cb668b3a3e4ddf70e951fc99781c46c
Author: syz-cluster <triage@syzkaller.com>
Date:   Mon Sep 7 12:08:34 2026 +0000

    syz-cluster: applied patch under review

diff --git a/tools/testing/selftests/mm/pagemap_ioctl.c b/tools/testing/selftests/mm/pagemap_ioctl.c
index eadc7159ca5b9..7ed5b8fb3b252 100644
--- a/tools/testing/selftests/mm/pagemap_ioctl.c
+++ b/tools/testing/selftests/mm/pagemap_ioctl.c
@@ -792,9 +792,9 @@ void *gethugepage(int map_size)
 	int ret;
 	char *map;
 
-	map = memalign(hpage_size, map_size);
+	map = alloc_isolated_mem(hpage_size, map_size);
 	if (!map)
-		ksft_exit_fail_msg("memalign failed %d %s\n", errno, strerror(errno));
+		ksft_exit_fail_msg("alloc_isolated_mem failed %d %s\n", errno, strerror(errno));
 
 	ret = madvise(map, map_size, MADV_HUGEPAGE);
 	if (ret)
@@ -856,7 +856,7 @@ int hpage_unit_tests(void)
 
 		/* 4. only middle page written */
 		wp_free(map, map_size);
-		free(map);
+		free_isolated_mem(map, map_size);
 		map = gethugepage(map_size);
 		wp_init(map, map_size);
 		wp_addr_range(map, map_size);
@@ -871,7 +871,7 @@ int hpage_unit_tests(void)
 				 "%s only middle page written\n", __func__);
 
 		wp_free(map, map_size);
-		free(map);
+		free_isolated_mem(map, map_size);
 	} else {
 		ksft_test_result_skip("%s all new huge page must be written\n", __func__);
 		ksft_test_result_skip("%s all the huge page must not be written\n", __func__);
@@ -898,7 +898,7 @@ int hpage_unit_tests(void)
 				 vec[0].start == (uintptr_t)(map + map_size/2),
 				 "%s clear first half of huge page\n", __func__);
 		wp_free(map, map_size);
-		free(map);
+		free_isolated_mem(map, map_size);
 	} else {
 		ksft_test_result_skip("%s clear first half of huge page\n", __func__);
 	}
@@ -927,7 +927,7 @@ int hpage_unit_tests(void)
 				 "%s clear first half of huge page with limited buffer\n",
 				 __func__);
 		wp_free(map, map_size);
-		free(map);
+		free_isolated_mem(map, map_size);
 	} else {
 		ksft_test_result_skip("%s clear first half of huge page with limited buffer\n",
 				      __func__);
@@ -955,7 +955,7 @@ int hpage_unit_tests(void)
 		ksft_test_result(ret == 1 && LEN(vec[0]) == vec_size/2,
 				 "%s clear second half huge page\n", __func__);
 		wp_free(map, map_size);
-		free(map);
+		free_isolated_mem(map, map_size);
 	} else {
 		ksft_test_result_skip("%s clear second half huge page\n", __func__);
 	}
@@ -988,7 +988,7 @@ int hpage_unit_tests(void)
 				 "%s get half huge page\n", __func__);
 
 		wp_free(map, map_size);
-		free(map);
+		free_isolated_mem(map, map_size);
 	} else {
 		ksft_test_result_skip("%s get half huge page\n", __func__);
 		ksft_test_result_skip("%s get half huge page\n", __func__);
@@ -1702,7 +1702,7 @@ int main(int __attribute__((unused)) argc, char *argv[])
 		wp_addr_range(map, hpage_size);
 		base_tests("Huge page testing:", map, hpage_size, 0);
 		wp_free(map, hpage_size);
-		free(map);
+		free_isolated_mem(map, hpage_size);
 	} else {
 		base_tests("Huge page testing:", NULL, 0, 1);
 	}
diff --git a/tools/testing/selftests/mm/soft-dirty.c b/tools/testing/selftests/mm/soft-dirty.c
index 5f278913c4d75..b6fad38c8beee 100644
--- a/tools/testing/selftests/mm/soft-dirty.c
+++ b/tools/testing/selftests/mm/soft-dirty.c
@@ -92,9 +92,9 @@ static void test_hugepage(int pagemap_fd, int pagesize)
 	if (!hpage_len)
 		ksft_exit_fail_msg("Reading PMD pagesize failed");
 
-	map = memalign(hpage_len, hpage_len);
+	map = alloc_isolated_mem(hpage_len, hpage_len);
 	if (!map)
-		ksft_exit_fail_msg("memalign failed\n");
+		ksft_exit_fail_msg("alloc_isolated_mem failed\n");
 
 	ret = madvise(map, hpage_len, MADV_HUGEPAGE);
 	if (ret)
@@ -130,7 +130,7 @@ static void test_hugepage(int pagemap_fd, int pagesize)
 		ksft_test_result_skip("Test %s huge page allocation\n", __func__);
 		ksft_test_result_skip("Test %s huge page dirty bit\n", __func__);
 	}
-	free(map);
+	free_isolated_mem(map, hpage_len);
 }
 
 static void test_mprotect(int pagemap_fd, int pagesize, bool anon)
diff --git a/tools/testing/selftests/mm/split_huge_page_test.c b/tools/testing/selftests/mm/split_huge_page_test.c
index c01d227d7fd6d..7865b0bab011b 100644
--- a/tools/testing/selftests/mm/split_huge_page_test.c
+++ b/tools/testing/selftests/mm/split_huge_page_test.c
@@ -153,7 +153,7 @@ static char *allocate_zero_filled_hugepage(size_t len)
 	char *result;
 	size_t i;
 
-	result = memalign(pmd_pagesize, len);
+	result = alloc_isolated_mem(pmd_pagesize, len);
 	if (!result) {
 		printf("Fail to allocate memory\n");
 		exit(EXIT_FAILURE);
@@ -167,6 +167,18 @@ static char *allocate_zero_filled_hugepage(size_t len)
 	return result;
 }
 
+static void disable_khugepaged(void *addr, size_t len)
+{
+	/*
+	 * Disables khugepaged from collapsing THPs in range, existing THP
+	 * pages remain.
+	 */
+	if (!madvise(addr, len, MADV_NOHUGEPAGE))
+		return;
+
+	ksft_exit_fail_msg("MADV_NOHUGEPAGE failed, err=%d\n", errno);
+}
+
 static void verify_rss_anon_split_huge_page_all_zeroes(char *one_page, int nr_hpages, size_t len)
 {
 	unsigned long rss_anon_before, rss_anon_after;
@@ -179,6 +191,8 @@ static void verify_rss_anon_split_huge_page_all_zeroes(char *one_page, int nr_hp
 	if (!rss_anon_before)
 		ksft_exit_fail_msg("No RssAnon is allocated before split\n");
 
+	disable_khugepaged(one_page, len);
+
 	/* split all THPs */
 	write_debugfs(PID_FMT, getpid(), (uint64_t)one_page,
 		      (uint64_t)one_page + len, 0);
@@ -205,7 +219,7 @@ static void split_pmd_zero_pages(void)
 	one_page = allocate_zero_filled_hugepage(len);
 	verify_rss_anon_split_huge_page_all_zeroes(one_page, nr_hpages, len);
 	ksft_test_result_pass("Split zero filled huge pages successful\n");
-	free(one_page);
+	free_isolated_mem(one_page, len);
 }
 
 static void split_pmd_thp_to_order(int order)
@@ -214,7 +228,7 @@ static void split_pmd_thp_to_order(int order)
 	size_t len = 4 * pmd_pagesize;
 	size_t i;
 
-	one_page = memalign(pmd_pagesize, len);
+	one_page = alloc_isolated_mem(pmd_pagesize, len);
 	if (!one_page)
 		ksft_exit_fail_msg("Fail to allocate memory: %s\n", strerror(errno));
 
@@ -226,6 +240,8 @@ static void split_pmd_thp_to_order(int order)
 	if (!check_huge_anon(one_page, 4 * pmd_pagesize, 4, pmd_pagesize))
 		ksft_exit_fail_msg("No THP is allocated\n");
 
+	disable_khugepaged(one_page, len);
+
 	/* split all THPs */
 	write_debugfs(PID_FMT, getpid(), (uint64_t)one_page,
 		(uint64_t)one_page + len, order);
@@ -246,7 +262,7 @@ static void split_pmd_thp_to_order(int order)
 		ksft_exit_fail_msg("Still AnonHugePages not split\n");
 
 	ksft_test_result_pass("Split huge pages to order %d successful\n", order);
-	free(one_page);
+	free_isolated_mem(one_page, len);
 }
 
 static void split_pte_mapped_thp(void)
@@ -274,6 +290,8 @@ static void split_pte_mapped_thp(void)
 		goto out;
 	}
 
+	disable_khugepaged(thp_area, thp_area_size);
+
 	/*
 	 * To challenge spitting code, we will mremap a single page of each
 	 * THP (page[i] of thp[i]) in the thp_area into page_area. This will
@@ -541,6 +559,7 @@ static int create_pagecache_thp_and_fd(const char *testfile, size_t fd_size,
 		ksft_test_result_skip("Pagecache folio split skipped\n");
 		return -2;
 	}
+	disable_khugepaged(*addr, fd_size);
 	return 0;
 err_out_close:
 	close(*fd);
diff --git a/tools/testing/selftests/mm/vm_util.c b/tools/testing/selftests/mm/vm_util.c
index 4821a35630363..159d627ae3b05 100644
--- a/tools/testing/selftests/mm/vm_util.c
+++ b/tools/testing/selftests/mm/vm_util.c
@@ -19,6 +19,11 @@
 #define KPAGEFLAGS_PATH "/proc/kpageflags"
 #define MAX_NR_ORDERS 20
 
+#define ALIGN(x, a)		(((x) + (a - 1)) & (~((a) - 1)))
+#define ALIGN_PTR(p, a)		((typeof(p))ALIGN((unsigned long)(p), a))
+#define IS_ALIGNED(x, a)	(((x) & ((typeof(x))(a) - 1)) == 0)
+#define PTR_ALIGNED(p, a)	(IS_ALIGNED((unsigned long)(p), a))
+
 unsigned int __page_size;
 unsigned int __page_shift;
 
@@ -351,31 +356,13 @@ char *__get_smap_entry(void *addr, const char *pattern, char *buf, size_t len)
 	return entry;
 }
 
-static bool __check_pmd_huge(void *addr, char *pattern, int nr_hpages,
-		  uint64_t hpage_size)
-{
-	char buffer[MAX_LINE_LENGTH];
-	uint64_t thp = -1;
-	char *entry;
-
-	entry = __get_smap_entry(addr, pattern, buffer, sizeof(buffer));
-	if (!entry)
-		goto err_out;
-
-	if (sscanf(entry, "%9" SCNu64 " kB", &thp) != 1)
-		ksft_exit_fail_msg("Reading smap error\n");
-
-err_out:
-	return thp == (nr_hpages * (hpage_size >> 10));
-}
-
-static bool check_large_folios(void *addr, size_t len, int nr_hpages,
-		uint64_t hpage_size)
+static bool check_large_folios(int pagemap_fd, int kpageflags_fd,
+			       void *addr, size_t len, int nr_hpages,
+			       uint64_t hpage_size)
 {
 	int order = 0, pagesize = getpagesize();
 	unsigned int nr_pages = hpage_size / pagesize;
 	int orders[MAX_NR_ORDERS], status;
-	int pagemap_fd, kpageflags_fd;
 	bool ret = false;
 
 	if (!nr_pages)
@@ -386,15 +373,6 @@ static bool check_large_folios(void *addr, size_t len, int nr_hpages,
 		ksft_exit_fail_msg("invalid order\n");
 
 	memset(orders, 0, sizeof(int) * MAX_NR_ORDERS);
-	pagemap_fd = open(PAGEMAP_PATH, O_RDONLY);
-	if (pagemap_fd == -1)
-		ksft_exit_fail_msg("read pagemap fail\n");
-
-	kpageflags_fd = open(KPAGEFLAGS_PATH, O_RDONLY);
-	if (kpageflags_fd == -1) {
-		close(pagemap_fd);
-		ksft_exit_fail_msg("read kpageflags fail\n");
-	}
 
 	status = gather_folio_orders(addr, len, pagemap_fd,
 			kpageflags_fd, orders, MAX_NR_ORDERS);
@@ -405,48 +383,112 @@ static bool check_large_folios(void *addr, size_t len, int nr_hpages,
 		ret = true;
 
 out:
-	close(pagemap_fd);
-	close(kpageflags_fd);
 	return ret;
 }
 
-bool check_huge_anon(void *addr, size_t len, int nr_hpages, uint64_t hpage_size)
-{
-	uint64_t pmd_pagesize = read_pmd_pagesize();
-
-	if (!pmd_pagesize)
-		ksft_exit_fail_msg("reading PMD pagesize failed\n");
+enum check_huge_type {
+	CHECK_HUGE_ANON,
+	CHECK_HUGE_FILE,
+	CHECK_HUGE_SHMEM,
+};
 
-	if (hpage_size == pmd_pagesize)
-		return __check_pmd_huge(addr, "AnonHugePages: ", nr_hpages, hpage_size);
+static bool check_huge_type(uint64_t categories, uint64_t kpageflags,
+			    enum check_huge_type type)
+{
+	const bool file = categories & PAGE_IS_FILE;
+	const bool swapbacked = kpageflags & KPF_SWAPBACKED;
+
+	switch (type) {
+	case CHECK_HUGE_ANON:
+		return !file;
+	case CHECK_HUGE_FILE:
+		return file && !swapbacked;
+	case CHECK_HUGE_SHMEM:
+		return file & swapbacked;
+	}
 
-	return check_large_folios(addr, len, nr_hpages, hpage_size);
+	return false;
 }
 
-bool check_huge_file(void *addr, size_t len, int nr_hpages, uint64_t hpage_size)
+static bool __check_huge(void *addr, size_t len, int nr_hpages,
+			 uint64_t hpage_size, enum check_huge_type type)
 {
-	uint64_t pmd_pagesize = read_pmd_pagesize();
+	bool ret = false;
+	int pagemap_fd, kpageflags_fd;
+	int nr_pmd_mappings = 0;
+	uint64_t pmd_pagesize, scan_mapping_size;
+	uint64_t categories, kpf;
+	unsigned long pfn;
+	bool check_pmd_mapping, allow_nonpresent;
+	char *start = addr;
+	char *end = start + len;
 
+	pmd_pagesize = read_pmd_pagesize();
 	if (!pmd_pagesize)
 		ksft_exit_fail_msg("reading PMD pagesize failed\n");
 
-	if (hpage_size == pmd_pagesize)
-		return __check_pmd_huge(addr, "FilePmdMapped:", nr_hpages, hpage_size);
+	check_pmd_mapping = (hpage_size == pmd_pagesize);
+	scan_mapping_size = (nr_hpages > 0) ? hpage_size : psize();
+	/* Some mTHP tests check a partially populated PMD-sized range. */
+	allow_nonpresent = (uint64_t)nr_hpages * hpage_size < len;
+
+	pagemap_fd = open(PAGEMAP_PATH, O_RDONLY);
+	if (pagemap_fd < 0)
+		ksft_exit_fail_msg("open pagemap fail\n");
+
+	kpageflags_fd = open(KPAGEFLAGS_PATH, O_RDONLY);
+	if (kpageflags_fd < 0) {
+		close(pagemap_fd);
+		ksft_exit_fail_msg("open kpageflags fail\n");
+	}
+
+	if (!check_pmd_mapping &&
+	    !check_large_folios(pagemap_fd, kpageflags_fd,
+				addr, len, nr_hpages, hpage_size))
+		goto out;
 
-	return check_large_folios(addr, len, nr_hpages, hpage_size);
+	for (; start < end; start += scan_mapping_size) {
+		categories = pagemap_scan_get_categories(pagemap_fd, start);
+		pfn = pagemap_get_pfn(pagemap_fd, start);
+		if (pfn == -1UL) {
+			if (!allow_nonpresent)
+				goto out;
+			else
+				continue;
+		}
+		if (pageflags_get(pfn, kpageflags_fd, &kpf))
+			ksft_exit_fail_msg("read kpageflags: %s\n", strerror(errno));
+		if (check_pmd_mapping && (categories & PAGE_IS_HUGE))
+			nr_pmd_mappings++;
+		if (kpf & KPF_COMPOUND_TAIL)
+			continue;
+		if (!check_huge_type(categories, kpf, type))
+			goto out;
+	}
+
+	if (check_pmd_mapping && (nr_pmd_mappings != nr_hpages))
+		goto out;
+	ret = true;
+
+out:
+	close(pagemap_fd);
+	close(kpageflags_fd);
+	return ret;
 }
 
-bool check_huge_shmem(void *addr, size_t len, int nr_hpages, uint64_t hpage_size)
+bool check_huge_anon(void *addr, size_t len, int nr_hpages, uint64_t hpage_size)
 {
-	uint64_t pmd_pagesize = read_pmd_pagesize();
-
-	if (!pmd_pagesize)
-		ksft_exit_fail_msg("reading PMD pagesize failed\n");
+	return __check_huge(addr, len, nr_hpages, hpage_size, CHECK_HUGE_ANON);
+}
 
-	if (hpage_size == pmd_pagesize)
-		return __check_pmd_huge(addr, "ShmemPmdMapped:", nr_hpages, hpage_size);
+bool check_huge_file(void *addr, size_t len, int nr_hpages, uint64_t hpage_size)
+{
+	return __check_huge(addr, len, nr_hpages, hpage_size, CHECK_HUGE_FILE);
+}
 
-	return check_large_folios(addr, len, nr_hpages, hpage_size);
+bool check_huge_shmem(void *addr, size_t len, int nr_hpages, uint64_t hpage_size)
+{
+	return __check_huge(addr, len, nr_hpages, hpage_size, CHECK_HUGE_SHMEM);
 }
 
 int64_t allocate_transhuge(void *ptr, int pagemap_fd)
@@ -477,6 +519,61 @@ int64_t allocate_transhuge(void *ptr, int pagemap_fd)
 	return -1;
 }
 
+void *alloc_isolated_mem(size_t align, size_t size)
+{
+	char *ptr, *guard, *addr_align;
+	size_t map_size, guard_size, page_size = psize();
+	size_t padding;
+
+	if (__builtin_popcountll((unsigned long)align) > 1)
+		return NULL;
+
+	align = (align > page_size) ? align : page_size;
+	guard_size = page_size;
+	size = ALIGN(size, page_size);
+	map_size = size + align + guard_size;
+
+	ptr = mmap(NULL, map_size, PROT_READ | PROT_WRITE,
+		   MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
+	if (ptr == MAP_FAILED)
+		return NULL;
+
+	addr_align = PTR_ALIGNED(ptr, align) ? ptr + align : ALIGN_PTR(ptr, align);
+	padding = addr_align - guard_size - ptr;
+	if (padding) {
+		munmap(ptr, padding);
+		map_size -= padding;
+		ptr += padding;
+	}
+
+	guard = ptr;
+	if (mprotect(guard, guard_size, PROT_NONE))
+		goto err_out;
+
+	guard = addr_align + size;
+	if (mprotect(guard, guard_size, PROT_NONE))
+		goto err_out;
+
+	padding = (ptr + map_size) - (guard + guard_size);
+	if (padding)
+		munmap(guard + guard_size, padding);
+
+	return addr_align;
+
+err_out:
+	munmap(ptr, map_size);
+	return NULL;
+}
+
+void free_isolated_mem(void *addr, size_t size)
+{
+	int guard_size, page_size = psize();
+
+	guard_size = page_size;
+	munmap((char *)addr - guard_size,
+	       guard_size * 2 + ALIGN(size, page_size));
+}
+
 int pageflags_get(unsigned long pfn, int kpageflags_fd, uint64_t *flags)
 {
 	size_t count;
@@ -581,13 +678,12 @@ bool softdirty_supported(void)
 	const size_t pagesize = getpagesize();
 
 	/* New mappings are expected to be marked with VM_SOFTDIRTY (sd). */
-	addr = mmap(0, pagesize, PROT_READ | PROT_WRITE,
-		    MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
-	if (addr == MAP_FAILED)
+	addr = alloc_isolated_mem(pagesize, pagesize);
+	if (!addr)
 		ksft_exit_fail_msg("mmap failed\n");
 
 	supported = check_vmflag(addr, "sd");
-	munmap(addr, pagesize);
+	free_isolated_mem(addr, pagesize);
 	return supported;
 }
 
diff --git a/tools/testing/selftests/mm/vm_util.h b/tools/testing/selftests/mm/vm_util.h
index 9a49af88702e4..ce1da9a553108 100644
--- a/tools/testing/selftests/mm/vm_util.h
+++ b/tools/testing/selftests/mm/vm_util.h
@@ -18,6 +18,7 @@
 #define PM_SWAP                       BIT_ULL(62)
 #define PM_PRESENT                    BIT_ULL(63)
 
+#define KPF_SWAPBACKED                BIT_ULL(14)
 #define KPF_COMPOUND_HEAD             BIT_ULL(15)
 #define KPF_COMPOUND_TAIL             BIT_ULL(16)
 #define KPF_HWPOISON                  BIT_ULL(19)
@@ -94,6 +95,8 @@ bool check_huge_anon(void *addr, size_t len, int nr_hpages, uint64_t hpage_size)
 bool check_huge_file(void *addr, size_t len, int nr_hpages, uint64_t hpage_size);
 bool check_huge_shmem(void *addr, size_t len, int nr_hpages, uint64_t hpage_size);
 int64_t allocate_transhuge(void *ptr, int pagemap_fd);
+void *alloc_isolated_mem(size_t align, size_t size);
+void free_isolated_mem(void *addr, size_t size);
 int pageflags_get(unsigned long pfn, int kpageflags_fd, uint64_t *flags);
 int gather_folio_orders(char *vaddr_start, size_t len,
 		int pagemap_fd, int kpageflags_fd, int orders[], int nr_orders);

3/2 2026/09/07 12:08 llm patch-evaluator
0m Model:
gemini-3.7-flash

Args:
null

Results:
null

Tokens:
							input: 9754
							output: 69
							thoughts: 497
						

Thoughts:
**Patch Evaluation for Syzkaller Fuzzing**

Okay, so I've been asked to assess this patch series in the context of syzkaller fuzzing. My immediate thought is to start with the diff itself. Let's see... the patch is touching files solely within `tools/testing/selftests/mm/`. I'm familiar with this area. The modified files include `pagemap_ioctl.c`, `soft-dirty.c`, `split_huge_page_test.c`, and some utility files.

Now, let's bring the fuzzing guidelines into the picture. Section 2, the "NEGATIVE CRITERIA," is what I need to focus on. Specifically, when should I flag this as *not* worth fuzzing? The criteria state that changes are a "no-go" if the modifications are strictly limited to things like documentation, comments, user-space tools, self-tests, or scripts that *don't* impact the compiled kernel or modules. This sounds promising.

Looking at the file paths, they're all nestled within `tools/testing/selftests/mm/`. Right, these are all user-space selftests, residing in the `tools/` directory. Crucially, I see no modifications to the kernel source code outside of this `tools/` directory.

Therefore, this patch clearly falls under the category of, and I quote, "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." So, based on this evaluation, I'm confident in setting:

*   `WorthFuzzing = false`
*   `FocusSymbols = []`
*   `EnableConfigs = []`

My reasoning is straightforward: The changes are entirely confined to user-space selftests within the `tools/testing/selftests/mm/` directory and do not alter the kernel image or any kernel modules. I'll make a final check with `set-results`.



4/2 2026/09/07 12:08 tool set-results
0m Args:
{
  "EnableConfigs": [],
  "FocusSymbols": [],
  "Reasoning": "The patch only modifies user-space selftest code under tools/testing/selftests/mm/ and does not affect the compiled kernel image (vmlinux) or kernel modules.",
  "WorthFuzzing": false
}

Results:
{
  "EnableConfigs": null,
  "FocusSymbols": [],
  "Reasoning": "The patch only modifies user-space selftest code under tools/testing/selftests/mm/ and does not affect the compiled kernel image (vmlinux) or kernel modules.",
  "WorthFuzzing": false
}

5/1 2026/09/07 12:08 action If
0m Args:
{
  "WorthFuzzing": false
}

Results:
null

LLM Calls Summary:
Total Calls Total Tokens Avg Tokens Total Duration (Seconds) Avg Duration (Seconds)
Tool Calls Summary:
Total Calls Total Duration (Seconds) Avg Duration (Seconds)