mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH v3 0/4] KVM: guest_memfd: fix NUMA selftests
@ 2026-09-07  7:24 Shivank Garg
  2026-09-07  7:24 ` [PATCH v3 1/4] KVM: selftests: Prepare guest_memfd_test for arbitrary NUMA nodes Shivank Garg
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Shivank Garg @ 2026-09-07  7:24 UTC (permalink / raw)
  To: Sean Christopherson, Paolo Bonzini, David Hildenbrand,
	Shuah Khan, Jim Mattson, Peter Shier, Ricardo Koller,
	Ackerley Tng
  Cc: kvm, linux-kselftest, linux-kernel, Shivank Garg

NUMA selftests in guest_memfd_test assumes that node 0 and 1 exist and
have memory. However, nodes can be sparse or memoryless which would
break this selftest.  Select the nodes from MPOL_F_MEMS_ALLOWED instead.

Based on KVM: selftests: Fix maxnodes bugs and cleanup related code [1]

Tested on a 7.3-rc1+, AMD EPYC 7713.

[1] https://lore.kernel.org/kvm/20260903001625.2792367-1-seanjc@google.com

Changes in v3:
- Rebase on Sean's spin-off series [1] which picks up patch 1 and 2.
- Drop Patch 3 as version in [1] is better. (Sean)
- Split patch 4 of V2 into 4 patches. (Sean)
- Use MAXNODE_FOR_MASK() for maxnode value. (Sean)
- Link to v2: https://lore.kernel.org/r/20260901-gmem-selftests-fix-v2-0-5a273153354c@amd.com

Changes in V2:
- Split from unbind race fix. (Sean)
- Include <linux/bits.h> that defines BITS_PER_TYPE for self-containment. (Sashiko)
- Link to V1: https://lore.kernel.org/kvm/20260823-shivank-gmem-fix-split-v1-0-512a29fb8e86@amd.com

Signed-off-by: Shivank Garg <shivankg@amd.com>
---
Shivank Garg (4):
      KVM: selftests: Prepare guest_memfd_test for arbitrary NUMA nodes
      KVM: selftests: Use an allowed memory node in test_mbind()
      KVM: selftests: Use allowed memory nodes in test_numa_allocation()
      KVM: selftests: Drop unused sysfs NUMA helpers

 tools/testing/selftests/kvm/guest_memfd_test.c | 61 +++++++++++++++++---------
 tools/testing/selftests/kvm/include/numaif.h   | 52 ----------------------
 2 files changed, 40 insertions(+), 73 deletions(-)
---
base-commit: 88405f0ad1d5c680afe3ea0ce9345fa9e1deaac8
change-id: 20260901-gmem-selftests-fix-2a5e94192f79
prerequisite-message-id: <20260903001625.2792367-1-seanjc@google.com>
prerequisite-patch-id: 6424a3d1e4b372d513b201984c97181a9fc2320d
prerequisite-patch-id: 1d0e83e328934e90b0e8cb9e4c47f9c7c2d12f9b
prerequisite-patch-id: 11bb6b35408a3f251ae7300aa6f1cde2f3ebfac1
prerequisite-patch-id: 7b68398ae0815a4892358359bd067b4cf84c4912
prerequisite-patch-id: 91a2873eeff8555ff7bc728e29a797a07247bdc6
prerequisite-patch-id: d068f85c63973f8bd7606cdb771a3d007b75ad02
prerequisite-patch-id: 26bcf27d961c67b4173bb418fda0a581a6c8a72c

Best regards,
-- 
Shivank Garg <shivankg@amd.com>


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH v3 1/4] KVM: selftests: Prepare guest_memfd_test for arbitrary NUMA nodes
  2026-09-07  7:24 [PATCH v3 0/4] KVM: guest_memfd: fix NUMA selftests Shivank Garg
@ 2026-09-07  7:24 ` Shivank Garg
  2026-09-07  7:24 ` [PATCH v3 2/4] KVM: selftests: Use an allowed memory node in test_mbind() Shivank Garg
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Shivank Garg @ 2026-09-07  7:24 UTC (permalink / raw)
  To: Sean Christopherson, Paolo Bonzini, David Hildenbrand,
	Shuah Khan, Jim Mattson, Peter Shier, Ricardo Koller,
	Ackerley Tng
  Cc: kvm, linux-kselftest, linux-kernel, Shivank Garg

Store the NUMA node IDs used by test_mbind() and
test_numa_allocation(), build nodemasks from those IDs, and use the IDs
when checking move_pages() results.  This prepares both tests to select
nodes at runtime instead of assuming nodes 0 and 1.

No functional change intended.

Signed-off-by: Shivank Garg <shivankg@amd.com>
---
 tools/testing/selftests/kvm/guest_memfd_test.c | 53 +++++++++++++++++---------
 1 file changed, 35 insertions(+), 18 deletions(-)

diff --git a/tools/testing/selftests/kvm/guest_memfd_test.c b/tools/testing/selftests/kvm/guest_memfd_test.c
index cd5df88bc642..b3bd03167ba8 100644
--- a/tools/testing/selftests/kvm/guest_memfd_test.c
+++ b/tools/testing/selftests/kvm/guest_memfd_test.c
@@ -78,31 +78,35 @@ static void test_mmap_supported(int fd, size_t total_size)
 
 static void test_mbind(int fd, size_t total_size)
 {
-	const unsigned long nodemask_0 = 1; /* nid: 0 */
 	unsigned long nodemask = 0;
 	unsigned long maxnode = MAXNODE_FOR_MASK(nodemask);
+	unsigned long bind_nodemask;
 	int policy;
 	char *mem;
+	int nid;
 	int ret;
 
 	if (!is_multi_numa_node_system())
 		return;
 
+	nid = 0;
+	bind_nodemask = BIT(nid);
+
 	mem = kvm_mmap(total_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd);
 
 	/* Test MPOL_INTERLEAVE policy */
-	kvm_mbind(mem, page_size * 2, MPOL_INTERLEAVE, &nodemask_0, maxnode, 0);
+	kvm_mbind(mem, page_size * 2, MPOL_INTERLEAVE, &bind_nodemask, maxnode, 0);
 	kvm_get_mempolicy(&policy, &nodemask, maxnode, mem, MPOL_F_ADDR);
-	TEST_ASSERT(policy == MPOL_INTERLEAVE && nodemask == nodemask_0,
+	TEST_ASSERT(policy == MPOL_INTERLEAVE && nodemask == bind_nodemask,
 		    "Wanted MPOL_INTERLEAVE (%u) and nodemask 0x%lx, got %u and 0x%lx",
-		    MPOL_INTERLEAVE, nodemask_0, policy, nodemask);
+		    MPOL_INTERLEAVE, bind_nodemask, policy, nodemask);
 
 	/* Test basic MPOL_BIND policy */
-	kvm_mbind(mem + page_size * 2, page_size * 2, MPOL_BIND, &nodemask_0, maxnode, 0);
+	kvm_mbind(mem + page_size * 2, page_size * 2, MPOL_BIND, &bind_nodemask, maxnode, 0);
 	kvm_get_mempolicy(&policy, &nodemask, maxnode, mem + page_size * 2, MPOL_F_ADDR);
-	TEST_ASSERT(policy == MPOL_BIND && nodemask == nodemask_0,
+	TEST_ASSERT(policy == MPOL_BIND && nodemask == bind_nodemask,
 		    "Wanted MPOL_BIND (%u) and nodemask 0x%lx, got %u and 0x%lx",
-		    MPOL_BIND, nodemask_0, policy, nodemask);
+		    MPOL_BIND, bind_nodemask, policy, nodemask);
 
 	/* Test MPOL_DEFAULT policy */
 	kvm_mbind(mem, total_size, MPOL_DEFAULT, NULL, 0, 0);
@@ -112,7 +116,7 @@ static void test_mbind(int fd, size_t total_size)
 		    MPOL_DEFAULT, policy, nodemask);
 
 	/* Test with invalid policy */
-	ret = mbind(mem, page_size, 999, &nodemask_0, maxnode, 0);
+	ret = mbind(mem, page_size, 999, &bind_nodemask, maxnode, 0);
 	TEST_ASSERT(ret == -1 && errno == EINVAL,
 		    "mbind with invalid policy should fail with EINVAL");
 
@@ -121,9 +125,9 @@ static void test_mbind(int fd, size_t total_size)
 
 static void test_numa_allocation(int fd, size_t total_size)
 {
-	unsigned long node0_mask = 1;  /* Node 0 */
-	unsigned long node1_mask = 2;  /* Node 1 */
+	unsigned long node0_mask, node1_mask;
 	unsigned long maxnode = 8;
+	int nid0, nid1;
 	void *pages[4];
 	int status[4];
 	char *mem;
@@ -132,6 +136,11 @@ static void test_numa_allocation(int fd, size_t total_size)
 	if (!is_multi_numa_node_system())
 		return;
 
+	nid0 = 0;
+	nid1 = 1;
+	node0_mask = BIT(nid0);
+	node1_mask = BIT(nid1);
+
 	mem = kvm_mmap(total_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd);
 
 	for (i = 0; i < 4; i++)
@@ -149,10 +158,14 @@ static void test_numa_allocation(int fd, size_t total_size)
 
 	/* Validate if pages are allocated on specified NUMA nodes */
 	kvm_move_pages(0, 4, pages, NULL, status, 0);
-	TEST_ASSERT(status[0] == 1, "Expected page 0 on node 1, got it on node %d", status[0]);
-	TEST_ASSERT(status[1] == 1, "Expected page 1 on node 1, got it on node %d", status[1]);
-	TEST_ASSERT(status[2] == 0, "Expected page 2 on node 0, got it on node %d", status[2]);
-	TEST_ASSERT(status[3] == 0, "Expected page 3 on node 0, got it on node %d", status[3]);
+	TEST_ASSERT(status[0] == nid1, "Expected page 0 on node %d, got it on node %d",
+		    nid1, status[0]);
+	TEST_ASSERT(status[1] == nid1, "Expected page 1 on node %d, got it on node %d",
+		    nid1, status[1]);
+	TEST_ASSERT(status[2] == nid0, "Expected page 2 on node %d, got it on node %d",
+		    nid0, status[2]);
+	TEST_ASSERT(status[3] == nid0, "Expected page 3 on node %d, got it on node %d",
+		    nid0, status[3]);
 
 	/* Punch hole for all pages */
 	kvm_fallocate(fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, 0, total_size);
@@ -163,10 +176,14 @@ static void test_numa_allocation(int fd, size_t total_size)
 	memset(mem, 0xaa, total_size);
 
 	kvm_move_pages(0, 4, pages, NULL, status, 0);
-	TEST_ASSERT(status[0] == 0, "Expected page 0 on node 0, got it on node %d", status[0]);
-	TEST_ASSERT(status[1] == 0, "Expected page 1 on node 0, got it on node %d", status[1]);
-	TEST_ASSERT(status[2] == 1, "Expected page 2 on node 1, got it on node %d", status[2]);
-	TEST_ASSERT(status[3] == 1, "Expected page 3 on node 1, got it on node %d", status[3]);
+	TEST_ASSERT(status[0] == nid0, "Expected page 0 on node %d, got it on node %d",
+		    nid0, status[0]);
+	TEST_ASSERT(status[1] == nid0, "Expected page 1 on node %d, got it on node %d",
+		    nid0, status[1]);
+	TEST_ASSERT(status[2] == nid1, "Expected page 2 on node %d, got it on node %d",
+		    nid1, status[2]);
+	TEST_ASSERT(status[3] == nid1, "Expected page 3 on node %d, got it on node %d",
+		    nid1, status[3]);
 
 	kvm_munmap(mem, total_size);
 }

-- 
2.43.0


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH v3 2/4] KVM: selftests: Use an allowed memory node in test_mbind()
  2026-09-07  7:24 [PATCH v3 0/4] KVM: guest_memfd: fix NUMA selftests Shivank Garg
  2026-09-07  7:24 ` [PATCH v3 1/4] KVM: selftests: Prepare guest_memfd_test for arbitrary NUMA nodes Shivank Garg
