]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
kvm/eventfd: Use priority waitqueue to catch events before userspace irqfd-wait
authorDavid Woodhouse <dwmw@amazon.co.uk>
Mon, 26 Oct 2020 17:43:35 +0000 (17:43 +0000)
committerDavid Woodhouse <dwmw@amazon.co.uk>
Wed, 28 Oct 2020 15:33:13 +0000 (15:33 +0000)
When posted interrupts are available, the IRTE is modified to deliver
interrupts direclty to the vCPU and nothing ever reaches userspace, if
it's listening on the same eventfd that feeds the irqfd.

I like that behaviour. Let's do it all the time, even without posted
interrupts. It makes it much easier to handle IRQ remapping invalidation
without having to constantly add/remove the fd from the userspace poll
set. We can just leave userspace polling on it, and the bypass will...
well... bypass it.

Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
virt/kvm/eventfd.c

index 2b93893657fc968fc87034b6d9e35339d09932e3..e996989cd580e76e058a712dd8e0967b4909ccea 100644 (file)
@@ -191,6 +191,7 @@ irqfd_wakeup(wait_queue_entry_t *wait, unsigned mode, int sync, void *key)
        struct kvm *kvm = irqfd->kvm;
        unsigned seq;
        int idx;
+       int ret = 0;
 
        if (flags & EPOLLIN) {
                u64 cnt;
@@ -207,6 +208,7 @@ irqfd_wakeup(wait_queue_entry_t *wait, unsigned mode, int sync, void *key)
                                              false) == -EWOULDBLOCK)
                        schedule_work(&irqfd->inject);
                srcu_read_unlock(&kvm->irq_srcu, idx);
+               ret = 1;
        }
 
        if (flags & EPOLLHUP) {
@@ -230,7 +232,7 @@ irqfd_wakeup(wait_queue_entry_t *wait, unsigned mode, int sync, void *key)
                spin_unlock_irqrestore(&kvm->irqfds.lock, iflags);
        }
 
-       return 0;
+       return ret;
 }
 
 static void
@@ -239,7 +241,7 @@ irqfd_ptable_queue_proc(struct file *file, wait_queue_head_t *wqh,
 {
        struct kvm_kernel_irqfd *irqfd =
                container_of(pt, struct kvm_kernel_irqfd, pt);
-       add_wait_queue(wqh, &irqfd->wait);
+       add_wait_queue_priority(wqh, &irqfd->wait);
 }
 
 /* Must be called under irqfds.lock */