[PATCH 5/7] KVM: selftests: Add common helper to get mask+number of usable memory NUMA nodes
From: Sean Christopherson
Date: Wed Sep 02 2026 - 20:18:20 EST
Extract and slightly adopt the xAPIC IPI test's logic for getting the mask
and number of usable memory NUMA nodes into a common helper. To allow for
friendlier behavior when the underlying kernel doesn't support NUMA, or the
test was run without sufficient permissions, zero out the mask and return
"zero nodes" if get_mempolicy() fails with ENOSYS or EPERM respectively.
I.e. allow tests to skip (sub)tests instead of throwing an assert.
Suggested-by: Shivank Garg <shivankg@xxxxxxx>
Signed-off-by: Sean Christopherson <seanjc@xxxxxxxxxx>
---
tools/testing/selftests/kvm/include/numaif.h | 13 +++++++++++++
tools/testing/selftests/kvm/x86/xapic_ipi_test.c | 5 +----
2 files changed, 14 insertions(+), 4 deletions(-)
diff --git a/tools/testing/selftests/kvm/include/numaif.h b/tools/testing/selftests/kvm/include/numaif.h
index 299dddff2729..0945500c6322 100644
--- a/tools/testing/selftests/kvm/include/numaif.h
+++ b/tools/testing/selftests/kvm/include/numaif.h
@@ -41,6 +41,19 @@ KVM_SYSCALL_DEFINE(mbind, 6, void *, addr, unsigned long, size, int, mode,
*/
#define MAXNODE_FOR_MASK(mask) (BITS_PER_TYPE(mask) + 1)
+static inline int kvm_get_numa_memory_nodes(unsigned long *nodemask)
+{
+ int r;
+
+ *nodemask = 0;
+
+ r = get_mempolicy(NULL, nodemask, MAXNODE_FOR_MASK(*nodemask), 0,
+ MPOL_F_MEMS_ALLOWED);
+ TEST_ASSERT(!r || errno == ENOSYS || errno == EPERM,
+ "Unexpected get_mempolicy() failure");
+ return __builtin_popcountl(*nodemask);
+}
+
/*
* Return the node ID of the next NUMA node in the mask, starting at @from+1.
* Guarantees a node is found, and that the found node is not @from. Pass -1
diff --git a/tools/testing/selftests/kvm/x86/xapic_ipi_test.c b/tools/testing/selftests/kvm/x86/xapic_ipi_test.c
index 7144ad833ae0..42c601617f5a 100644
--- a/tools/testing/selftests/kvm/x86/xapic_ipi_test.c
+++ b/tools/testing/selftests/kvm/x86/xapic_ipi_test.c
@@ -244,15 +244,12 @@ void do_migrations(struct test_data_page *data, int run_secs, int delay_usecs,
fprintf(stderr, "Calling migrate_pages every %d microseconds\n",
delay_usecs);
- /* Get set of first 64 numa nodes available */
- kvm_get_mempolicy(NULL, &nodemask, MAXNODE_FOR_MASK(nodemask),
- 0, MPOL_F_MEMS_ALLOWED);
+ nodes = kvm_get_numa_memory_nodes(&nodemask);
fprintf(stderr, "Numa nodes found amongst first %lu possible nodes "
"(each 1-bit indicates node is present): %#lx\n",
BITS_PER_TYPE(nodemask), nodemask);
- nodes = __builtin_popcountl(nodemask);
TEST_ASSERT(nodes > 1,
"Did not find at least 2 numa nodes. Can't do migration");
--
2.55.0.970.g62bdec98f9-goog