Re: [PATCH 3/4] selftests: mm: implement the mTHP-sized hugepage check helpers

Baolin Wang <[email protected]> Sat, 1 Aug 2026 13:08:27 +0800
Newsgroups org.kernel.vger.linux-kselftest,org.kernel.vger.linux-kernel,org.kvack.linux-mm
Message-ID <[email protected]>

On 7/28/26 4:13 PM, Baolin Wang wrote:
> Implement mTHP-sized hugepage checking helpers using gather_folio_orders().
> Also rename the existing PMD-sized huge page check function to
> __check_pmd_huge() for clarity.
> 
> Signed-off-by: Baolin Wang <[email protected]>
> ---
>   tools/testing/selftests/mm/vm_util.c | 55 ++++++++++++++++++++++++++--
>   1 file changed, 51 insertions(+), 4 deletions(-)
> 
> diff --git a/tools/testing/selftests/mm/vm_util.c b/tools/testing/selftests/mm/vm_util.c
> index 09e5d5cabe21..a4ffaa0ca6fa 100644
> --- a/tools/testing/selftests/mm/vm_util.c
> +++ b/tools/testing/selftests/mm/vm_util.c
> @@ -15,6 +15,10 @@
>   #define SMAP_FILE_PATH "/proc/self/smaps"
>   #define STATUS_FILE_PATH "/proc/self/status"
>   #define MAX_LINE_LENGTH 500
> +#define PAGEMAP_PATH "/proc/self/pagemap"
> +#define KPAGEFLAGS_PATH "/proc/kpageflags"
> +#define GET_ORDER(nr_pages)    (31 - __builtin_clz(nr_pages))

sashiko comment:
"Is there a risk of undefined behavior here if nr_pages evaluates to 0?

If check_large_folios() is called with an hpage_size smaller than the 
system page size, the division hpage_size / pagesize will yield 0. 
Calling __builtin_clz(0) results in undefined behavior."

This doesn't happen now. But for code robustness, I'll add a hpage_size 
check in check_large_folios().

> +#define NR_ORDERS 20
>   
>   unsigned int __page_size;
>   unsigned int __page_shift;
> @@ -348,7 +352,7 @@ char *__get_smap_entry(void *addr, const char *pattern, char *buf, size_t len)
>   	return entry;
>   }
>   
> -bool __check_huge(void *addr, char *pattern, int nr_hpages,
> +static bool __check_pmd_huge(void *addr, char *pattern, int nr_hpages,
>   		  uint64_t hpage_size)
>   {
>   	char buffer[MAX_LINE_LENGTH];
> @@ -366,19 +370,62 @@ bool __check_huge(void *addr, char *pattern, int nr_hpages,
>   	return thp == (nr_hpages * (hpage_size >> 10));
>   }
>   
> +static bool check_large_folios(void *addr, unsigned long size, int nr_hpages, uint64_t hpage_size)
> +{
> +	int pagesize = getpagesize();
> +	int order = GET_ORDER(hpage_size / pagesize);
> +	int pagemap_fd, kpageflags_fd;
> +	int orders[NR_ORDERS], status;
> +	bool ret = false;
> +
> +	memset(orders, 0, sizeof(int) * 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, size, pagemap_fd,
> +			kpageflags_fd, orders, NR_ORDERS);
> +	if (status)
> +		goto out;
> +
> +	if (orders[order] == nr_hpages)
> +		ret = true;

sashiko comment:
"Does this code overflow the orders[] stack array if the calculated 
order is 20 or greater?

For example, on architectures supporting very large huge pages (like 
16GB huge pages on PowerPC), the order could be 22. It looks like 
indexing orders[order] here without bounds checking could cause an 
out-of-bounds stack read."

This doesn't look like the mTHP order size, but I'll add an order check.