@ 2026-09-07  7:24 ` Shivank Garg
  2026-09-07  7:24 ` [PATCH v3 3/4] KVM: selftests: Use allowed memory nodes in test_numa_allocation() Shivank Garg
  2026-09-07  7:25 ` [PATCH v3 4/4] KVM: selftests: Drop unused sysfs NUMA helpers Shivank Garg
  3 siblings, 0 replies; 5+ messages in thread
From: Shivank Garg @ 2026-09-07  7:24 UTC (permalink / raw)
  To: Sean Christopherson, Paolo Bonzini, David Hildenbrand,
	Shuah Khan, Jim Mattson, Peter Shier, Ricardo Koller,
	Ackerley Tng
  Cc: kvm, linux-kselftest, linux-kernel, Shivank Garg

test_mbind() hardcodes node 0 and skips the test unless sysfs reports
more than one NUMA node.  This can fail if node 0 has no memory or is
excluded by the task's cpuset.

Pick a node from MPOL_F_MEMS_ALLOWED instead.  The test only needs one
node, so allow it to run on single-node systems too.

Signed-off-by: Shivank Garg <shivankg@amd.com>
---
 tools/testing/selftests/kvm/guest_memfd_test.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/tools/testing/selftests/kvm/guest_memfd_test.c b/tools/testing/selftests/kvm/guest_memfd_test.c
index b3bd03167ba8..ea8e38064e83 100644
--- a/tools/testing/selftests/kvm/guest_memfd_test.c
+++ b/tools/testing/selftests/kvm/guest_memfd_test.c
@@ -81,15 +81,16 @@ static void test_mbind(int fd, size_t total_size)
 	unsigned long nodemask = 0;
 	unsigned long maxnode = MAXNODE_FOR_MASK(nodemask);
 	unsigned long bind_nodemask;
+	unsigned long mems_allowed;
 	int policy;
 	char *mem;
 	int nid;
 	int ret;
 
-	if (!is_multi_numa_node_system())
+	if (!kvm_get_numa_memory_nodes(&mems_allowed))
 		return;
 
-	nid = 0;
+	nid = kvm_get_next_numa_node(mems_allowed, -1);
 	bind_nodemask = BIT(nid);
 
 	mem = kvm_mmap(total_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd);

-- 
2.43.0


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH v3 3/4] KVM: selftests: Use allowed memory nodes in test_numa_allocation()
  2026-09-07  7:24 [PATCH v3 0/4] KVM: guest_memfd: fix NUMA selftests Shivank Garg
  2026-09-07  7:24 ` [PATCH v3 1/4] KVM: selftests: Prepare guest_memfd_test for arbitrary NUMA nodes Shivank Garg
  2026-09-07  7:24 ` [PATCH v3 2/4] KVM: selftests: Use an allowed memory node in test_mbind() Shivank Garg
@ 2026-09-07  7:24 ` Shivank Garg
  2026-09-07  7:25 ` [PATCH v3 4/4] KVM: selftests: Drop unused sysfs NUMA helpers Shivank Garg
  3 siblings, 0 replies; 5+ messages in thread
From: Shivank Garg @ 2026-09-07  7:24 UTC (permalink / raw)
  To: Sean Christopherson, Paolo Bonzini, David Hildenbrand,
	Shuah Khan, Jim Mattson, Peter Shier, Ricardo Koller,
	Ackerley Tng
  Cc: kvm, linux-kselftest, linux-kernel, Shivank Garg

test_numa_allocation() assumes that nodes 0 and 1 exist and are usable.
That is not guaranteed on systems with sparse or memoryless nodes, or
when a cpuset restricts the task.

Pick two nodes from MPOL_F_MEMS_ALLOWED and use MAXNODE_FOR_MASK() when
passing the masks to mbind().  Keep the two-node requirement because the
test verifies that pages are allocated on different nodes.

Signed-off-by: Shivank Garg <shivankg@amd.com>
---
 tools/testing/selftests/kvm/guest_memfd_test.c | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/tools/testing/selftests/kvm/guest_memfd_test.c b/tools/testing/selftests/kvm/guest_memfd_test.c
index ea8e38064e83..cc5abca1adae 100644
--- a/tools/testing/selftests/kvm/guest_memfd_test.c
+++ b/tools/testing/selftests/kvm/guest_memfd_test.c
@@ -127,18 +127,19 @@ static void test_mbind(int fd, size_t total_size)
 static void test_numa_allocation(int fd, size_t total_size)
 {
 	unsigned long node0_mask, node1_mask;
-	unsigned long maxnode = 8;
+	unsigned long maxnode = MAXNODE_FOR_MASK(node0_mask);
+	unsigned long mems_allowed;
 	int nid0, nid1;
 	void *pages[4];
 	int status[4];
 	char *mem;
 	int i;
 
-	if (!is_multi_numa_node_system())
+	if (kvm_get_numa_memory_nodes(&mems_allowed) < 2)
 		return;
 
-	nid0 = 0;
-	nid1 = 1;
+	nid0 = kvm_get_next_numa_node(mems_allowed, -1);
+	nid1 = kvm_get_next_numa_node(mems_allowed, nid0);
 	node0_mask = BIT(nid0);
 	node1_mask = BIT(nid1);
 

-- 
2.43.0


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH v3 4/4] KVM: selftests: Drop unused sysfs NUMA helpers
  2026-09-07  7:24 [PATCH v3 0/4] KVM: guest_memfd: fix NUMA selftests Shivank Garg
                   ` (2 preceding siblings ...)
  2026-09-07  7:24 ` [PATCH v3 3/4] KVM: selftests: Use allowed memory nodes in test_numa_allocation() Shivank Garg
@ 2026-09-07  7:25 ` Shivank Garg
  3 siblings, 0 replies; 5+ messages in thread
From: Shivank Garg @ 2026-09-07  7:25 UTC (permalink / raw)
  To: Sean Christopherson, Paolo Bonzini, David Hildenbrand,
	Shuah Khan, Jim Mattson, Peter Shier, Ricardo Koller,
	Ackerley Tng
  Cc: kvm, linux-kselftest, linux-kernel, Shivank Garg

No users of get_max_numa_node(), is_numa_available(), or
is_multi_numa_node_system() remain.  Remove the helpers and the now
unused dirent.h include.

Signed-off-by: Shivank Garg <shivankg@amd.com>
---
 tools/testing/selftests/kvm/include/numaif.h | 52 ----------------------------
 1 file changed, 52 deletions(-)

diff --git a/tools/testing/selftests/kvm/include/numaif.h b/tools/testing/selftests/kvm/include/numaif.h
index 0945500c6322..c3884017ebb8 100644
--- a/tools/testing/selftests/kvm/include/numaif.h
+++ b/tools/testing/selftests/kvm/include/numaif.h
@@ -4,8 +4,6 @@
 #ifndef SELFTEST_KVM_NUMAIF_H
 #define SELFTEST_KVM_NUMAIF_H
 
-#include <dirent.h>
-
 #include <linux/bitmap.h>
 #include <linux/mempolicy.h>
 
