qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [RFC 0/5] run hpet on a dedicated thread
@ 2013-09-12  5:24 Liu Ping Fan
  2013-09-12  5:24 ` [Qemu-devel] [PATCH 1/5] irq: introduce route method in IRQState to get gsi Liu Ping Fan
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: Liu Ping Fan @ 2013-09-12  5:24 UTC (permalink / raw)
  To: qemu-devel; +Cc: Paolo Bonzini, Stefan Hajnoczi, Anthony Liguori, Jan Kiszka

Nowadays, we run hpet on iothread. But there are so many undetermined jobs
on iothread. It will heavily affect the accuracy of hpet's timing.
When running on a dedicated thread, the accuracy of timing is only determined
by scheduler. which is more fixed.

This series depend on the thread-safe patches for timers. 
And it is just for discussion. And code is premature.


Liu Ping Fan (5):
  irq: introduce route method in IRQState to get gsi
  irq: implement route method of ioapic
  irqfd: equip irqfd with polarity
  hpet: deliver irq by irqfd when in dedicated thread mode
  hpet: run on dedicate thread

 hw/core/irq.c             | 39 ++++++++++++++++++++++
 hw/core/qdev.c            |  8 +++++
 hw/i386/kvm/i8259.c       |  8 ++++-
 hw/i386/kvm/ioapic.c      | 21 +++++++++++-
 hw/i386/pc_q35.c          |  4 +--
 hw/misc/vfio.c            |  4 +--
 hw/timer/hpet.c           | 85 ++++++++++++++++++++++++++++++++++++++++++++---
 hw/virtio/virtio-pci.c    |  2 +-
 include/hw/irq.h          |  5 +++
 include/hw/qdev-core.h    |  2 ++
 include/sysemu/kvm.h      |  4 ++-
 kvm-all.c                 | 14 ++++----
 linux-headers/linux/kvm.h |  3 ++
 13 files changed, 180 insertions(+), 19 deletions(-)

-- 
1.8.1.4

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [Qemu-devel] [PATCH 1/5] irq: introduce route method in IRQState to get gsi
  2013-09-12  5:24 [Qemu-devel] [RFC 0/5] run hpet on a dedicated thread Liu Ping Fan
@ 2013-09-12  5:24 ` Liu Ping Fan
  2013-09-12  5:24 ` [Qemu-devel] [PATCH 2/5] irq: implement route method of ioapic Liu Ping Fan
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Liu Ping Fan @ 2013-09-12  5:24 UTC (permalink / raw)
  To: qemu-devel; +Cc: Paolo Bonzini, Stefan Hajnoczi, Anthony Liguori, Jan Kiszka

Since the interrupt pin's connection does not change, so we can decide
the gsi for the pin.  Introducing "route" method in IRQState to do that,
and the implement of "route" requires the guarantee that it can survive
without BQL.

When delivering irq, this will help us to step around the irq system in
qemu, and forward irq directly to kernel where re-entrance is already
allowed.

Signed-off-by: Liu Ping Fan <pingfank@linux.vnet.ibm.com>
---
 hw/core/irq.c    | 39 +++++++++++++++++++++++++++++++++++++++
 include/hw/irq.h |  5 +++++
 2 files changed, 44 insertions(+)

diff --git a/hw/core/irq.c b/hw/core/irq.c
index 2078542..3f88f57 100644
--- a/hw/core/irq.c
+++ b/hw/core/irq.c
@@ -26,6 +26,10 @@
 
 struct IRQState {
     qemu_irq_handler handler;
+    /* the implement requires to guarantee the re-entrance without the
+    * protection of BQL
+    */
+    qemu_irq_route route;
     void *opaque;
     int n;
 };
@@ -38,6 +42,15 @@ void qemu_set_irq(qemu_irq irq, int level)
     irq->handler(irq->opaque, irq->n, level);
 }
 
+/* This func is designed to survive without BQL. */
+int qemu_irq_route_gsi(qemu_irq irq)
+{
+    if (irq->route) {
+        return irq->route(irq->opaque, irq->n);
+    }
+    return -1;
+}
+
 qemu_irq *qemu_extend_irqs(qemu_irq *old, int n_old, qemu_irq_handler handler,
                            void *opaque, int n)
 {
@@ -63,6 +76,32 @@ qemu_irq *qemu_extend_irqs(qemu_irq *old, int n_old, qemu_irq_handler handler,
     return s;
 }
 
+qemu_irq *qemu_extend_irqs_2(qemu_irq *old, int n_old, qemu_irq_handler handler,
+                           qemu_irq_route route, void *opaque, int n)
+{
+    qemu_irq *s;
+    struct IRQState *p;
+    int i;
+
+    if (!old) {
+        n_old = 0;
+    }
+    s = old ? g_renew(qemu_irq, old, n + n_old) : g_new(qemu_irq, n);
+    p = old ? g_renew(struct IRQState, s[0], n + n_old) :
+                g_new(struct IRQState, n);
+    for (i = 0; i < n + n_old; i++) {
+        if (i >= n_old) {
+            p->handler = handler;
+            p->route = route;
+            p->opaque = opaque;
+            p->n = i;
+        }
+        s[i] = p;
+        p++;
+    }
+    return s;
+}
+
 qemu_irq *qemu_allocate_irqs(qemu_irq_handler handler, void *opaque, int n)
 {
     return qemu_extend_irqs(NULL, 0, handler, opaque, n);
diff --git a/include/hw/irq.h b/include/hw/irq.h
index 610e6b7..c10ef25 100644
--- a/include/hw/irq.h
+++ b/include/hw/irq.h
@@ -6,6 +6,7 @@
 typedef struct IRQState *qemu_irq;
 
 typedef void (*qemu_irq_handler)(void *opaque, int n, int level);
+typedef int (*qemu_irq_route)(void *opaque, int n);
 
 void qemu_set_irq(qemu_irq irq, int level);
 
@@ -30,11 +31,15 @@ static inline void qemu_irq_pulse(qemu_irq irq)
  */
 qemu_irq *qemu_allocate_irqs(qemu_irq_handler handler, void *opaque, int n);
 
+int qemu_irq_route_gsi(qemu_irq irq);
+
 /* Extends an Array of IRQs. Old IRQs have their handlers and opaque data
  * preserved. New IRQs are assigned the argument handler and opaque data.
  */
 qemu_irq *qemu_extend_irqs(qemu_irq *old, int n_old, qemu_irq_handler handler,
                                 void *opaque, int n);
+qemu_irq *qemu_extend_irqs_2(qemu_irq *old, int n_old, qemu_irq_handler handler,
+                           qemu_irq_route route, void *opaque, int n);
 
 void qemu_free_irqs(qemu_irq *s);
 
-- 
1.8.1.4

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [Qemu-devel] [PATCH 2/5] irq: implement route method of ioapic
  2013-09-12  5:24 [Qemu-devel] [RFC 0/5] run hpet on a dedicated thread Liu Ping Fan
  2013-09-12  5:24 ` [Qemu-devel] [PATCH 1/5] irq: introduce route method in IRQState to get gsi Liu Ping Fan
