diff mbox

kvm: Flush coalesced MMIO buffer periodly

Message ID 1264405604-13506-1-git-send-email-sheng@linux.intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

Sheng Yang Jan. 25, 2010, 7:46 a.m. UTC
None
diff mbox

Patch

diff --git a/cpu-all.h b/cpu-all.h
index 8ed76c7..51effc0 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -916,6 +916,8 @@  void qemu_register_coalesced_mmio(target_phys_addr_t addr, ram_addr_t size);
 
 void qemu_unregister_coalesced_mmio(target_phys_addr_t addr, ram_addr_t size);
 
+void qemu_flush_coalesced_mmio_buffer(void);
+
 /*******************************************/
 /* host CPU ticks (if available) */
 
diff --git a/exec.c b/exec.c
index 99e88e1..40c01a1 100644
--- a/exec.c
+++ b/exec.c
@@ -2424,6 +2424,12 @@  void qemu_unregister_coalesced_mmio(target_phys_addr_t addr, ram_addr_t size)
         kvm_uncoalesce_mmio_region(addr, size);
 }
 
+void qemu_flush_coalesced_mmio_buffer(void)
+{
+    if (kvm_enabled())
+        kvm_flush_coalesced_mmio_buffer();
+}
+
 #ifdef __linux__
 
 #include <sys/vfs.h>
diff --git a/kvm-all.c b/kvm-all.c
index 0423fff..3d9fcc0 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -25,6 +25,9 @@ 
 #include "hw/hw.h"
 #include "gdbstub.h"
 #include "kvm.h"
+#ifndef KVM_UPSTREAM
+#include "libkvm.h"
+#endif
 
 #ifdef KVM_UPSTREAM
 /* KVM uses PAGE_SIZE in it's definition of COALESCED_MMIO_MAX */
@@ -385,6 +388,23 @@  int kvm_uncoalesce_mmio_region(target_phys_addr_t start, ram_addr_t size)
     return ret;
 }
 
+void kvm_flush_coalesced_mmio_buffer(void)
+{
+#ifdef KVM_CAP_COALESCED_MMIO
+    if (kvm_state->coalesced_mmio_ring) {
+        struct kvm_coalesced_mmio_ring *ring =
+            kvm_state->coalesced_mmio_ring;
+        while (ring->first != ring->last) {
+            cpu_physical_memory_rw(ring->coalesced_mmio[ring->first].phys_addr,
+                           &ring->coalesced_mmio[ring->first].data[0],
+                           ring->coalesced_mmio[ring->first].len, 1);
+	    smp_wmb();
+            ring->first = (ring->first + 1) % KVM_COALESCED_MMIO_MAX;
+        }
+    }
+#endif
+}
+
 int kvm_check_extension(KVMState *s, unsigned int extension)
 {
     int ret;
diff --git a/qemu-kvm.c b/qemu-kvm.c
index 599c3d6..70d7658 100644
--- a/qemu-kvm.c
+++ b/qemu-kvm.c
@@ -463,6 +463,12 @@  static void kvm_create_vcpu(CPUState *env, int id)
         goto err_fd;
     }
 
+#ifdef KVM_CAP_COALESCED_MMIO
+    if (kvm_state->coalesced_mmio && !kvm_state->coalesced_mmio_ring)
+        kvm_state->coalesced_mmio_ring = (void *) env->kvm_run +
+		kvm_state->coalesced_mmio * PAGE_SIZE;
+#endif
+
     return;
   err_fd:
     close(env->kvm_fd);
@@ -927,8 +933,7 @@  int kvm_run(CPUState *env)
 
 #if defined(KVM_CAP_COALESCED_MMIO)
     if (kvm_state->coalesced_mmio) {
-        struct kvm_coalesced_mmio_ring *ring =
-            (void *) run + kvm_state->coalesced_mmio * PAGE_SIZE;
+        struct kvm_coalesced_mmio_ring *ring = kvm_state->coalesced_mmio_ring;
         while (ring->first != ring->last) {
             cpu_physical_memory_rw(ring->coalesced_mmio[ring->first].phys_addr,
                            &ring->coalesced_mmio[ring->first].data[0],
diff --git a/qemu-kvm.h b/qemu-kvm.h
index 6b3e5a1..066e1c0 100644
--- a/qemu-kvm.h
+++ b/qemu-kvm.h
@@ -435,6 +435,7 @@  int kvm_register_coalesced_mmio(kvm_context_t kvm, uint64_t addr,
                                 uint32_t size);
 int kvm_unregister_coalesced_mmio(kvm_context_t kvm, uint64_t addr,
                                   uint32_t size);
+void kvm_flush_coalesced_mmio_buffer(void);
 
 /*!
  * \brief Create a memory alias
@@ -1144,6 +1145,7 @@  typedef struct KVMState {
     int fd;
     int vmfd;
     int coalesced_mmio;
+    struct kvm_coalesced_mmio_ring *coalesced_mmio_ring;
     int broken_set_mem_region;
     int migration_log;
     int vcpu_events;
diff --git a/vl.c b/vl.c
index 9edea10..f39ad56 100644
--- a/vl.c
+++ b/vl.c
@@ -3227,6 +3227,7 @@  static void gui_update(void *opaque)
     DisplayState *ds = opaque;
     DisplayChangeListener *dcl = ds->listeners;
 
+    qemu_flush_coalesced_mmio_buffer();
     dpy_refresh(ds);
 
     while (dcl != NULL) {
@@ -3242,6 +3243,7 @@  static void nographic_update(void *opaque)
 {
     uint64_t interval = GUI_REFRESH_INTERVAL;
 
+    qemu_flush_coalesced_mmio_buffer();
     qemu_mod_timer(nographic_timer, interval + qemu_get_clock(rt_clock));
 }