lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20260202005451.774496-7-usamaarif642@gmail.com>
Date: Sun,  1 Feb 2026 16:50:23 -0800
From: Usama Arif <usamaarif642@...il.com>
To: ziy@...dia.com,
	Andrew Morton <akpm@...ux-foundation.org>,
	David Hildenbrand <david@...nel.org>,
	lorenzo.stoakes@...cle.com,
	linux-mm@...ck.org
Cc: hannes@...xchg.org,
	riel@...riel.com,
	shakeel.butt@...ux.dev,
	kas@...nel.org,
	baohua@...nel.org,
	dev.jain@....com,
	baolin.wang@...ux.alibaba.com,
	npache@...hat.com,
	Liam.Howlett@...cle.com,
	ryan.roberts@....com,
	vbabka@...e.cz,
	lance.yang@...ux.dev,
	linux-kernel@...r.kernel.org,
	kernel-team@...a.com,
	Usama Arif <usamaarif642@...il.com>
Subject: [RFC 06/12] selftests/mm: add PUD THP basic allocation test

Add a selftest for PUD-level THPs (1GB THPs) with test infrastructure
and a basic allocation test.

The test uses the kselftest harness FIXTURE/TEST_F framework. A shared
fixture allocates a 2GB anonymous mapping and computes a PUD-aligned
address within it. Helper functions read THP counters from /proc/vmstat
and mTHP statistics from sysfs.

The basic allocation test verifies the fundamental PUD THP allocation
path by touching a PUD-aligned region and checking that the mTHP
anon_fault_alloc counter increments, confirming a 1GB folio was
allocated.

Signed-off-by: Usama Arif <usamaarif642@...il.com>
---
 tools/testing/selftests/mm/Makefile       |   1 +
 tools/testing/selftests/mm/pud_thp_test.c | 161 ++++++++++++++++++++++
 2 files changed, 162 insertions(+)
 create mode 100644 tools/testing/selftests/mm/pud_thp_test.c

diff --git a/tools/testing/selftests/mm/Makefile b/tools/testing/selftests/mm/Makefile
index eaf9312097f7b..ab79f1693941a 100644
--- a/tools/testing/selftests/mm/Makefile
+++ b/tools/testing/selftests/mm/Makefile
@@ -88,6 +88,7 @@ TEST_GEN_FILES += pagemap_ioctl
 TEST_GEN_FILES += pfnmap
 TEST_GEN_FILES += process_madv
 TEST_GEN_FILES += prctl_thp_disable
+TEST_GEN_FILES += pud_thp_test
 TEST_GEN_FILES += thuge-gen
 TEST_GEN_FILES += transhuge-stress
 TEST_GEN_FILES += uffd-stress