@ 2013-09-12  5:24 ` Liu Ping Fan
  2013-09-12  5:24 ` [Qemu-devel] [PATCH 3/5] irqfd: equip irqfd with polarity Liu Ping Fan
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Liu Ping Fan @ 2013-09-12  5:24 UTC (permalink / raw)
  To: qemu-devel; +Cc: Paolo Bonzini, Stefan Hajnoczi, Anthony Liguori, Jan Kiszka

Implement the routing of PC's interrupt gpio to intc, and
retrieve the gsi.

Signed-off-by: Liu Ping Fan <pingfank@linux.vnet.ibm.com>
---
 hw/core/qdev.c         |  8 ++++++++
 hw/i386/kvm/i8259.c    |  8 +++++++-
 hw/i386/kvm/ioapic.c   | 21 ++++++++++++++++++++-
 hw/i386/pc_q35.c       |  4 ++--
 include/hw/qdev-core.h |  2 ++
 include/sysemu/kvm.h   |  1 +
 6 files changed, 40 insertions(+), 4 deletions(-)

diff --git a/hw/core/qdev.c b/hw/core/qdev.c
index 758de9f..63605d1 100644
--- a/hw/core/qdev.c
+++ b/hw/core/qdev.c
@@ -312,6 +312,14 @@ void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
     dev->num_gpio_in += n;
 }
 
