selftests/mm: move HugeTLB helpers to hugepage_settings

Move library functions that abstract HugeTLB /proc and /sysfs access from
vm_util to hugepage_settings.

This will help creating common helpers that save and restore HugeTLB and
THP settings.

Link: https://lore.kernel.org/20260511162840.375890-25-rppt@kernel.org
Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
Tested-by: Luiz Capitulino <luizcap@redhat.com>
Tested-by: Sarthak Sharma <sarthak.sharma@arm.com>
Cc: Baolin Wang <baolin.wang@linux.alibaba.com>
Cc: Barry Song <baohua@kernel.org>
Cc: David Hildenbrand <david@kernel.org>
Cc: Dev Jain <dev.jain@arm.com>
Cc: Donet Tom <donettom@linux.ibm.com>
Cc: Jason Gunthorpe <jgg@ziepe.ca>
Cc: John Hubbard <jhubbard@nvidia.com>
Cc: Lance Yang <lance.yang@linux.dev>
Cc: Leon Romanovsky <leon@kernel.org>
Cc: Liam Howlett <liam@infradead.org>
Cc: Li Wang <li.wang@linux.dev>
Cc: Lorenzo Stoakes <ljs@kernel.org>
Cc: Mark Brown <broonie@kernel.org>
Cc: Michal Hocko <mhocko@suse.com>
Cc: Nico Pache <npache@redhat.com>
Cc: Peter Xu <peterx@redhat.com>
Cc: Ryan Roberts <ryan.roberts@arm.com>
Cc: Shuah Khan <shuah@kernel.org>
Cc: Suren Baghdasaryan <surenb@google.com>
Cc: Vlastimil Babka <vbabka@kernel.org>
Cc: Zi Yan <ziy@nvidia.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
This commit is contained in:
Mike Rapoport (Microsoft) 2026-05-11 19:28:08 +03:00 committed by Andrew Morton
parent 81afb1ee7b
commit 1bdc1698e6
16 changed files with 88 additions and 71 deletions

View File

@ -29,6 +29,7 @@
#include "../../../../mm/gup_test.h"
#include "kselftest.h"
#include "vm_util.h"
#include "hugepage_settings.h"
static size_t pagesize;
static int nr_hugetlbsizes;

View File

@ -11,6 +11,7 @@
*/
#include "kselftest_harness.h"
#include "hugepage_settings.h"
#include <errno.h>
#include <fcntl.h>
@ -27,7 +28,6 @@
#include <sys/ioctl.h>
#include <sys/time.h>
/*
* This is a private UAPI to the kernel test module so it isn't exported
* in the usual include/uapi/... directory.

View File

@ -1,7 +1,9 @@
// SPDX-License-Identifier: GPL-2.0
#include <dirent.h>
#include <fcntl.h>
#include <limits.h>
#include <signal.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -395,3 +397,69 @@ bool thp_is_enabled(void)
/* THP is considered enabled if it's either "always" or "madvise" */
return mode == 1 || mode == 3;
}
int detect_hugetlb_page_sizes(size_t sizes[], int max)
{
DIR *dir = opendir("/sys/kernel/mm/hugepages/");
int count = 0;
if (!dir)
return 0;
while (count < max) {
struct dirent *entry = readdir(dir);
size_t kb;
if (!entry)
break;
if (entry->d_type != DT_DIR)
continue;
if (sscanf(entry->d_name, "hugepages-%zukB", &kb) != 1)
continue;
sizes[count++] = kb * 1024;
ksft_print_msg("[INFO] detected hugetlb page size: %zu KiB\n",
kb);
}
closedir(dir);
return count;
}
unsigned long default_huge_page_size(void)
{
unsigned long hps = 0;
char *line = NULL;
size_t linelen = 0;
FILE *f = fopen("/proc/meminfo", "r");
if (!f)
return 0;
while (getline(&line, &linelen, f) > 0) {
if (sscanf(line, "Hugepagesize: %lu kB", &hps) == 1) {
hps <<= 10;
break;
}
}
free(line);
fclose(f);
return hps;
}
unsigned long get_free_hugepages(void)
{
unsigned long fhp = 0;
char *line = NULL;
size_t linelen = 0;
FILE *f = fopen("/proc/meminfo", "r");
if (!f)
return fhp;
while (getline(&line, &linelen, f) > 0) {
if (sscanf(line, "HugePages_Free: %lu", &fhp) == 1)
break;
}
free(line);
fclose(f);
return fhp;
}

View File

