On 10 Aug 2025, at 12:49, Donet Tom wrote: > On 8/9/25 12:31 AM, Zi Yan wrote: >> The helper gathers an folio order statistics of folios within a virtual >> address range and checks it against a given order list. It aims to provide >> a more precise folio order check instead of just checking the existence of >> PMD folios. >> >> Signed-off-by: Zi Yan <[email protected]> >> --- >> .../selftests/mm/split_huge_page_test.c | 4 +- >> tools/testing/selftests/mm/vm_util.c | 133 ++++++++++++++++++ >> tools/testing/selftests/mm/vm_util.h | 7 + >> 3 files changed, 141 insertions(+), 3 deletions(-) >> >> diff --git a/tools/testing/selftests/mm/split_huge_page_test.c >> b/tools/testing/selftests/mm/split_huge_page_test.c >> index cb364c5670c6..5ab488fab1cd 100644 >> --- a/tools/testing/selftests/mm/split_huge_page_test.c >> +++ b/tools/testing/selftests/mm/split_huge_page_test.c >> @@ -34,8 +34,6 @@ uint64_t pmd_pagesize; >> #define PID_FMT_OFFSET "%d,0x%lx,0x%lx,%d,%d" >> #define PATH_FMT "%s,0x%lx,0x%lx,%d" >> -#define PFN_MASK ((1UL<<55)-1) >> -#define KPF_THP (1UL<<22) >> #define GET_ORDER(nr_pages) (31 - __builtin_clz(nr_pages)) >> int is_backed_by_thp(char *vaddr, int pagemap_file, int kpageflags_file) >> @@ -49,7 +47,7 @@ int is_backed_by_thp(char *vaddr, int pagemap_file, int >> kpageflags_file) >> if (kpageflags_file) { >> pread(kpageflags_file, &page_flags, sizeof(page_flags), >> - (paddr & PFN_MASK) * sizeof(page_flags)); >> + PAGEMAP_PFN(paddr) * sizeof(page_flags)); >> return !!(page_flags & KPF_THP); >> } >> diff --git a/tools/testing/selftests/mm/vm_util.c >> b/tools/testing/selftests/mm/vm_util.c >> index 6a239aa413e2..41d50b74b2f6 100644 >> --- a/tools/testing/selftests/mm/vm_util.c >> +++ b/tools/testing/selftests/mm/vm_util.c >> @@ -338,6 +338,139 @@ int detect_hugetlb_page_sizes(size_t sizes[], int max) >> return count; >> } >> +static int get_page_flags(char *vaddr, int pagemap_file, int >> kpageflags_file, >> + uint64_t *flags) >> +{ >> + unsigned long pfn; >> + size_t count; >> + >> + pfn = pagemap_get_pfn(pagemap_file, vaddr); >> + /* >> + * Treat non-present page as a page without any flag, so that >> + * gather_folio_orders() just record the current folio order. >> + */ >> + if (pfn == -1UL) { >> + *flags = 0; >> + return 0; >> + } >> + >> + count = pread(kpageflags_file, flags, sizeof(*flags), >> + pfn * sizeof(*flags)); >> + >> + if (count != sizeof(*flags)) >> + return -1; >> + >> + return 0; >> +} >> + >> +static int gather_folio_orders(char *vaddr_start, size_t len, >> + int pagemap_file, int kpageflags_file, >> + int orders[], int nr_orders) >> +{ >> + uint64_t page_flags = 0; >> + int cur_order = -1; >> + char *vaddr; >> + >> + if (!pagemap_file || !kpageflags_file) >> + return -1; >> + if (nr_orders <= 0) >> + return -1; >> + >> + for (vaddr = vaddr_start; vaddr < vaddr_start + len; ) { >> + char *next_folio_vaddr; >> + int status; >> + >> + if (get_page_flags(vaddr, pagemap_file, kpageflags_file, >> &page_flags)) >> + return -1; >> + >> + /* all order-0 pages with possible false postive (non folio) */ >> + if (!(page_flags & (KPF_COMPOUND_HEAD | KPF_COMPOUND_TAIL))) { >> + orders[0]++; >> + vaddr += psize(); >> + continue; >> + } >> + >> + /* skip non thp compound pages */ >> + if (!(page_flags & KPF_THP)) { >> + vaddr += psize(); >> + continue; >> + } >> + >> + /* vpn points to part of a THP at this point */ >> + if (page_flags & KPF_COMPOUND_HEAD) >> + cur_order = 1; >> + else { >> + /* not a head nor a tail in a THP? */ >> + if (!(page_flags & KPF_COMPOUND_TAIL)) >> + return -1; >> + continue; > > If KPF_COMPOUND_TAIL is set, do we use the same vaddr, or should we advance > to the next vaddr before continuing?
Yeah, I missed a vaddr += psize() here. Thank you for pointing this out. Best Regards, Yan, Zi