@@ -73,54 +71,4 @@ static inline int kvm_get_next_numa_node(unsigned long nodemask, int from)
 	return to;
 }
 
-static inline int get_max_numa_node(void)
-{
-	struct dirent *de;
-	int max_node = 0;
-	DIR *d;
-
-	/*
-	 * Assume there's a single node if the kernel doesn't support NUMA,
-	 * or if no nodes are found.
-	 */
-	d = opendir("/sys/devices/system/node");
-	if (!d)
-		return 0;
-
-	while ((de = readdir(d)) != NULL) {
-		int node_id;
-		char *endptr;
-
-		if (strncmp(de->d_name, "node", 4) != 0)
-			continue;
-
-		node_id = strtol(de->d_name + 4, &endptr, 10);
-		if (*endptr != '\0')
-			continue;
-
-		if (node_id > max_node)
-			max_node = node_id;
-	}
-	closedir(d);
-
-	return max_node;
-}
-
-static bool is_numa_available(void)
-{
-	/*
-	 * Probe for NUMA by doing a dummy get_mempolicy().  If the syscall
-	 * fails with ENOSYS, then the kernel was built without NUMA support.
-	 * if the syscall fails with EPERM, then the process/user lacks the
-	 * necessary capabilities (CAP_SYS_NICE).
-	 */
-	return !get_mempolicy(NULL, NULL, 0, NULL, 0) ||
-		(errno != ENOSYS && errno != EPERM);
-}
-
-static inline bool is_multi_numa_node_system(void)
-{
-	return is_numa_available() && get_max_numa_node() >= 1;
-}
-
 #endif /* SELFTEST_KVM_NUMAIF_H */

-- 
2.43.0


^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2026-09-07  7:25 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-07  7:24 [PATCH v3 0/4] KVM: guest_memfd: fix NUMA selftests Shivank Garg
2026-09-07  7:24 ` [PATCH v3 1/4] KVM: selftests: Prepare guest_memfd_test for arbitrary NUMA nodes Shivank Garg
2026-09-07  7:24 ` [PATCH v3 2/4] KVM: selftests: Use an allowed memory node in test_mbind() Shivank Garg
2026-09-07  7:24 ` [PATCH v3 3/4] KVM: selftests: Use allowed memory nodes in test_numa_allocation() Shivank Garg
2026-09-07  7:25 ` [PATCH v3 4/4] KVM: selftests: Drop unused sysfs NUMA helpers Shivank Garg

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®