[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
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Qemu-devel] [PATCH] KVM: IRQFD: equip irqfd and resamplefd with polarity,
Liu Ping Fan <=