+void qdev_init_gpio_in_2(DeviceState *dev, qemu_irq_handler handler,
+        qemu_irq_route route, int n)
+{
+    dev->gpio_in = qemu_extend_irqs_2(dev->gpio_in, dev->num_gpio_in, handler,
+                                        route, dev, n);
+    dev->num_gpio_in += n;
+}
+
 void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n)
 {
     assert(dev->num_gpio_out == 0);
diff --git a/hw/i386/kvm/i8259.c b/hw/i386/kvm/i8259.c
index 53e3ca8..1193b54 100644
--- a/hw/i386/kvm/i8259.c
+++ b/hw/i386/kvm/i8259.c
@@ -106,6 +106,11 @@ static void kvm_pic_reset(DeviceState *dev)
     kvm_pic_put(s);
 }
 
+static int kvm_pic_route_gsi(void *opaque, int irq)
+{
+    return irq;
+}
+
 static void kvm_pic_set_irq(void *opaque, int irq, int level)
 {
     int delivered;
@@ -130,7 +135,8 @@ qemu_irq *kvm_i8259_init(ISABus *bus)
     i8259_init_chip(TYPE_KVM_I8259, bus, true);
     i8259_init_chip(TYPE_KVM_I8259, bus, false);
 
-    return qemu_allocate_irqs(kvm_pic_set_irq, NULL, ISA_NUM_IRQS);
+    return qemu_extend_irqs_2(NULL, 0, kvm_pic_set_irq, kvm_pic_route_gsi,
+                NULL, ISA_NUM_IRQS);
 }
 
 static void kvm_i8259_class_init(ObjectClass *klass, void *data)
diff --git a/hw/i386/kvm/ioapic.c b/hw/i386/kvm/ioapic.c
index f11a540..1e6ff0b 100644
--- a/hw/i386/kvm/ioapic.c
+++ b/hw/i386/kvm/ioapic.c
@@ -44,6 +44,19 @@ void kvm_pc_setup_irq_routing(bool pci_enabled)
     }
 }
 
+int kvm_pc_route_gsi(void *opaque, int n)
+{
+    GSIState *s = opaque;
+    int gsi;
+
+    if (n < ISA_NUM_IRQS) {
+        gsi = qemu_irq_route_gsi(s->i8259_irq[n]);
+    } else {
+        gsi = qemu_irq_route_gsi(s->ioapic_irq[n]);
+    }
+    return gsi;
+}
+
 void kvm_pc_gsi_handler(void *opaque, int n, int level)
 {
     GSIState *s = opaque;
@@ -127,11 +140,17 @@ static void kvm_ioapic_set_irq(void *opaque, int irq, int level)
     apic_report_irq_delivered(delivered);
 }
 