diff --git a/tools/testing/selftests/mm/pud_thp_test.c b/tools/testing/selftests/mm/pud_thp_test.c
new file mode 100644
index 0000000000000..6f0c02c6afd3a
--- /dev/null
+++ b/tools/testing/selftests/mm/pud_thp_test.c
@@ -0,0 +1,161 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Test program for PUD-level Transparent Huge Pages (1GB anonymous THP)
+ *
+ * Prerequisites:
+ * - Kernel with PUD THP support (CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD)
+ * - THP enabled: echo always > /sys/kernel/mm/transparent_hugepage/enabled
+ * - PUD THP enabled: echo always > /sys/kernel/mm/transparent_hugepage/hugepages-1048576kB/enabled
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/wait.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdint.h>
+#include <sys/syscall.h>
+
+#include "kselftest_harness.h"
+
+#define PUD_SIZE	(1UL << 30)	/* 1GB */
+#define PMD_SIZE	(1UL << 21)	/* 2MB */
+#define PAGE_SIZE	(1UL << 12)	/* 4KB */
+
+#define TEST_REGION_SIZE	(2 * PUD_SIZE)	/* 2GB to ensure PUD alignment */
+
+/* Get PUD-aligned address within a region */
+static inline void *pud_align(void *addr)
+{
+	return (void *)(((unsigned long)addr + PUD_SIZE - 1) & ~(PUD_SIZE - 1));
+}
+
+/* Read vmstat counter */
+static unsigned long read_vmstat(const char *name)
+{
+	FILE *fp;
+	char line[256];
+	unsigned long value = 0;
+
+	fp = fopen("/proc/vmstat", "r");
+	if (!fp)
+		return 0;
+
+	while (fgets(line, sizeof(line), fp)) {
+		if (strncmp(line, name, strlen(name)) == 0 &&
+		    line[strlen(name)] == ' ') {
+			sscanf(line + strlen(name), " %lu", &value);
+			break;
+		}
+	}
+	fclose(fp);
+	return value;
+}
+
+/* Read mTHP stats for PUD order (1GB = 1048576kB) */
+static unsigned long read_mthp_stat(const char *stat_name)
+{
+	char path[256];
+	char buf[64];
+	int fd;
+	ssize_t ret;
+	unsigned long value = 0;
+
+	snprintf(path, sizeof(path),
+		 "/sys/kernel/mm/transparent_hugepage/hugepages-1048576kB/stats/%s",
+		 stat_name);
+	fd = open(path, O_RDONLY);
+	if (fd < 0)
+		return 0;
+	ret = read(fd, buf, sizeof(buf) - 1);
+	close(fd);
+	if (ret <= 0)
+		return 0;
+	buf[ret] = '\0';
+	sscanf(buf, "%lu", &value);
+	return value;
+}
+
+/* Check if PUD THP is enabled */
+static int pud_thp_enabled(void)
+{
+	char buf[64];
+	int fd;
+	ssize_t ret;
+
+	fd = open("/sys/kernel/mm/transparent_hugepage/hugepages-1048576kB/enabled", O_RDONLY);
+	if (fd < 0)
+		return 0;
+	ret = read(fd, buf, sizeof(buf) - 1);
+	close(fd);
+	if (ret <= 0)
+		return 0;
+	buf[ret] = '\0';
+
+	/* Check if [always] or [madvise] is set */
+	if (strstr(buf, "[always]") || strstr(buf, "[madvise]"))
+		return 1;
+	return 0;
+}
+
+/*
+ * Main fixture for PUD THP tests
+ * Allocates a 2GB region and provides a PUD-aligned pointer within it
+ */
+FIXTURE(pud_thp)
+{
+	void *mem;		/* Base mmap allocation */
+	void *aligned;		/* PUD-aligned pointer within mem */
+	unsigned long mthp_alloc_before;
+	unsigned long split_before;
+};
+
+FIXTURE_SETUP(pud_thp)
+{
+	if (!pud_thp_enabled())
+		SKIP(return, "PUD THP not enabled in sysfs");
+
+	self->mthp_alloc_before = read_mthp_stat("anon_fault_alloc");
+	self->split_before = read_vmstat("thp_split_pud");
+
+	self->mem = mmap(NULL, TEST_REGION_SIZE, PROT_READ | PROT_WRITE,
+			 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+	ASSERT_NE(self->mem, MAP_FAILED);
+
+	self->aligned = pud_align(self->mem);
+}
+
+FIXTURE_TEARDOWN(pud_thp)
+{
+	if (self->mem && self->mem != MAP_FAILED)
+		munmap(self->mem, TEST_REGION_SIZE);
+}
+
+/*
+ * Test: Basic PUD THP allocation
+ * Verifies that touching a PUD-aligned region allocates a PUD THP
+ */
+TEST_F(pud_thp, basic_allocation)
+{
+	unsigned long mthp_alloc_after;
+
+	/* Touch memory to trigger page fault and PUD THP allocation */
+	memset(self->aligned, 0xAB, PUD_SIZE);
+
+	mthp_alloc_after = read_mthp_stat("anon_fault_alloc");
+
+	/*
+	 * If mTHP allocation counter increased, a PUD THP was allocated.
+	 */
+	if (mthp_alloc_after <= self->mthp_alloc_before)
+		SKIP(return, "PUD THP not allocated");
+
+	TH_LOG("PUD THP allocated (anon_fault_alloc: %lu -> %lu)",
+	       self->mthp_alloc_before, mthp_alloc_after);
+}
+
+TEST_HARNESS_MAIN
-- 
2.47.3


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