NOT FOR COMMIT - Here's what it would look like to add a GSI
flavor for KVM_EOIFD later.  I expect we're going to need this
to support generic EOI notifiers in qemu when irqchip is enabled.
No API doc included here yet.

Signed-off-by: Alex Williamson <alex.william...@redhat.com>
---

 include/linux/kvm.h |    8 +++++++-
 virt/kvm/eventfd.c  |   17 +++++++++++++++--
 2 files changed, 22 insertions(+), 3 deletions(-)

diff --git a/include/linux/kvm.h b/include/linux/kvm.h
index 5ca887d..18d87fc 100644
--- a/include/linux/kvm.h
+++ b/include/linux/kvm.h
@@ -621,6 +621,7 @@ struct kvm_ppc_smmu_info {
 #define KVM_CAP_IRQFD_LEVEL 81
 #define KVM_CAP_EOIFD 82
 #define KVM_CAP_EOIFD_LEVEL_IRQFD 83
+#define KVM_CAP_EOIFD_GSI 84
 
 #ifdef KVM_CAP_IRQ_ROUTING
 
@@ -699,11 +700,16 @@ struct kvm_irqfd {
 #define KVM_EOIFD_FLAG_DEASSIGN (1 << 0)
 /* Available with KVM_CAP_EOIFD_LEVEL_IRQFD */
 #define KVM_EOIFD_FLAG_LEVEL_IRQFD (1 << 1)
+/* Available with KVM_CAP_EOIFD_GSI */
+#define KVM_EOIFD_FLAG_GSI (1 << 2)
 
 struct kvm_eoifd {
        __u32 fd;
        __u32 flags;
-       __u32 irqfd;
+       union {
+               __u32 irqfd;
+               __u32 gsi;
+       };
        __u8 pad[20];
 };
 
diff --git a/virt/kvm/eventfd.c b/virt/kvm/eventfd.c
index 2fae198..b6d9c1c 100644
--- a/virt/kvm/eventfd.c
+++ b/virt/kvm/eventfd.c
@@ -826,6 +826,11 @@ static void eoifd_event(struct kvm_irq_ack_notifier 
*notifier)
 
        eoifd = container_of(notifier, struct _eoifd, notifier);
 
+       if (!eoifd->level_irqfd) {
+               eventfd_signal(eoifd->eventfd, 1);
+               return;
+       }
+
        /*
         * Ack notifier is per GSI, which may be shared with others.
         * Only de-assert and send EOI if our source ID is asserted.
@@ -876,6 +881,8 @@ static int kvm_assign_eoifd(struct kvm *kvm, struct 
kvm_eoifd *args)
                        ret = -EINVAL;
                        goto fail;
                }
+       } else if (args->flags & KVM_EOIFD_FLAG_GSI) {
+               gsi = args->gsi;
        } else {
                ret = -EINVAL;
                goto fail;
@@ -934,6 +941,7 @@ static int kvm_deassign_eoifd(struct kvm *kvm, struct 
kvm_eoifd *args)
 {
        struct eventfd_ctx *eventfd = NULL, *level_irqfd = NULL;
        struct _eoifd *eoifd;
+       unsigned gsi = ~0;
        int ret = -ENOENT;
 
        eventfd = eventfd_ctx_fdget(args->fd);
@@ -948,6 +956,8 @@ static int kvm_deassign_eoifd(struct kvm *kvm, struct 
kvm_eoifd *args)
                        ret = PTR_ERR(level_irqfd);
                        goto fail;
                }
+       } else if (args->flags & KVM_EOIFD_FLAG_GSI) {
+               gsi = args->gsi;
        } else {
                ret = -EINVAL;
                goto fail;
@@ -957,7 +967,9 @@ static int kvm_deassign_eoifd(struct kvm *kvm, struct 
kvm_eoifd *args)
 
        list_for_each_entry(eoifd, &kvm->eoifds.items, list) {
                if (eoifd->eventfd == eventfd &&
-                   eoifd->level_irqfd == level_irqfd) {
+                   ((level_irqfd && eoifd->level_irqfd == level_irqfd) ||
+                    (!level_irqfd && !eoifd->level_irqfd &&
+                     eoifd->notifier.gsi == gsi))) {
                        eoifd_destroy(kvm, eoifd);
                        ret = 0;
                        break;
@@ -978,7 +990,8 @@ fail:
 int kvm_eoifd(struct kvm *kvm, struct kvm_eoifd *args)
 {
        if (args->flags & ~(KVM_EOIFD_FLAG_DEASSIGN |
-                           KVM_EOIFD_FLAG_LEVEL_IRQFD))
+                           KVM_EOIFD_FLAG_LEVEL_IRQFD |
+                           KVM_EOIFD_FLAG_GSI))
                return -EINVAL;
 
        if (args->flags & KVM_EOIFD_FLAG_DEASSIGN)

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to