Re: [PATCH v5 07/21] KVM: selftests: Verify IRQ bypass works in IRQ test
From: Sean Christopherson
Date: Thu Jun 04 2026 - 12:53:20 EST
On Thu, Jun 04, 2026, Josh Hilke wrote:
> @@ -76,9 +109,10 @@ static void kvm_route_msi(struct kvm_vm *vm, u32 gsi, struct kvm_vcpu *vcpu,
>
> static void help(const char *name)
> {
> - printf("Usage: %s [-h]\n", name);
> + printf("Usage: %s [-d <segment:bus:device.function>] [-h]\n", name);
> printf("\n");
> printf("Tests KVM IRQ injection via irqfd using an emulated eventfd.\n");
> + printf("-d Use a VFIO device to send MSI-X interrupts instead of using an emulated eventfd\n");
printf("-d Use a VFIO device to send MSI-X interrupts instead of manually signaling the eventfd\n");
> printf("\n");
> exit(KSFT_FAIL);
> }
> @@ -100,14 +134,21 @@ int main(int argc, char **argv)
> u32 gsi = kvm_random_u64_in_range(&kvm_rng, 24, KVM_MAX_IRQ_ROUTES - 1);
> u8 vector = kvm_random_u64_in_range(&kvm_rng, 32, UINT8_MAX);
>
> - struct kvm_vcpu *vcpus[KVM_MAX_VCPUS];
> pthread_t vcpu_threads[KVM_MAX_VCPUS];
> + struct kvm_vcpu *vcpus[KVM_MAX_VCPUS];
> + struct vfio_pci_device *device = NULL;
> int nr_irqs = 1000, nr_vcpus = 1;
> - int i, j, c, eventfd;
> + const char *device_bdf = NULL;
> + int i, j, c, msix, eventfd;
> + struct iommu *iommu;
> struct kvm_vm *vm;
> + unsigned int irq;
I think it makes sense to track "irq" as a signed int, so that the !device path
can set it to -1. Then it can be printed somewhat blindly without being outright
wrong.
> - while ((c = getopt(argc, argv, "h")) != -1) {
> + while ((c = getopt(argc, argv, "d:h")) != -1) {
> switch (c) {
> + case 'd':
> + device_bdf = optarg;
> + break;
> case 'h':
> default:
> help(argv[0]);
> @@ -119,7 +160,17 @@ int main(int argc, char **argv)
> vm = vm_create_with_vcpus(nr_vcpus, guest_code, vcpus);
> vm_install_exception_handler(vm, vector, guest_irq_handler);
>
> - eventfd = kvm_new_eventfd();
> + if (device_bdf) {
> + iommu = iommu_init(default_iommu_mode);
> + device = vfio_pci_device_init(device_bdf, iommu);
> + msix = vfio_setup_msi(device);
> + irq = vfio_msix_to_host_irq(device_bdf, msix);
> + eventfd = device->msi_eventfds[msix];
> + printf("Using device %s MSI-X[%d] (IRQ-%u)\n", device_bdf, msix,
> + irq);
> + } else {
> + eventfd = kvm_new_eventfd();
> + }
>
> printf("Injecting interrupts for GSI %d (Vector 0x%x) %d times\n",
> gsi, vector, nr_irqs);
> @@ -147,8 +198,7 @@ int main(int argc, char **argv)
> "IRQ flag for vCPU %d not clear prior to test",
> vcpus[j]->id);
Print the IRQ in the assert. Ditto for the pCPU in the future. Providing more
debug information is nice, but it should *always* be secondary to providing info
in the assert/error itself.
TEST_ASSERT(GUEST_RECEIVED_INTERRUPT(vcpu, do_use_nmi),
"vCPU %d timed out waiting for %s (vector 0x%x) from GSI %d (via CPU %d)\n",
vcpu->id, do_use_nmi ? "NMI" : "IRQ",
do_use_nmi ? NMI_VECTOR : vector, gsi, irq_cpu);
>
> - /* Trigger interrupt */
> - eventfd_write(eventfd, 1);
> + trigger_interrupt(device, eventfd);
>
> clock_gettime(CLOCK_MONOTONIC, &start);
> for (;;) {
> --
> 2.54.0.1032.g2f8565e1d1-goog
>