qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH] KVM: IRQFD: equip irqfd and resamplefd with polarit


From: Liu Ping Fan
Subject: [Qemu-devel] [PATCH] KVM: IRQFD: equip irqfd and resamplefd with polarity
Date: Thu, 12 Sep 2013 13:28:27 +0800

Nowadays, irqfd can emulate trigger mode, but it can not emulate
trigger polarity. While in some cases, ioapic ioredtbl[x] expects
_low_ active. So equipping irqfd with the ability. Correspondingly,
resamplefd will have the same polarity as irqfd.

Signed-off-by: Liu Ping Fan <address@hidden>
---
This helps to step around making the interrupt component re-entrance
in qemu
---
 include/linux/kvm_host.h |  1 +
 include/uapi/linux/kvm.h |  2 ++
 virt/kvm/eventfd.c       | 32 ++++++++++++++++++++++----------
 3 files changed, 25 insertions(+), 10 deletions(-)

diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index a63d83e..0b8c3b1 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -678,6 +678,7 @@ bool kvm_is_mmio_pfn(pfn_t pfn);
 struct kvm_irq_ack_notifier {
        struct hlist_node link;
        unsigned gsi;
+       int polarity; /* 0 high active */
        void (*irq_acked)(struct kvm_irq_ack_notifier *kian);
 };
 
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index acccd08..bba3a1b 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -740,6 +740,8 @@ struct kvm_xen_hvm_config {
  * emlation.  See Documentation/virtual/kvm/api.txt.
  */
 #define KVM_IRQFD_FLAG_RESAMPLE (1 << 1)
+/* 0: high-active */
+#define KVM_IRQFD_FLAG_POLARITY (1<<2)
 
 struct kvm_irqfd {
        __u32 fd;
diff --git a/virt/kvm/eventfd.c b/virt/kvm/eventfd.c
index 1550637..865c656 100644
--- a/virt/kvm/eventfd.c
+++ b/virt/kvm/eventfd.c
@@ -77,6 +77,7 @@ struct _irqfd {
        struct kvm_kernel_irq_routing_entry __rcu *irq_entry;
        /* Used for level IRQ fast-path */
        int gsi;
+       int polarity; /* 0 high active */
        struct work_struct inject;
        /* The resampler used by this irqfd (resampler-only) */
        struct _irqfd_resampler *resampler;
@@ -100,13 +101,13 @@ irqfd_inject(struct work_struct *work)
        struct kvm *kvm = irqfd->kvm;
 
        if (!irqfd->resampler) {
-               kvm_set_irq(kvm, KVM_USERSPACE_IRQ_SOURCE_ID, irqfd->gsi, 1,
-                               false);
-               kvm_set_irq(kvm, KVM_USERSPACE_IRQ_SOURCE_ID, irqfd->gsi, 0,
-                               false);
+               kvm_set_irq(kvm, KVM_USERSPACE_IRQ_SOURCE_ID, irqfd->gsi,
+                               !irqfd->polarity, false);
+               kvm_set_irq(kvm, KVM_USERSPACE_IRQ_SOURCE_ID, irqfd->gsi,
+                               !!irqfd->polarity, false);
        } else
                kvm_set_irq(kvm, KVM_IRQFD_RESAMPLE_IRQ_SOURCE_ID,
-                           irqfd->gsi, 1, false);
+                           irqfd->gsi, !irqfd->polarity, false);
 }
 
 /*
@@ -123,7 +124,8 @@ irqfd_resampler_ack(struct kvm_irq_ack_notifier *kian)
        resampler = container_of(kian, struct _irqfd_resampler, notifier);
 
        kvm_set_irq(resampler->kvm, KVM_IRQFD_RESAMPLE_IRQ_SOURCE_ID,
-                   resampler->notifier.gsi, 0, false);
+               resampler->notifier.gsi,
+               !!resampler->notifier.polarity, false);
 
        rcu_read_lock();
 
@@ -148,7 +150,7 @@ irqfd_resampler_shutdown(struct _irqfd *irqfd)
                list_del(&resampler->link);
                kvm_unregister_irq_ack_notifier(kvm, &resampler->notifier);
                kvm_set_irq(kvm, KVM_IRQFD_RESAMPLE_IRQ_SOURCE_ID,
-                           resampler->notifier.gsi, 0, false);
+                           resampler->notifier.gsi, !!irqfd->polarity, false);
                kfree(resampler);
        }
 
@@ -302,6 +304,7 @@ kvm_irqfd_assign(struct kvm *kvm, struct kvm_irqfd *args)
 
        irqfd->kvm = kvm;
        irqfd->gsi = args->gsi;
+       irqfd->polarity = !!(args->flags & KVM_IRQFD_FLAG_POLARITY);
        INIT_LIST_HEAD(&irqfd->list);
        INIT_WORK(&irqfd->inject, irqfd_inject);
        INIT_WORK(&irqfd->shutdown, irqfd_shutdown);
@@ -337,8 +340,15 @@ kvm_irqfd_assign(struct kvm *kvm, struct kvm_irqfd *args)
                list_for_each_entry(resampler,
                                    &kvm->irqfds.resampler_list, link) {
                        if (resampler->notifier.gsi == irqfd->gsi) {
-                               irqfd->resampler = resampler;
-                               break;
+                               if (likely(resampler->notifier.polarity ==
+                                       irqfd->polarity)) {
+                                       irqfd->resampler = resampler;
+                                       break;
+                               } else {
+                                       ret = -EBUSY;
+                                       
mutex_unlock(&kvm->irqfds.resampler_lock);
+                                       goto fail;
+                               }
                        }
                }
 
@@ -353,6 +363,7 @@ kvm_irqfd_assign(struct kvm *kvm, struct kvm_irqfd *args)
                        resampler->kvm = kvm;
                        INIT_LIST_HEAD(&resampler->list);
                        resampler->notifier.gsi = irqfd->gsi;
+                       resampler->notifier.polarity = irqfd->polarity;
                        resampler->notifier.irq_acked = irqfd_resampler_ack;
                        INIT_LIST_HEAD(&resampler->link);
 
@@ -489,7 +500,8 @@ kvm_irqfd_deassign(struct kvm *kvm, struct kvm_irqfd *args)
 int
 kvm_irqfd(struct kvm *kvm, struct kvm_irqfd *args)
 {
-       if (args->flags & ~(KVM_IRQFD_FLAG_DEASSIGN | KVM_IRQFD_FLAG_RESAMPLE))
+       if (args->flags & ~(KVM_IRQFD_FLAG_DEASSIGN | KVM_IRQFD_FLAG_RESAMPLE
+               | KVM_IRQFD_FLAG_POLARITY))
                return -EINVAL;
 
        if (args->flags & KVM_IRQFD_FLAG_DEASSIGN)
-- 
1.8.1.4




reply via email to

[Prev in Thread] Current Thread [Next in Thread]