Add an irq_bypass consumer to the KVM eventfd, so that when a MSI interrupt happens and triggerred from VFIO, it can be handled fast. Signed-off-by: Yunhong Jiang <yunhong.jiang@xxxxxxxxxxxxxxx> --- include/linux/kvm_irqfd.h | 1 + virt/kvm/eventfd.c | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/include/linux/kvm_irqfd.h b/include/linux/kvm_irqfd.h index 0c1de05098c8..5573d53ccebb 100644 --- a/include/linux/kvm_irqfd.h +++ b/include/linux/kvm_irqfd.h @@ -65,6 +65,7 @@ struct kvm_kernel_irqfd { poll_table pt; struct work_struct shutdown; struct irq_bypass_consumer consumer; + struct irq_bypass_consumer fastpath; struct irq_bypass_producer *producer; }; diff --git a/virt/kvm/eventfd.c b/virt/kvm/eventfd.c index c31d43b762db..b20a2d1bbf73 100644 --- a/virt/kvm/eventfd.c +++ b/virt/kvm/eventfd.c @@ -144,6 +144,8 @@ irqfd_shutdown(struct work_struct *work) #ifdef CONFIG_HAVE_KVM_IRQ_BYPASS irq_bypass_unregister_consumer(&irqfd->consumer); #endif + if (irqfd->fastpath.token) + irq_bypass_unregister_consumer(&irqfd->fastpath); eventfd_ctx_put(irqfd->eventfd); kfree(irqfd); } @@ -203,6 +205,14 @@ irqfd_wakeup_pollin(struct kvm_kernel_irqfd *irqfd) } static int +kvm_fastpath_irq(void *arg) +{ + struct kvm_kernel_irqfd *irqfd = arg; + + return irqfd_wakeup_pollin(irqfd); +} + +static int irqfd_wakeup_pollup(struct kvm_kernel_irqfd *irqfd) { struct kvm *kvm = irqfd->kvm; @@ -296,6 +306,34 @@ int __attribute__((weak)) kvm_arch_update_irqfd_routing( } #endif +static int kvm_fastpath_stub(struct irq_bypass_consumer *stub, + struct irq_bypass_producer *stub1) +{ + return 0; +} + +static void kvm_fastpath_stub1(struct irq_bypass_consumer *stub, + struct irq_bypass_producer *stub1) +{ +} + +static int setup_fastpath_consumer(struct kvm_kernel_irqfd *irqfd) +{ + int ret; + + irqfd->fastpath.token = (void *)irqfd->eventfd; + irqfd->fastpath.add_producer = kvm_fastpath_stub; + irqfd->fastpath.del_producer = kvm_fastpath_stub1; + irqfd->fastpath.handle_irq = kvm_fastpath_irq; + irqfd->fastpath.irq_context = irqfd; + ret = irq_bypass_register_consumer(&irqfd->fastpath); + + if (ret) + /* A special tag to indicate consumer not working */ + irqfd->fastpath.token = (void *)0; + return ret; +} + static int kvm_irqfd_assign(struct kvm *kvm, struct kvm_irqfd *args) { @@ -435,6 +473,10 @@ kvm_irqfd_assign(struct kvm *kvm, struct kvm_irqfd *args) irqfd->consumer.token, ret); #endif + if (setup_fastpath_consumer(irqfd)) + pr_info("irq bypass fastpath consumer (toke %p) registration fails: %d\n", + irqfd->eventfd, ret); + return 0; fail: -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html