Implement the mTHP hugepage check helper. Signed-off-by: Baolin Wang --- tools/testing/selftests/mm/vm_util.c | 52 +++++++++++++++++++++++++--- 1 file changed, 48 insertions(+), 4 deletions(-) diff --git a/tools/testing/selftests/mm/vm_util.c b/tools/testing/selftests/mm/vm_util.c index 853c8a4caa1d..d0f8aa66b988 100644 --- a/tools/testing/selftests/mm/vm_util.c +++ b/tools/testing/selftests/mm/vm_util.c @@ -16,6 +16,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)) +#define NR_ORDERS 20 unsigned int __page_size; unsigned int __page_shift; @@ -353,7 +357,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]; @@ -371,19 +375,59 @@ 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; + +out: + close(pagemap_fd); + close(kpageflags_fd); + return ret; +} + bool check_huge_anon(void *addr, unsigned long size, int nr_hpages, uint64_t hpage_size) { - return __check_huge(addr, "AnonHugePages: ", nr_hpages, hpage_size); + if (hpage_size == read_pmd_pagesize()) + return __check_pmd_huge(addr, "AnonHugePages: ", nr_hpages, hpage_size); + + return check_large_folios(addr, size, nr_hpages, hpage_size); } bool check_huge_file(void *addr, int nr_hpages, uint64_t hpage_size) { - return __check_huge(addr, "FilePmdMapped:", nr_hpages, hpage_size); + return __check_pmd_huge(addr, "FilePmdMapped:", nr_hpages, hpage_size); } bool check_huge_shmem(void *addr, unsigned long size, int nr_hpages, uint64_t hpage_size) { - return __check_huge(addr, "ShmemPmdMapped:", nr_hpages, hpage_size); + if (hpage_size == read_pmd_pagesize()) + return __check_pmd_huge(addr, "ShmemPmdMapped:", nr_hpages, hpage_size); + + return check_large_folios(addr, size, nr_hpages, hpage_size); } int64_t allocate_transhuge(void *ptr, int pagemap_fd) -- 2.43.5