qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [PATCH 4/5] hpet: deliver irq by irqfd when in dedicated th


From: Liu Ping Fan
Subject: [Qemu-devel] [PATCH 4/5] hpet: deliver irq by irqfd when in dedicated thread mode
Date: Thu, 12 Sep 2013 13:24:52 +0800

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 <address@hidden>
---
 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




reply via email to

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