public inbox for kvm@vger.kernel.org
 help / color / mirror / Atom feed
From: Jan Kiszka <jan.kiszka@siemens.com>
To: Avi Kivity <avi@redhat.com>, Marcelo Tosatti <mtosatti@redhat.com>
Cc: kvm@vger.kernel.org, "Michael S. Tsirkin" <mst@redhat.com>
Subject: [PATCH v3 9/9] qemu-kvm: hpet: Add MSI support for in-kernel irqchip mode
Date: Tue, 26 Apr 2011 16:01:00 +0200	[thread overview]
Message-ID: <4DB6D01C.6080706@siemens.com> (raw)
In-Reply-To: <3d089633897515a214af032ed633342a7001945f.1303823975.git.jan.kiszka@siemens.com>

Just like PCI devices, the HPET requires special care to route MSI
events to the in-kernel irqchip if enabled.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
 hw/hpet.c |   71 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 70 insertions(+), 1 deletions(-)

v3: Let modifying_bit return bool to avoid unexpected results.

diff --git a/hw/hpet.c b/hw/hpet.c
index 6ce07bc..ed8018d 100644
--- a/hw/hpet.c
+++ b/hw/hpet.c
@@ -31,6 +31,7 @@
 #include "hpet_emul.h"
 #include "sysbus.h"
 #include "mc146818rtc.h"
+#include "kvm.h"
 
 //#define HPET_DEBUG
 #ifdef HPET_DEBUG
@@ -55,6 +56,7 @@ typedef struct HPETTimer {  /* timers */
     uint8_t wrap_flag;      /* timer pop will indicate wrap for one-shot 32-bit
                              * mode. Next pop will be actual timer expiration.
                              */
+    KVMMsiMessage kmm;
 } HPETTimer;
 
 typedef struct HPETState {
@@ -141,11 +143,59 @@ static int deactivating_bit(uint64_t old, uint64_t new, uint64_t mask)
     return ((old & mask) && !(new & mask));
 }
 
+static bool modifying_bit(uint64_t old, uint64_t new, uint64_t mask)
+{
+    return (old ^ new) & mask;
+}
+
 static uint64_t hpet_get_ticks(HPETState *s)
 {
     return ns_to_ticks(qemu_get_clock_ns(vm_clock) + s->hpet_offset);
 }
 
+static void kvm_hpet_msi_update(HPETTimer *t)
+{
+    KVMMsiMessage new_entry;
+    int ret = 0;
+
+    if (!kvm_enabled() || !kvm_irqchip_in_kernel()) {
+        return;
+    }
+
+    if (timer_fsb_route(t)) {
+        new_entry.addr_hi = 0;
+        new_entry.addr_lo = t->fsb >> 32;
+        new_entry.data = t->fsb & 0xffffffff;
+        if (t->kmm.gsi == -1) {
+            kvm_msi_message_add(&new_entry);
+            ret = 1;
+        } else {
+            ret = kvm_msi_message_update(&t->kmm, &new_entry);
+        }
+        if (ret > 0) {
+            t->kmm = new_entry;
+            kvm_commit_irq_routes();
+        }
+    } else if (t->kmm.gsi != -1) {
+        kvm_msi_message_del(&t->kmm);
+        t->kmm.gsi = -1;
+    }
+}
+
+static void kvm_hpet_msi_free(HPETState *s)
+{
+    int i;
+
+    for (i = 0; i < s->num_timers; i++) {
+        HPETTimer *timer = &s->timer[i];
+
+        if (timer->kmm.gsi != -1) {
+            kvm_msi_message_del(&timer->kmm);
+            timer->kmm.gsi = -1;
+        }
+    }
+}
+
 /*
  * calculate diff between comparator value and current ticks
  */
@@ -192,7 +242,11 @@ static void update_irq(struct HPETTimer *timer, int set)
             qemu_irq_lower(s->irqs[route]);
         }
     } else if (timer_fsb_route(timer)) {
-        stl_phys(timer->fsb >> 32, timer->fsb & 0xffffffff);
+        if (kvm_enabled() && kvm_irqchip_in_kernel()) {
+            kvm_set_irq(timer->kmm.gsi, 1, NULL);
+        } else {
+            stl_phys(timer->fsb >> 32, timer->fsb & 0xffffffff);
+        }
     } else if (timer->config & HPET_TN_TYPE_LEVEL) {
         s->isr |= mask;
         qemu_irq_raise(s->irqs[route]);
@@ -214,6 +268,8 @@ static int hpet_pre_load(void *opaque)
 {
     HPETState *s = opaque;
 
+    kvm_hpet_msi_free(s);
+
     /* version 1 only supports 3, later versions will load the actual value */
     s->num_timers = HPET_MIN_TIMERS;
     return 0;
@@ -222,6 +278,7 @@ static int hpet_pre_load(void *opaque)
 static int hpet_post_load(void *opaque, int version_id)
 {
     HPETState *s = opaque;
+    int i;
 
     /* Recalculate the offset between the main counter and guest time */
     s->hpet_offset = ticks_to_ns(s->hpet_counter) - qemu_get_clock_ns(vm_clock);
@@ -241,6 +298,10 @@ static int hpet_post_load(void *opaque, int version_id)
         hpet_pit_disable();
     }
 
+    for (i = 0; i < s->num_timers; i++) {
+        kvm_hpet_msi_update(&s->timer[i]);
+    }
+
     return 0;
 }
 
@@ -485,6 +546,9 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
             } else if (deactivating_bit(old_val, new_val, HPET_TN_ENABLE)) {
                 hpet_del_timer(timer);
             }
