[PATCH v4 19/19] KVM: selftests: Add xAPIC support in IRQ test
From: Josh Hilke
Date: Fri May 29 2026 - 20:35:17 EST
From: David Matlack <dmatlack@xxxxxxxxxx>
Add the '-x' flag to tools/testing/selftests/kvm/irq_test.c to configure
the guest to use xAPIC mode instead of the default x2APIC mode. This
expands test coverage to ensure that IRQ injection and routing work
correctly when the guest uses the older xAPIC interface.
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 | 28 +++++++++++++++++++++-----
1 file changed, 23 insertions(+), 5 deletions(-)
diff --git a/tools/testing/selftests/kvm/irq_test.c b/tools/testing/selftests/kvm/irq_test.c
index 967083b8e2ff..29f54a435c8e 100644
--- a/tools/testing/selftests/kvm/irq_test.c
+++ b/tools/testing/selftests/kvm/irq_test.c
@@ -20,6 +20,7 @@ static bool guest_received_irq[KVM_MAX_VCPUS];
static bool guest_received_nmi[KVM_MAX_VCPUS];
static pid_t vcpu_tids[KVM_MAX_VCPUS];
static bool migrate_vcpus;
+static bool x2apic = true;
static bool irq_affinity;
static bool block_vcpus;
static bool done;
@@ -31,14 +32,20 @@ static bool done;
static u32 guest_get_vcpu_id(void)
{
- return x2apic_read_reg(APIC_ID);
+ if (x2apic)
+ return x2apic_read_reg(APIC_ID);
+ else
+ return xapic_read_reg(APIC_ID) >> 24;
}
static void guest_irq_handler(struct ex_regs *regs)
{
WRITE_ONCE(guest_received_irq[guest_get_vcpu_id()], true);
- x2apic_write_reg(APIC_EOI, 0);
+ if (x2apic)
+ x2apic_write_reg(APIC_EOI, 0);
+ else
+ xapic_write_reg(APIC_EOI, 0);
}
static void guest_nmi_handler(struct ex_regs *regs)
@@ -48,7 +55,10 @@ static void guest_nmi_handler(struct ex_regs *regs)
static void guest_code(void)
{
- x2apic_enable();
+ if (x2apic)
+ x2apic_enable();
+ else
+ xapic_enable();
sti_nop();
@@ -144,7 +154,7 @@ static void kvm_clear_gsi_routes(struct kvm_vm *vm)
static void help(const char *name)
{
- printf("Usage: %s [-a] [-b] [-c] [-d <segment:bus:device.function>] [-h] [-i nr_irqs] [-m] [-n] [-v nr_vcpus]\n", name);
+ printf("Usage: %s [-a] [-b] [-c] [-d <segment:bus:device.function>] [-h] [-i nr_irqs] [-m] [-n] [-v nr_vcpus] [-x]\n", name);
printf("\n");
printf("Tests KVM IRQ injection via irqfd using an emulated eventfd.\n");
printf("-a Randomly affinitize the device's host IRQ to different physical CPUs throughout the test\n");
@@ -155,6 +165,7 @@ static void help(const char *name)
printf("-m Pin vCPU threads to random physical CPUs throughout the test\n");
printf("-n Deliver 50 percent of IRQs as non-maskable interrupts\n");
printf("-v Number of vCPUS to run\n");
+ printf("-x Use xAPIC mode instead of x2APIC mode in the guest\n");
printf("\n");
exit(KSFT_FAIL);
}
@@ -188,7 +199,7 @@ int main(int argc, char **argv)
struct kvm_vm *vm;
cpu_set_t available_cpus;
- while ((c = getopt(argc, argv, "abcd:hi:mnv:")) != -1) {
+ while ((c = getopt(argc, argv, "abcd:hi:mnv:x")) != -1) {
switch (c) {
case 'a':
irq_affinity = true;
@@ -214,6 +225,9 @@ int main(int argc, char **argv)
case 'v':
nr_vcpus = atoi_positive("Number of vCPUS", optarg);
break;
+ case 'x':
+ x2apic = false;
+ break;
case 'h':
default:
help(argv[0]);
@@ -226,6 +240,9 @@ int main(int argc, char **argv)
vm_install_exception_handler(vm, vector, guest_irq_handler);
vm_install_exception_handler(vm, NMI_VECTOR, guest_nmi_handler);
+ if (!x2apic)
+ virt_pg_map(vm, APIC_DEFAULT_GPA, APIC_DEFAULT_GPA);
+
if (device_bdf) {
iommu = iommu_init(default_iommu_mode);
device = vfio_pci_device_init(device_bdf, iommu);
@@ -248,6 +265,7 @@ int main(int argc, char **argv)
kvm_assign_irqfd(vm, gsi, eventfd);
+ sync_global_to_guest(vm, x2apic);
sync_global_to_guest(vm, block_vcpus);
for (i = 0; i < nr_vcpus; i++)
--
2.54.0.929.g9b7fa37559-goog