KVM: selftests: Add xAPIC support in eventfd IRQ test

Extend the eventfd IRQ test with a '-x' flag to let the user run the test
in xAPIC mode instead of the default x2APIC mode.  When using xAPIC mode,
sanity check user input to ensure the test is being run with at most 255
vCPUs, as xAPIC can only address IDs 0-254 (255, i.e. 0xff, broadcasts to
all CPUs).

Signed-off-by: David Matlack <dmatlack@google.com>
Co-developed-by: Josh Hilke <jrhilke@google.com>
Signed-off-by: Josh Hilke <jrhilke@google.com>
[sean: add sanity check on number of vCPUs]
Link: https://patch.msgid.link/20260626213534.3866178-21-seanjc@google.com
Signed-off-by: Sean Christopherson <seanjc@google.com>
This commit is contained in:
David Matlack 2026-06-26 14:35:33 -07:00 committed by Sean Christopherson
parent 0315713a19
commit 2708ecca4d

View File

@ -18,6 +18,7 @@ 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 bool x2apic = true;
static bool irq_affinity;
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();
@ -158,7 +168,7 @@ static const char *probe_iommu_type(void)
static void help(const char *name)
{
printf("Usage: %s [-a] [-d <segment:bus:device.function>] [-e] [-h] [-i nr_irqs] [-m] [-n] [-t iommu_type] [-v nr_vcpus]\n", name);
printf("Usage: %s [-a] [-d <segment:bus:device.function>] [-e] [-h] [-i nr_irqs] [-m] [-n] [-t iommu_type] [-v nr_vcpus] [-x]\n", name);
printf("\n");
printf("Tests KVM interrupt routing and delivery via irqfd.\n");
printf("-a Affine the device's host IRQ to a random physical CPU\n");
@ -169,6 +179,7 @@ static void help(const char *name)
printf("-n Deliver 50 percent of IRQs as non-maskable interrupts\n");
printf("-t Override the IOMMU type to use (vfio_type1_iommu or iommufd)\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);
}
@ -205,7 +216,7 @@ int main(int argc, char **argv)
struct kvm_vm *vm;
int irq, irq_cpu;
while ((c = getopt(argc, argv, "ad:ehi:mnt:v:")) != -1) {
while ((c = getopt(argc, argv, "ad:ehi:mnt:v:x")) != -1) {
switch (c) {
case 'a':
irq_affinity = true;
@ -233,6 +244,9 @@ int main(int argc, char **argv)
TEST_ASSERT(nr_vcpus <= KVM_MAX_VCPUS,
"KVM selftests support at most %u vCPUs", KVM_MAX_VCPUS);
break;
case 'x':
x2apic = false;
break;
case 'h':
default:
help(argv[0]);
@ -248,6 +262,11 @@ 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) {
TEST_ASSERT(nr_vcpus < 256, "xAPIC can only target IDs [0-254] (255 vCPUs)");
virt_pg_map(vm, APIC_DEFAULT_GPA, APIC_DEFAULT_GPA);
}
if (device_bdf) {
if (!iommu_type)
iommu_type = probe_iommu_type();
@ -271,6 +290,8 @@ int main(int argc, char **argv)
kvm_assign_irqfd(vm, gsi, eventfd);
sync_global_to_guest(vm, x2apic);
if (migrate_vcpus)
kvm_sched_getaffinity(0, sizeof(available_cpus), &available_cpus);