+static int kvm_ioapic_route_irq(void *opaque, int irq)
+{
+    return irq;
+}
+
 static void kvm_ioapic_init(IOAPICCommonState *s, int instance_no)
 {
     memory_region_init_reservation(&s->io_memory, NULL, "kvm-ioapic", 0x1000);
 
-    qdev_init_gpio_in(DEVICE(s), kvm_ioapic_set_irq, IOAPIC_NUM_PINS);
+    qdev_init_gpio_in_2(DEVICE(s), kvm_ioapic_set_irq, kvm_ioapic_route_irq,
+        IOAPIC_NUM_PINS);
 }
 
 static Property kvm_ioapic_properties[] = {
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index 198c785..df1deb3 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -120,8 +120,8 @@ static void pc_q35_init(QEMUMachineInitArgs *args)
     gsi_state = g_malloc0(sizeof(*gsi_state));
     if (kvm_irqchip_in_kernel()) {
         kvm_pc_setup_irq_routing(pci_enabled);
-        gsi = qemu_allocate_irqs(kvm_pc_gsi_handler, gsi_state,
-                                 GSI_NUM_PINS);
+        gsi = qemu_extend_irqs_2(NULL, 0, kvm_pc_gsi_handler,
+                                kvm_pc_route_gsi, gsi_state, GSI_NUM_PINS);
     } else {
         gsi = qemu_allocate_irqs(gsi_handler, gsi_state, GSI_NUM_PINS);
     }
diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
index 46972f4..4b8eb35 100644
--- a/include/hw/qdev-core.h
+++ b/include/hw/qdev-core.h
@@ -252,6 +252,8 @@ BusState *qdev_get_child_bus(DeviceState *dev, const char *name);
 /* Register device properties.  */
 /* GPIO inputs also double as IRQ sinks.  */
 void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n);
+void qdev_init_gpio_in_2(DeviceState *dev, qemu_irq_handler handler,
+        qemu_irq_route route, int n);
 void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n);
 
 BusState *qdev_get_parent_bus(DeviceState *dev);
diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
index 8e76685..47cc012 100644
--- a/include/sysemu/kvm.h
+++ b/include/sysemu/kvm.h
@@ -312,6 +312,7 @@ void kvm_irqchip_release_virq(KVMState *s, int virq);
 int kvm_irqchip_add_irqfd_notifier(KVMState *s, EventNotifier *n,
                                    EventNotifier *rn, int virq);
 int kvm_irqchip_remove_irqfd_notifier(KVMState *s, EventNotifier *n, int virq);
+int kvm_pc_route_gsi(void *opaque, int n);
 void kvm_pc_gsi_handler(void *opaque, int n, int level);
 void kvm_pc_setup_irq_routing(bool pci_enabled);
 void kvm_init_irq_routing(KVMState *s);
-- 
1.8.1.4

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [Qemu-devel] [PATCH 3/5] irqfd: equip irqfd with polarity
  2013-09-12  5:24 [Qemu-devel] [RFC 0/5] run hpet on a dedicated thread Liu Ping Fan
  2013-09-12  5:24 ` [Qemu-devel] [PATCH 1/5] irq: introduce route method in IRQState to get gsi Liu Ping Fan
  2013-09-12  5:24 ` [Qemu-devel] [PATCH 2/5] irq: implement route method of ioapic Liu Ping Fan
