Re: [PATCH v5 18/21] KVM: selftests: Verify vCPU migration during IRQ delivery in IRQ test

From: Sean Christopherson

Date: Thu Jun 04 2026 - 13:34:11 EST


On Thu, Jun 04, 2026, Josh Hilke wrote:
> From: David Matlack <dmatlack@xxxxxxxxxx>
>
> Add the '-m' flag to tools/testing/selftests/kvm/irq_test.c to migrate
> vCPU threads across random physical CPUs during the test. This validates
> KVM's ability to handle vCPUs changing physical CPUs while interrupts
> are actively being injected.
>
> Co-developed-by: Josh Hilke <jrhilke@xxxxxxxxxx>
> Signed-off-by: Josh Hilke <jrhilke@xxxxxxxxxx>
> Signed-off-by: David Matlack <dmatlack@xxxxxxxxxx>
> ---
> tools/testing/selftests/kvm/irq_test.c | 33 ++++++++++++++++++++++++--
> 1 file changed, 31 insertions(+), 2 deletions(-)
>
> diff --git a/tools/testing/selftests/kvm/irq_test.c b/tools/testing/selftests/kvm/irq_test.c
> index ed48562318bf..5f7df76005ec 100644
> --- a/tools/testing/selftests/kvm/irq_test.c
> +++ b/tools/testing/selftests/kvm/irq_test.c
> @@ -18,6 +18,8 @@ static u64 timeout_ns = 2ULL * 1000 * 1000 * 1000;
> static bool guest_ready_for_irqs[KVM_MAX_VCPUS];
> static bool guest_received_irq[KVM_MAX_VCPUS];
> static bool guest_received_nmi[KVM_MAX_VCPUS];
> +static pid_t vcpu_tids[KVM_MAX_VCPUS];

This doesn't need to exist.

> +static bool migrate_vcpus;

This doesn't need to be globally visible.

> static bool irq_affinity;
> static bool block_vcpus;
> static bool done;
> @@ -67,12 +69,23 @@ static void *vcpu_thread_main(void *arg)
> struct kvm_vcpu *vcpu = arg;
> struct ucall uc;
>
> + WRITE_ONCE(vcpu_tids[vcpu->id], kvm_gettid());

...

> @@ -246,6 +264,14 @@ int main(int argc, char **argv)
> */
> irq_cpu = -1;
>
> + if (migrate_vcpus) {
> + kvm_sched_getaffinity(vcpu_tids[0], sizeof(available_cpus), &available_cpus);

This is silly, just use the affinity of the main task. There's no reason to go
look at a child task's affinity.

> +
> + if (nr_vcpus > CPU_COUNT(&available_cpus)) {
> + printf("There are more vCPUs than pCPUs; refusing to migrate.\n");

Why? Overcommitting vCPUs:pCPUs is quite common, and arguably more interesting
for this test. And it's not like the test prevents overlap anyways (it is random
after all).

> + migrate_vcpus = false;
> + }
> + }
> for (i = 0; i < nr_irqs; i++) {
> const bool do_clear_routes = clear_routes && (i & BIT(3));
> const bool do_use_nmi = use_nmi && (i & BIT(2));
> @@ -262,6 +288,9 @@ int main(int argc, char **argv)
> write_proc_irq_smp_affinity_list(irq_affinity_fp, irq, irq_cpu);
> }
>
> + if (migrate_vcpus && vcpu->id == 0)
> + migrate_vcpu_threads(nr_vcpus, vcpu_threads, &available_cpus);

Meh, rather than shuffle everything in a batch, just change the affinity for the
target vCPU. That makes the code easier to read, and is arguably more interesting
because there's at least some chance the task will be migrated while the interrupt
is being delivered, whereas migrating everything up front means the migrations will
have completed before the interrupt is sent the vast majority of the time.

> +
> for (j = 0; j < nr_vcpus; j++) {
> TEST_ASSERT(!GUEST_RECEIVED_IRQ(vcpus[j]),
> "IRQ flag for vCPU %d not clear prior to test",
> --
> 2.54.0.1032.g2f8565e1d1-goog
>