+            if (modifying_bit(old_val, new_val, HPET_TN_FSB_ENABLE)) {
+                kvm_hpet_msi_update(timer);
+            }
             break;
         case HPET_TN_CFG + 4: // Interrupt capabilities
             DPRINTF("qemu: invalid HPET_TN_CFG+4 write\n");
@@ -533,9 +597,11 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
                 break;
         case HPET_TN_ROUTE:
             timer->fsb = (timer->fsb & 0xffffffff00000000ULL) | new_val;
+            kvm_hpet_msi_update(timer);
             break;
         case HPET_TN_ROUTE + 4:
             timer->fsb = (new_val << 32) | (timer->fsb & 0xffffffff);
+            kvm_hpet_msi_update(timer);
             break;
         default:
             DPRINTF("qemu: invalid hpet_ram_writel\n");
@@ -667,6 +733,8 @@ static void hpet_reset(DeviceState *d)
     hpet_cfg.hpet[s->hpet_id].event_timer_block_id = (uint32_t)s->capability;
     hpet_cfg.hpet[s->hpet_id].address = sysbus_from_qdev(d)->mmio[0].addr;
     count = 1;
+
+    kvm_hpet_msi_free(s);
 }
 
 static void hpet_handle_rtc_irq(void *opaque, int n, int level)
@@ -711,6 +779,7 @@ static int hpet_init(SysBusDevice *dev)
         timer->qemu_timer = qemu_new_timer_ns(vm_clock, hpet_timer, timer);
         timer->tn = i;
         timer->state = s;
+        timer->kmm.gsi = -1;
     }
 
     /* 64-bit main counter; LegacyReplacementRoute. */
-- 
1.7.1

  parent reply	other threads:[~2011-04-26 14:01 UTC|newest]

Thread overview: 47+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-04-26 13:19 [PATCH v2 0/9] qemu-kvm: Clean up and enhance MSI irqchip support Jan Kiszka
2011-04-26 13:19 ` [PATCH v2 1/9] qemu-kvm: Drop unneeded kvm_irq_routing_entry declaration Jan Kiszka
2011-04-26 13:19 ` [PATCH v2 2/9] qemu-kvm: Rename kvm_msix_message to KVMMsiMessage Jan Kiszka
2011-04-26 13:19 ` [PATCH v2 3/9] qemu-kvm: Refactor MSI core API of KVM Jan Kiszka
2011-04-26 13:19 ` [PATCH v2 4/9] qemu-kvm: Fix and clean up msix vector use/unuse hooks Jan Kiszka
2011-04-26 13:19 ` [PATCH v2 5/9] qemu-kvm: Move gsi bits from kvm_msix_vector_add to kvm_msi_add_message Jan Kiszka
2011-04-26 13:19 ` [PATCH v2 6/9] qemu-kvm: Move entry comparison into kvm_msi_update_message Jan Kiszka
2011-04-26 13:19 ` [PATCH v2 7/9] qemu-kvm: Add in-kernel irqchip support for MSI Jan Kiszka
2011-04-26 13:19 ` [PATCH v2 8/9] qemu-kvm: Refresh MSI settings after vmload Jan Kiszka
2011-04-26 13:19 ` [PATCH v2 9/9] qemu-kvm: hpet: Add MSI support for in-kernel irqchip mode Jan Kiszka
2011-04-26 13:30   ` Michael Tokarev
2011-04-26 13:55     ` Jan Kiszka
2011-04-26 13:56       ` Avi Kivity
2011-04-26 13:58         ` Jan Kiszka
2011-04-26 14:01   ` Jan Kiszka [this message]
2011-04-26 16:06     ` [PATCH v3 " Christoph Hellwig
2011-04-26 17:06       ` Jan Kiszka
2011-04-26 17:09         ` Christoph Hellwig
2011-04-27  7:27 ` [PATCH v2 0/9] qemu-kvm: Clean up and enhance MSI irqchip support Avi Kivity
2011-04-27  9:00   ` Jan Kiszka
2011-04-27  9:04     ` Avi Kivity
2011-04-27  9:06       ` Jan Kiszka
2011-04-27  9:14         ` Avi Kivity
2011-04-27 11:21           ` Jan Kiszka
2011-04-27 12:12             ` Avi Kivity
2011-04-27 13:31               ` Jan Kiszka
2011-04-27 13:39                 ` Avi Kivity
2011-04-27 13:54                   ` Jan Kiszka
2011-04-27 14:01                     ` Avi Kivity
2011-04-27 14:11                       ` Michael S. Tsirkin
2011-04-27 14:02                     ` Michael S. Tsirkin
2011-04-27 14:10                       ` Jan Kiszka
2011-04-27 14:14                         ` Michael S. Tsirkin
2011-04-27 14:21                           ` Jan Kiszka
2011-04-27 13:49                 ` Michael S. Tsirkin
2011-04-27  9:34 ` Avi Kivity
2011-04-27 11:39   ` [PATCH v2 8/9] qemu-kvm: Refresh MSI settings after vmload Jan Kiszka
2011-04-27 12:19     ` Avi Kivity
2011-04-27 14:16     ` Michael S. Tsirkin
2011-04-27 14:28       ` Jan Kiszka
2011-04-27 14:30         ` Michael S. Tsirkin
2011-04-27 14:39           ` Jan Kiszka
2011-04-27 15:09             ` Michael S. Tsirkin
2011-04-27 15:21               ` Jan Kiszka
2011-04-27 16:02                 ` Michael S. Tsirkin
2011-04-27 16:20                   ` Jan Kiszka
2011-04-27 16:26                     ` Michael S. Tsirkin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4DB6D01C.6080706@siemens.com \
    --to=jan.kiszka@siemens.com \
    --cc=avi@redhat.com \
    --cc=kvm@vger.kernel.org \
    --cc=mst@redhat.com \
    --cc=mtosatti@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox