* [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®