From: Sean Christopherson <seanjc@google.com>
To: Paolo Bonzini <pbonzini@redhat.com>,
Sean Christopherson <seanjc@google.com>
Cc: kvm@vger.kernel.org, linux-kernel@vger.kernel.org,
Shivank Garg <shivankg@amd.com>
Subject: [PATCH 4/7] KVM: selftests: Compute node masks on-demand in xAPIC IPI test
Date: Wed, 2 Sep 2026 17:16:22 -0700 [thread overview]
Message-ID: <20260903001625.2792367-5-seanjc@google.com> (raw)
In-Reply-To: <20260903001625.2792367-1-seanjc@google.com>
Compute the node masks for the source (from) and destination (to) NUMA
nodes in the xAPIC IPI test instead of pre-filling an array of masks with
node per mask. Computing the mask on-demand is technically slower, but
doesn't require a large-ish on-stack array, and more importantly allows the
test to use a generic "get next NUMA node" API without having to commit all
of KVM selftests to using a large array of single-bit nodemasks.
Implement said API as a common KVM NUMA API so that it can be used by other
tests, e.g. in guest_memfd tests. Deliberately make @from "exclusive" as
the anticipated usage in KVM selftests is to select the next, *different*
node, i.e. so that users don't have to copy+paste code to assert that the
found node is different than the starting node. The obvious downside is
that implementing the exclusive logic forces callers to pass -1 instead of
0 when the goal is to find the first node in the mask, but that arguably
yields more intuitive code anyways.
From an overall test functionality/coverage perspective, no functional
change intended (the walking pattern of node migration should be unchanged).
Signed-off-by: Sean Christopherson <seanjc@google.com>
---
tools/testing/selftests/kvm/include/numaif.h | 21 +++++++++++-
.../selftests/kvm/x86/xapic_ipi_test.c | 32 ++++++-------------
2 files changed, 30 insertions(+), 23 deletions(-)
diff --git a/tools/testing/selftests/kvm/include/numaif.h b/tools/testing/selftests/kvm/include/numaif.h
index 71f261eafc90..299dddff2729 100644
--- a/tools/testing/selftests/kvm/include/numaif.h
+++ b/tools/testing/selftests/kvm/include/numaif.h
@@ -6,7 +6,7 @@
#include <dirent.h>
-#include <linux/bitops.h>
+#include <linux/bitmap.h>
#include <linux/mempolicy.h>
#include "kvm_syscalls.h"
@@ -41,6 +41,25 @@ KVM_SYSCALL_DEFINE(mbind, 6, void *, addr, unsigned long, size, int, mode,
*/
#define MAXNODE_FOR_MASK(mask) (BITS_PER_TYPE(mask) + 1)
+/*
+ * 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
+ * to find the first node in the mask.
+ */
+static inline int kvm_get_next_numa_node(unsigned long nodemask, int from)
+{
+ const unsigned long nr_bits = BITS_PER_TYPE(nodemask);
+ int to;
+
+ to = find_next_bit(&nodemask, nr_bits, from + 1);
+ if (to == nr_bits)
+ to = find_next_bit(&nodemask, nr_bits, 0);
+
+ TEST_ASSERT(to != nr_bits && to != from,
+ "Unabled to find second NUMA node (from = %d, to = %d)", from, to);
+ return to;
+}
+
static inline int get_max_numa_node(void)
{
struct dirent *de;
diff --git a/tools/testing/selftests/kvm/x86/xapic_ipi_test.c b/tools/testing/selftests/kvm/x86/xapic_ipi_test.c
index 9d1dfad4efa6..7144ad833ae0 100644
--- a/tools/testing/selftests/kvm/x86/xapic_ipi_test.c
+++ b/tools/testing/selftests/kvm/x86/xapic_ipi_test.c
@@ -233,13 +233,10 @@ void do_migrations(struct test_data_page *data, int run_secs, int delay_usecs,
{
long pages_not_moved;
unsigned long nodemask = 0;
- unsigned long nodemasks[BITS_PER_TYPE(nodemask)];
int nodes = 0;
time_t start_time, last_update, now;
time_t interval_secs = 1;
- int i;
int from, to;
- unsigned long bit;
u64 hlt_count;
u64 wake_count;
u64 ipis_sent;
@@ -255,24 +252,15 @@ void do_migrations(struct test_data_page *data, int run_secs, int delay_usecs,
"(each 1-bit indicates node is present): %#lx\n",
BITS_PER_TYPE(nodemask), nodemask);
- /* Init array of masks containing a single-bit in each, one for each
- * available node. migrate_pages called below requires specifying nodes
- * as bit masks.
- */
- for (i = 0, bit = 1; i < BITS_PER_TYPE(nodemask); i++, bit <<= 1) {
- if (nodemask & bit) {
- nodemasks[nodes] = nodemask & bit;
- nodes++;
- }
- }
-
+ nodes = __builtin_popcountl(nodemask);
TEST_ASSERT(nodes > 1,
"Did not find at least 2 numa nodes. Can't do migration");
fprintf(stderr, "Migrating amongst %d nodes found\n", nodes);
- from = 0;
- to = 1;
+ from = kvm_get_next_numa_node(nodemask, -1);
+ to = kvm_get_next_numa_node(nodemask, from);
+
start_time = time(NULL);
last_update = start_time;
@@ -281,6 +269,9 @@ void do_migrations(struct test_data_page *data, int run_secs, int delay_usecs,
wake_count = data->wake_count;
while ((int)(time(NULL) - start_time) < run_secs) {
+ unsigned long from_mask = BIT(from);
+ unsigned long to_mask = BIT(to);
+
data->migrations_attempted++;
/*
@@ -291,9 +282,8 @@ void do_migrations(struct test_data_page *data, int run_secs, int delay_usecs,
* KVM_CREATE_VCPU ioctl. If that assumption ever changes this
* test may break or give a false positive signal.
*/
- pages_not_moved = migrate_pages(0, MAXNODE_FOR_MASK(nodemasks[from]),
- &nodemasks[from],
- &nodemasks[to]);
+ pages_not_moved = migrate_pages(0, MAXNODE_FOR_MASK(from_mask),
+ &from_mask, &to_mask);
if (pages_not_moved < 0)
fprintf(stderr,
"migrate_pages failed, errno=%d\n", errno);
@@ -305,9 +295,7 @@ void do_migrations(struct test_data_page *data, int run_secs, int delay_usecs,
data->migrations_completed++;
from = to;
- to++;
- if (to == nodes)
- to = 0;
+ to = kvm_get_next_numa_node(nodemask, from);
now = time(NULL);
if (((now - start_time) % interval_secs == 0) &&
--
2.55.0.970.g62bdec98f9-goog
next prev parent reply other threads:[~2026-09-03 0:16 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-03 0:16 [PATCH 0/7] KVM: selftests: Fix maxnodes bugs and cleanup related code Sean Christopherson
2026-09-03 0:16 ` [PATCH 1/7] KVM: selftests: Account for kernel's off-by-one bug in NUMA node syscalls Sean Christopherson
2026-09-06 10:08 ` Garg, Shivank
2026-09-03 0:16 ` [PATCH 2/7] KVM: selftests: Fix maxnode argument to migrate_pages() in xapic_ipi_test Sean Christopherson
2026-09-03 0:16 ` [PATCH 3/7] KVM: selftests: use BITS_PER_TYPE() for NUMA masks Sean Christopherson
2026-09-03 0:16 ` Sean Christopherson [this message]
2026-09-06 17:05 ` [PATCH 4/7] KVM: selftests: Compute node masks on-demand in xAPIC IPI test Garg, Shivank
2026-09-03 0:16 ` [PATCH 5/7] KVM: selftests: Add common helper to get mask+number of usable memory NUMA nodes Sean Christopherson
2026-09-06 17:53 ` Garg, Shivank
2026-09-03 0:16 ` [PATCH 6/7] KVM: selftests: Automatically run xAPIC IPI migration test when possible Sean Christopherson
2026-09-06 18:01 ` Garg, Shivank
2026-09-03 0:16 ` [PATCH 7/7] KVM: selftests: Skip xAPIC IPI migration test when forced but unsupported Sean Christopherson
2026-09-06 18:13 ` Garg, Shivank
2026-09-21 14:05 ` [PATCH 0/7] KVM: selftests: Fix maxnodes bugs and cleanup related code Sean Christopherson
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260903001625.2792367-5-seanjc@google.com \
--to=seanjc@google.com \
--cc=kvm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=pbonzini@redhat.com \
--cc=shivankg@amd.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.