diff --git a/tools/testing/selftests/kvm/irq_test.c b/tools/testing/selftests/kvm/irq_test.c index d2c745c54960..240f6f0fdbe4 100644 --- a/tools/testing/selftests/kvm/irq_test.c +++ b/tools/testing/selftests/kvm/irq_test.c @@ -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 ] [-e] [-h] [-i nr_irqs] [-m] [-n] [-t iommu_type] [-v nr_vcpus]\n", name); + printf("Usage: %s [-a] [-d ] [-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);