@ -6,6 +6,8 @@
#include <stddef.h>
#include <stdint.h>
/* Transparent Huge Pages (THP) */
enum thp_enabled {
THP_NEVER,
THP_ALWAYS,
@ -86,4 +88,10 @@ unsigned long thp_shmem_supported_orders(void);
bool thp_available(void);
bool thp_is_enabled(void);
/* HugeTLB */
int detect_hugetlb_page_sizes(size_t sizes[], int max);
unsigned long default_huge_page_size(void);
unsigned long get_free_hugepages(void);
#endif /* __HUGEPAGE_SETTINGS_H__ */

View File

@ -20,6 +20,7 @@
#include <fcntl.h>
#include "vm_util.h"
#include "kselftest.h"
#include "hugepage_settings.h"
#define MIN_FREE_PAGES 20
#define NR_HUGE_PAGES 10 /* common number of pages to map/allocate */

View File

@ -18,6 +18,7 @@
#include <linux/memfd.h>
#include "vm_util.h"
#include "kselftest.h"
#include "hugepage_settings.h"
#define LENGTH (256UL*1024*1024)
#define PROTECTION (PROT_READ | PROT_WRITE)

View File

@ -11,6 +11,7 @@
#include <sys/mman.h>
#include <fcntl.h>
#include "vm_util.h"
#include "hugepage_settings.h"
#define PAGE_COMPOUND_HEAD (1UL << 15)
#define PAGE_COMPOUND_TAIL (1UL << 16)

View File

@ -20,6 +20,7 @@
#include <sys/syscall.h>
#include "vm_util.h"
#include "kselftest.h"
#include "hugepage_settings.h"
#ifndef STATX_DIOALIGN
#define STATX_DIOALIGN 0x00002000U

View File

@ -10,6 +10,7 @@
#include "vm_util.h"
#include "kselftest.h"
#include "hugepage_settings.h"
#define INLOOP_ITER 100

View File

@ -25,6 +25,7 @@
#include <unistd.h>
#include "vm_util.h"
#include "hugepage_settings.h"
#define INLOOP_ITER 100

View File

@ -46,6 +46,7 @@
#include <sys/ptrace.h>
#include <setjmp.h>
#include "hugepage_settings.h"
#include "pkey-helpers.h"
int iteration_nr = 1;

View File

@ -28,6 +28,7 @@
#include <string.h>
#include "vm_util.h"
#include "kselftest.h"
#include "hugepage_settings.h"
#if !defined(MAP_HUGETLB)
#define MAP_HUGETLB 0x40000

View File

@ -37,6 +37,7 @@
#include "kselftest.h"
#include "vm_util.h"
#include "hugepage_settings.h"
#define UFFD_FLAGS (O_CLOEXEC | O_NONBLOCK | UFFD_USER_MODE_ONLY)

View File

@ -11,6 +11,7 @@
#include "vm_util.h"
#include "kselftest.h"
#include "hugepage_settings.h"
/*
* The hint addr value is used to allocate addresses

View File

@ -2,7 +2,6 @@
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <dirent.h>
#include <inttypes.h>
#include <sys/ioctl.h>
#include <linux/userfaultfd.h>
@ -291,53 +290,6 @@ int64_t allocate_transhuge(void *ptr, int pagemap_fd)
return -1;
}
unsigned long default_huge_page_size(void)
{
unsigned long hps = 0;
char *line = NULL;
size_t linelen = 0;
FILE *f = fopen("/proc/meminfo", "r");
if (!f)
return 0;
while (getline(&line, &linelen, f) > 0) {
if (sscanf(line, "Hugepagesize: %lu kB", &hps) == 1) {
hps <<= 10;
break;
}
}
free(line);
fclose(f);
return hps;
}
int detect_hugetlb_page_sizes(size_t sizes[], int max)
{
DIR *dir = opendir("/sys/kernel/mm/hugepages/");
int count = 0;
if (!dir)
return 0;
while (count < max) {
struct dirent *entry = readdir(dir);
size_t kb;
if (!entry)
break;
if (entry->d_type != DT_DIR)
continue;
if (sscanf(entry->d_name, "hugepages-%zukB", &kb) != 1)
continue;
sizes[count++] = kb * 1024;
ksft_print_msg("[INFO] detected hugetlb page size: %zu KiB\n",
kb);
}
closedir(dir);
return count;
}
int pageflags_get(unsigned long pfn, int kpageflags_fd, uint64_t *flags)
{
size_t count;
@ -396,25 +348,6 @@ int uffd_unregister(int uffd, void *addr, uint64_t len)
return ret;
}
unsigned long get_free_hugepages(void)
{
unsigned long fhp = 0;
char *line = NULL;
size_t linelen = 0;
FILE *f = fopen("/proc/meminfo", "r");
if (!f)
return fhp;
while (getline(&line, &linelen, f) > 0) {
if (sscanf(line, "HugePages_Free: %lu", &fhp) == 1)
break;
}
free(line);
fclose(f);
return fhp;
}
static bool check_vmflag(void *addr, const char *flag)
{
char buffer[MAX_LINE_LENGTH];

View File

@ -94,8 +94,6 @@ bool check_huge_anon(void *addr, int nr_hpages, uint64_t hpage_size);
bool check_huge_file(void *addr, int nr_hpages, uint64_t hpage_size);
bool check_huge_shmem(void *addr, int nr_hpages, uint64_t hpage_size);
int64_t allocate_transhuge(void *ptr, int pagemap_fd);
unsigned long default_huge_page_size(void);
int detect_hugetlb_page_sizes(size_t sizes[], int max);
int pageflags_get(unsigned long pfn, int kpageflags_fd, uint64_t *flags);
int uffd_register(int uffd, void *addr, uint64_t len,
@ -103,7 +101,6 @@ int uffd_register(int uffd, void *addr, uint64_t len,
int uffd_unregister(int uffd, void *addr, uint64_t len);
int uffd_register_with_ioctls(int uffd, void *addr, uint64_t len,
bool miss, bool wp, bool minor, uint64_t *ioctls);
unsigned long get_free_hugepages(void);
bool check_vmflag_io(void *addr);
bool check_vmflag_pfnmap(void *addr);
bool check_vmflag_guard(void *addr);