@ 2013-09-12  5:24 ` Liu Ping Fan
  2013-09-12  5:24 ` [Qemu-devel] [PATCH 4/5] hpet: deliver irq by irqfd when in dedicated thread mode Liu Ping Fan
  2013-09-12  5:24 ` [Qemu-devel] [PATCH 5/5] hpet: run on dedicate thread Liu Ping Fan
  4 siblings, 0 replies; 6+ messages in thread
From: Liu Ping Fan @ 2013-09-12  5:24 UTC (permalink / raw)
  To: qemu-devel; +Cc: Paolo Bonzini, Stefan Hajnoczi, Anthony Liguori, Jan Kiszka

Equip irqfd with polarity, so it can emulate the low-active interrupt.
We take one extra bit in flags to pass this info to kernel and keep
the default value "zero" as high-active.

Signed-off-by: Liu Ping Fan <pingfank@linux.vnet.ibm.com>
---
The kernel will extend this interface correspondingly

---
 hw/misc/vfio.c            |  4 ++--
 hw/virtio/virtio-pci.c    |  2 +-
 include/sysemu/kvm.h      |  3 ++-
 kvm-all.c                 | 14 ++++++++------
 linux-headers/linux/kvm.h |  3 +++
 5 files changed, 16 insertions(+), 10 deletions(-)

diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c
index a1c08fb..f1fb761 100644
--- a/hw/misc/vfio.c
+++ b/hw/misc/vfio.c
@@ -646,7 +646,7 @@ static int vfio_msix_vector_do_use(PCIDevice *pdev, unsigned int nr,
     vector->virq = msg ? kvm_irqchip_add_msi_route(kvm_state, *msg) : -1;
     if (vector->virq < 0 ||
         kvm_irqchip_add_irqfd_notifier(kvm_state, &vector->interrupt,
-                                       NULL, vector->virq) < 0) {
+                                       NULL, vector->virq, 0) < 0) {
         if (vector->virq >= 0) {
             kvm_irqchip_release_virq(kvm_state, vector->virq);
             vector->virq = -1;
@@ -814,7 +814,7 @@ retry:
         vector->virq = kvm_irqchip_add_msi_route(kvm_state, msg);
         if (vector->virq < 0 ||
             kvm_irqchip_add_irqfd_notifier(kvm_state, &vector->interrupt,
-                                           NULL, vector->virq) < 0) {
+                                           NULL, vector->virq, 0) < 0) {
             qemu_set_fd_handler(event_notifier_get_fd(&vector->interrupt),
                                 vfio_msi_interrupt, NULL, vector);
         }
diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
index f2c489b..a8dbb4f 100644
--- a/hw/virtio/virtio-pci.c
+++ b/hw/virtio/virtio-pci.c
@@ -508,7 +508,7 @@ static int kvm_virtio_pci_irqfd_use(VirtIOPCIProxy *proxy,
     VirtQueue *vq = virtio_get_queue(proxy->vdev, queue_no);
     EventNotifier *n = virtio_queue_get_guest_notifier(vq);
     int ret;
-    ret = kvm_irqchip_add_irqfd_notifier(kvm_state, n, NULL, irqfd->virq);
+    ret = kvm_irqchip_add_irqfd_notifier(kvm_state, n, NULL, irqfd->virq, 0);
     return ret;
 }
 
diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
index 47cc012..a990db7 100644
--- a/include/sysemu/kvm.h
+++ b/include/sysemu/kvm.h
@@ -309,8 +309,9 @@ int kvm_irqchip_add_msi_route(KVMState *s, MSIMessage msg);
 int kvm_irqchip_update_msi_route(KVMState *s, int virq, MSIMessage msg);
 void kvm_irqchip_release_virq(KVMState *s, int virq);
 
+/* polarity: 0 high-active */
 int kvm_irqchip_add_irqfd_notifier(KVMState *s, EventNotifier *n,
-                                   EventNotifier *rn, int virq);
+                                   EventNotifier *rn, int virq, int polarity);
 int kvm_irqchip_remove_irqfd_notifier(KVMState *s, EventNotifier *n, int virq);
 int kvm_pc_route_gsi(void *opaque, int n);
 void kvm_pc_gsi_handler(void *opaque, int n, int level);
diff --git a/kvm-all.c b/kvm-all.c
index 875e32e..d0e457b 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -1231,12 +1231,13 @@ int kvm_irqchip_update_msi_route(KVMState *s, int virq, MSIMessage msg)
 }
 
 static int kvm_irqchip_assign_irqfd(KVMState *s, int fd, int rfd, int virq,
-                                    bool assign)
+                                    bool assign, int polarity)
 {
     struct kvm_irqfd irqfd = {
         .fd = fd,
         .gsi = virq,
-        .flags = assign ? 0 : KVM_IRQFD_FLAG_DEASSIGN,
+        .flags = (assign ? 0 : KVM_IRQFD_FLAG_DEASSIGN)
+            | (polarity ? 0 : KVM_IRQFD_FLAG_POLARITY),
     };
 
     if (rfd != -1) {
@@ -1271,7 +1272,8 @@ int kvm_irqchip_add_msi_route(KVMState *s, MSIMessage msg)
     return -ENOSYS;
 }
 
-static int kvm_irqchip_assign_irqfd(KVMState *s, int fd, int virq, bool assign)
+static int kvm_irqchip_assign_irqfd(KVMState *s, int fd, int virq, bool assign,
+    int polarity)
 {
     abort();
 }
@@ -1283,16 +1285,16 @@ int kvm_irqchip_update_msi_route(KVMState *s, int virq, MSIMessage msg)
 #endif /* !KVM_CAP_IRQ_ROUTING */
 
 int kvm_irqchip_add_irqfd_notifier(KVMState *s, EventNotifier *n,
-                                   EventNotifier *rn, int virq)
+                                   EventNotifier *rn, int virq, int polarity)
 {
     return kvm_irqchip_assign_irqfd(s, event_notifier_get_fd(n),
-           rn ? event_notifier_get_fd(rn) : -1, virq, true);
+           rn ? event_notifier_get_fd(rn) : -1, virq, true, polarity);
 }
 
 int kvm_irqchip_remove_irqfd_notifier(KVMState *s, EventNotifier *n, int virq)
 {
     return kvm_irqchip_assign_irqfd(s, event_notifier_get_fd(n), -1, virq,
-           false);
+           false, 0);
 }
 
 static int kvm_irqchip_create(KVMState *s)
diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h
index c614070..64afc8a 100644
--- a/linux-headers/linux/kvm.h
+++ b/linux-headers/linux/kvm.h
@@ -740,6 +740,9 @@ struct kvm_xen_hvm_config {
  */
 #define KVM_IRQFD_FLAG_RESAMPLE (1 << 1)
 
+/* 0: high-active */
+#define KVM_IRQFD_FLAG_POLARITY (1<<2)
+
 struct kvm_irqfd {
 	__u32 fd;
 	__u32 gsi;
-- 
1.8.1.4

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [Qemu-devel] [PATCH 4/5] hpet: deliver irq by irqfd when in dedicated thread mode
  2013-09-12  5:24 [Qemu-devel] [RFC 0/5] run hpet on a dedicated thread Liu Ping Fan
                   ` (2 preceding siblings ...)
  2013-09-12  5:24 ` [Qemu-devel] [PATCH 3/5] irqfd: equip irqfd with polarity Liu Ping Fan
@ 2013-09-12  5:24 ` Liu Ping Fan
  2013-09-12  5:24 ` [Qemu-devel] [PATCH 5/5] hpet: run on dedicate thread Liu Ping Fan
  4 siblings, 0 replies; 6+ messages in thread
From: Liu Ping Fan @ 2013-09-12  5:24 UTC (permalink / raw)
  To: qemu-devel; +Cc: Paolo Bonzini, Stefan Hajnoczi, Anthony Liguori, Jan Kiszka

Running hpet in iothread, there could be variable payload, which
will finally affect the accurate of timing. So we want to run
hpet on dedicated thread.

For hpet, almost of the things can run out of BQL, except interrupt.
We step around interrupt by using irqfd.

Signed-off-by: Liu Ping Fan <pingfank@linux.vnet.ibm.com>
---
 hw/timer/hpet.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 50 insertions(+), 4 deletions(-)

diff --git a/hw/timer/hpet.c b/hw/timer/hpet.c
index ff43850..ae54b87 100644
--- a/hw/timer/hpet.c
+++ b/hw/timer/hpet.c
@@ -33,6 +33,7 @@
 #include "hw/sysbus.h"
 #include "hw/timer/mc146818rtc.h"
 #include "hw/timer/i8254.h"
+#include "sysemu/kvm.h"
 
 //#define HPET_DEBUG
 #ifdef HPET_DEBUG
@@ -68,6 +69,12 @@ typedef struct HPETTimer {  /* timers */
                              */
 } HPETTimer;
 
+typedef struct IrqfdInfo {
+    EventNotifier *n;
+    EventNotifier *rn;
+    int gsi;
+} IrqfdInfo;
+
 typedef struct HPETState {
     /*< private >*/
     SysBusDevice parent_obj;
@@ -76,12 +83,14 @@ typedef struct HPETState {
     MemoryRegion iomem;
     uint64_t hpet_offset;
     qemu_irq irqs[HPET_NUM_IRQ_ROUTES];
+    IrqfdInfo irqfds[HPET_NUM_IRQ_ROUTES];
     uint32_t flags;
     uint8_t rtc_irq_level;
     qemu_irq pit_enabled;
     uint8_t num_timers;
     uint32_t intcap;
     HPETTimer timer[HPET_MAX_TIMERS];
+    bool dedicate_mode;
 
     /* Memory-mapped, software visible registers */
     uint64_t capability;        /* capabilities */
@@ -206,14 +215,19 @@ static void update_irq(struct HPETTimer *timer, int set)
     if (!set || !timer_enabled(timer) || !hpet_enabled(timer->state)) {
         s->isr &= ~mask;
         if (!timer_fsb_route(timer)) {
-            /* fold the ICH PIRQ# pin's internal inversion logic into hpet */
-            if (route >= ISA_NUM_IRQS) {
-                qemu_irq_raise(s->irqs[route]);
+            if (s->dedicate_mode && s->irqfds[timer->tn].n) {
+                    event_notifier_set(s->irqfds[timer->tn].n);
             } else {
-                qemu_irq_lower(s->irqs[route]);
+                /* fold the ICH PIRQ# pin's internal inversion logic into hpet */
+                if (route >= ISA_NUM_IRQS) {
+                    qemu_irq_raise(s->irqs[route]);
+                } else {
+                    qemu_irq_lower(s->irqs[route]);
+                }
             }
         }
     } else if (timer_fsb_route(timer)) {
+        /* For the case of fsb, we resort to the lock in mem dispatcher */
         stl_le_phys(timer->fsb >> 32, timer->fsb & 0xffffffff);
     } else if (timer->config & HPET_TN_TYPE_LEVEL) {
         s->isr |= mask;
@@ -479,6 +493,32 @@ static uint64_t hpet_ram_read(void *opaque, hwaddr addr,
     return 0;
 }
 
+static void timer_assign_irqfd(HPETState *s, HPETTimer *timer, bool assign)
+{
+    int irqnum = (timer->config & HPET_TN_INT_ROUTE_MASK)
+                    >> HPET_TN_INT_ROUTE_SHIFT;
+    int level = timer->fsb & HPET_TN_TYPE_LEVEL;
+    IrqfdInfo *info = &s->irqfds[timer->tn];
+
+    if (assign) {
+        if (!info->n) {
+            info->n = g_new0(EventNotifier, 1);
+            info->rn = g_new0(EventNotifier, 1);
+            event_notifier_init(info->n, 0);
+            event_notifier_init(info->rn, 0);
+        }
+        info->gsi = qemu_irq_route_gsi(s->irqs[irqnum]);
+        kvm_irqchip_add_irqfd_notifier(kvm_state, info->n,
+                        level ? info->rn : NULL, info->gsi, 1);
+    } else {
+        kvm_irqchip_remove_irqfd_notifier(kvm_state, info->n, info->gsi);
+        g_free(info->n);
+        g_free(info->rn);
+        info->n = NULL;
+        info->rn = NULL;
+    }
+}
+
 static void hpet_ram_write(void *opaque, hwaddr addr,
                            uint64_t value, unsigned size)
 {
@@ -514,8 +554,14 @@ static void hpet_ram_write(void *opaque, hwaddr addr,
                 timer->period = (uint32_t)timer->period;
             }
             if (activating_bit(old_val, new_val, HPET_TN_ENABLE)) {
+                if (s->dedicate_mode) {
+                    timer_assign_irqfd(s, timer, true);
+                }
                 hpet_set_timer(timer);
             } else if (deactivating_bit(old_val, new_val, HPET_TN_ENABLE)) {
+                if (s->dedicate_mode) {
+                    timer_assign_irqfd(s, timer, false);
+                }
                 hpet_del_timer(timer);
             }
             break;
-- 
1.8.1.4

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [Qemu-devel] [PATCH 5/5] hpet: run on dedicate thread
  2013-09-12  5:24 [Qemu-devel] [RFC 0/5] run hpet on a dedicated thread Liu Ping Fan
                   ` (3 preceding siblings ...)
  2013-09-12  5:24 ` [Qemu-devel] [PATCH 4/5] hpet: deliver irq by irqfd when in dedicated thread mode Liu Ping Fan
@ 2013-09-12  5:24 ` Liu Ping Fan
  4 siblings, 0 replies; 6+ messages in thread
From: Liu Ping Fan @ 2013-09-12  5:24 UTC (permalink / raw)
  To: qemu-devel; +Cc: Paolo Bonzini, Stefan Hajnoczi, Anthony Liguori, Jan Kiszka

migration is not supported yet.

Signed-off-by: Liu Ping Fan <pingfank@linux.vnet.ibm.com>
---
 hw/timer/hpet.c | 31 ++++++++++++++++++++++++++++++-
 1 file changed, 30 insertions(+), 1 deletion(-)

diff --git a/hw/timer/hpet.c b/hw/timer/hpet.c
index ae54b87..8e32e36 100644
--- a/hw/timer/hpet.c
+++ b/hw/timer/hpet.c
@@ -91,6 +91,10 @@ typedef struct HPETState {
     uint32_t intcap;
     HPETTimer timer[HPET_MAX_TIMERS];
     bool dedicate_mode;
+    AioContext *ctx;
+    bool created;
+    bool stop;
+    QemuThread t;
 
     /* Memory-mapped, software visible registers */
     uint64_t capability;        /* capabilities */
@@ -702,6 +706,16 @@ static const MemoryRegionOps hpet_ram_ops = {
     .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
+static void *hpet_work_thread(void *opaque)
+{
+    HPETState *hpet = opaque;
+
+    while (!hpet->stop) {
+        aio_poll(hpet->ctx, true);
+    }
+    return NULL;
+}
+
 static void hpet_reset(DeviceState *d)
 {
     HPETState *s = HPET(d);
@@ -732,6 +746,11 @@ static void hpet_reset(DeviceState *d)
 
     /* to document that the RTC lowers its output on reset as well */
     s->rtc_irq_level = 0;
+    if (!s->created) {
+        s->created = true;
+        qemu_thread_create(&s->t, hpet_work_thread, s, QEMU_THREAD_JOINABLE);
+    }
+
 }
 
 static void hpet_handle_legacy_irq(void *opaque, int n, int level)
@@ -788,10 +807,20 @@ static void hpet_realize(DeviceState *dev, Error **errp)
     } else if (s->num_timers > HPET_MAX_TIMERS) {
         s->num_timers = HPET_MAX_TIMERS;
     }
+    s->dedicate_mode = kvm_irqfds_enabled() ? true : false;
+    if (s->dedicate_mode) {
+        s->ctx = aio_context_new();
+    }
     for (i = 0; i < HPET_MAX_TIMERS; i++) {
         timer = &s->timer[i];
-        timer->qemu_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, hpet_timer, timer);
         timer->tn = i;
+        if (s->dedicate_mode) {
+            timer->qemu_timer = aio_timer_new(s->ctx, QEMU_CLOCK_VIRTUAL,
+                        SCALE_NS, hpet_timer, timer);
+        } else {
+            timer->qemu_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
+                        hpet_timer, timer);
+        }
         timer->state = s;
     }
 
-- 
1.8.1.4

^ permalink raw reply related	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2013-09-12  5:26 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-09-12  5:24 [Qemu-devel] [RFC 0/5] run hpet on a dedicated thread Liu Ping Fan
2013-09-12  5:24 ` [Qemu-devel] [PATCH 1/5] irq: introduce route method in IRQState to get gsi Liu Ping Fan
2013-09-12  5:24 ` [Qemu-devel] [PATCH 2/5] irq: implement route method of ioapic Liu Ping Fan
2013-09-12  5:24 ` [Qemu-devel] [PATCH 3/5] irqfd: equip irqfd with polarity Liu Ping Fan
2013-09-12  5:24 ` [Qemu-devel] [PATCH 4/5] hpet: deliver irq by irqfd when in dedicated thread mode Liu Ping Fan
2013-09-12  5:24 ` [Qemu-devel] [PATCH 5/5] hpet: run on dedicate thread Liu Ping Fan

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).