qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v3 uq/master 0/6] kvm: Get coalesced MMIO flushing out of the hot-path
@ 2012-08-23 11:02 Jan Kiszka
  2012-08-23 11:02 ` [Qemu-devel] [PATCH v3 uq/master 1/6] memory: Flush coalesced MMIO on selected region access Jan Kiszka
                   ` (6 more replies)
  0 siblings, 7 replies; 8+ messages in thread
From: Jan Kiszka @ 2012-08-23 11:02 UTC (permalink / raw)
  To: Avi Kivity, Marcelo Tosatti
  Cc: Anthony Liguori, Liu Ping Fan, qemu-devel, kvm

This is just a repost, now targeting uq/master as agreed. No changes
compared to v2 except that "i82378: Remove bogus MMIO coalescing" was
dropped as it is already in QEMU upstream by now.

Original description:

We currently flush the coalesced MMIO buffer on every vmexit to
userspace. KVM only provides a single buffer per VM, so a central lock
is required to read from it. This is a contention point given a large
enough VCPU set. Moreover, we need to hold the BQL while replaying the
queued requests, probably for a long time until there is more fine
grained locking available. Good reasons to overcome the unconditional
flush.

The series achieves this by flushing only on selected memory region
accesses, either generically via the memory access dispatcher or
directly on certain VGA PIO accesses that are not yet fully converted.
Another reason to flush are remappings or other relevant region state
changes.

Jan Kiszka (6):
  memory: Flush coalesced MMIO on selected region access
  memory: Use transaction_begin/commit also for single-step operations
  memory: Fold memory_region_update_topology into
    memory_region_transaction_commit
  memory: Flush coalesced MMIO on mapping and state changes
  VGA: Flush coalesced MMIO on related MMIO/PIO accesses
  kvm: Stop flushing coalesced MMIO on vmexit

 hw/cirrus_vga.c |    7 ++++
 hw/qxl.c        |    1 +
 hw/vga-isa-mm.c |    1 +
 hw/vga.c        |    5 +++
 hw/vmware_vga.c |    1 +
 kvm-all.c       |    2 -
 memory.c        |  104 ++++++++++++++++++++++++++++++++-----------------------
 memory.h        |   26 ++++++++++++++
 8 files changed, 102 insertions(+), 45 deletions(-)

-- 
1.7.3.4

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

* [Qemu-devel] [PATCH v3 uq/master 1/6] memory: Flush coalesced MMIO on selected region access
  2012-08-23 11:02 [Qemu-devel] [PATCH v3 uq/master 0/6] kvm: Get coalesced MMIO flushing out of the hot-path Jan Kiszka
@ 2012-08-23 11:02 ` Jan Kiszka
  2012-08-23 11:02 ` [Qemu-devel] [PATCH v3 uq/master 2/6] memory: Use transaction_begin/commit also for single-step operations Jan Kiszka
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Jan Kiszka @ 2012-08-23 11:02 UTC (permalink / raw)
  To: Avi Kivity, Marcelo Tosatti
  Cc: Anthony Liguori, Liu Ping Fan, qemu-devel, kvm

Instead of flushing pending coalesced MMIO requests on every vmexit,
this provides a mechanism to selectively flush when memory regions
related to the coalesced one are accessed. This first of all includes
the coalesced region itself but can also applied to other regions, e.g.
of the same device, by calling memory_region_set_flush_coalesced.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
 memory.c |   24 ++++++++++++++++++++++++
 memory.h |   26 ++++++++++++++++++++++++++
 2 files changed, 50 insertions(+), 0 deletions(-)

diff --git a/memory.c b/memory.c
index 643871b..835eb86 100644
--- a/memory.c
+++ b/memory.c
@@ -311,6 +311,9 @@ static void memory_region_read_accessor(void *opaque,
     MemoryRegion *mr = opaque;
     uint64_t tmp;
 
+    if (mr->flush_coalesced_mmio) {
+        qemu_flush_coalesced_mmio_buffer();
+    }
     tmp = mr->ops->read(mr->opaque, addr, size);
     *value |= (tmp & mask) << shift;
 }
@@ -325,6 +328,9 @@ static void memory_region_write_accessor(void *opaque,
     MemoryRegion *mr = opaque;
     uint64_t tmp;
 
+    if (mr->flush_coalesced_mmio) {
+        qemu_flush_coalesced_mmio_buffer();
+    }
     tmp = (*value >> shift) & mask;
     mr->ops->write(mr->opaque, addr, tmp, size);
 }
@@ -826,6 +832,7 @@ void memory_region_init(MemoryRegion *mr,
     mr->dirty_log_mask = 0;
     mr->ioeventfd_nb = 0;
     mr->ioeventfds = NULL;
+    mr->flush_coalesced_mmio = false;
 }
 
 static bool memory_region_access_valid(MemoryRegion *mr,
@@ -1176,12 +1183,16 @@ void memory_region_add_coalescing(MemoryRegion *mr,
     cmr->addr = addrrange_make(int128_make64(offset), int128_make64(size));
     QTAILQ_INSERT_TAIL(&mr->coalesced, cmr, link);
     memory_region_update_coalesced_range(mr);
+    memory_region_set_flush_coalesced(mr);
 }
 
 void memory_region_clear_coalescing(MemoryRegion *mr)
 {
     CoalescedMemoryRange *cmr;
 
+    qemu_flush_coalesced_mmio_buffer();
+    mr->flush_coalesced_mmio = false;
+
     while (!QTAILQ_EMPTY(&mr->coalesced)) {
         cmr = QTAILQ_FIRST(&mr->coalesced);
         QTAILQ_REMOVE(&mr->coalesced, cmr, link);
@@ -1190,6 +1201,19 @@ void memory_region_clear_coalescing(MemoryRegion *mr)
     memory_region_update_coalesced_range(mr);
 }
 
+void memory_region_set_flush_coalesced(MemoryRegion *mr)
+{
+    mr->flush_coalesced_mmio = true;
+}
+
+void memory_region_clear_flush_coalesced(MemoryRegion *mr)
+{
+    qemu_flush_coalesced_mmio_buffer();
+    if (QTAILQ_EMPTY(&mr->coalesced)) {
+        mr->flush_coalesced_mmio = false;
+    }
+}
+
 void memory_region_add_eventfd(MemoryRegion *mr,
                                target_phys_addr_t addr,
                                unsigned size,
diff --git a/memory.h b/memory.h
index bd1bbae..e5aa028 100644
--- a/memory.h
+++ b/memory.h
@@ -133,6 +133,7 @@ struct MemoryRegion {
     bool enabled;
     bool rom_device;
     bool warning_printed; /* For reservations */
+    bool flush_coalesced_mmio;
     MemoryRegion *alias;
     target_phys_addr_t alias_offset;
     unsigned priority;
@@ -521,6 +522,31 @@ void memory_region_add_coalescing(MemoryRegion *mr,
 void memory_region_clear_coalescing(MemoryRegion *mr);
 
 /**
+ * memory_region_set_flush_coalesced: Enforce memory coalescing flush before
+ *                                    accesses.
+ *
+ * Ensure that pending coalesced MMIO request are flushed before the memory
+ * region is accessed. This property is automatically enabled for all regions
+ * passed to memory_region_set_coalescing() and memory_region_add_coalescing().
+ *
+ * @mr: the memory region to be updated.
+ */
+void memory_region_set_flush_coalesced(MemoryRegion *mr);
+
+/**
+ * memory_region_clear_flush_coalesced: Disable memory coalescing flush before
+ *                                      accesses.
+ *
+ * Clear the automatic coalesced MMIO flushing enabled via
+ * memory_region_set_flush_coalesced. Note that this service has no effect on
+ * memory regions that have MMIO coalescing enabled for themselves. For them,
+ * automatic flushing will stop once coalescing is disabled.
+ *
+ * @mr: the memory region to be updated.
+ */
+void memory_region_clear_flush_coalesced(MemoryRegion *mr);
+
+/**
  * memory_region_add_eventfd: Request an eventfd to be triggered when a word
  *                            is written to a location.
  *
-- 
1.7.3.4

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

* [Qemu-devel] [PATCH v3 uq/master 2/6] memory: Use transaction_begin/commit also for single-step operations
  2012-08-23 11:02 [Qemu-devel] [PATCH v3 uq/master 0/6] kvm: Get coalesced MMIO flushing out of the hot-path Jan Kiszka
  2012-08-23 11:02 ` [Qemu-devel] [PATCH v3 uq/master 1/6] memory: Flush coalesced MMIO on selected region access Jan Kiszka
@ 2012-08-23 11:02 ` Jan Kiszka
  2012-08-23 11:02 ` [Qemu-devel] [PATCH v3 uq/master 3/6] memory: Fold memory_region_update_topology into memory_region_transaction_commit Jan Kiszka
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Jan Kiszka @ 2012-08-23 11:02 UTC (permalink / raw)
  To: Avi Kivity, Marcelo Tosatti
  Cc: Anthony Liguori, Liu Ping Fan, qemu-devel, kvm

Wrap also simple operations consisting only of a single step with
memory_region_transaction_begin/commit. This allows to perform
additional steps like coalesced MMIO flushing from a single place.

This requires dropping some micro-optimizations: The skipping of
topology updates after updating disabled or unregistered regions.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
 memory.c |   40 +++++++++++++++++++++++++---------------
 1 files changed, 25 insertions(+), 15 deletions(-)

diff --git a/memory.c b/memory.c
index 835eb86..58583cf 100644
--- a/memory.c
+++ b/memory.c
@@ -1076,8 +1076,9 @@ void memory_region_set_log(MemoryRegion *mr, bool log, unsigned client)
 {
     uint8_t mask = 1 << client;
 
+    memory_region_transaction_begin();
     mr->dirty_log_mask = (mr->dirty_log_mask & ~mask) | (log * mask);
-    memory_region_update_topology(mr);
+    memory_region_transaction_commit();
 }
 
 bool memory_region_get_dirty(MemoryRegion *mr, target_phys_addr_t addr,
@@ -1110,16 +1111,18 @@ void memory_region_sync_dirty_bitmap(MemoryRegion *mr)
 void memory_region_set_readonly(MemoryRegion *mr, bool readonly)
 {
     if (mr->readonly != readonly) {
+        memory_region_transaction_begin();
         mr->readonly = readonly;
-        memory_region_update_topology(mr);
+        memory_region_transaction_commit();
     }
 }
 
 void memory_region_rom_device_set_readable(MemoryRegion *mr, bool readable)
 {
     if (mr->readable != readable) {
+        memory_region_transaction_begin();
         mr->readable = readable;
-        memory_region_update_topology(mr);
+        memory_region_transaction_commit();
     }
 }
 
@@ -1230,6 +1233,7 @@ void memory_region_add_eventfd(MemoryRegion *mr,
     };
     unsigned i;
 
+    memory_region_transaction_begin();
     for (i = 0; i < mr->ioeventfd_nb; ++i) {
         if (memory_region_ioeventfd_before(mrfd, mr->ioeventfds[i])) {
             break;
@@ -1241,7 +1245,7 @@ void memory_region_add_eventfd(MemoryRegion *mr,
     memmove(&mr->ioeventfds[i+1], &mr->ioeventfds[i],
             sizeof(*mr->ioeventfds) * (mr->ioeventfd_nb-1 - i));
     mr->ioeventfds[i] = mrfd;
-    memory_region_update_topology(mr);
+    memory_region_transaction_commit();
 }
 
 void memory_region_del_eventfd(MemoryRegion *mr,
@@ -1260,6 +1264,7 @@ void memory_region_del_eventfd(MemoryRegion *mr,
     };
     unsigned i;
 
+    memory_region_transaction_begin();
     for (i = 0; i < mr->ioeventfd_nb; ++i) {
         if (memory_region_ioeventfd_equal(mrfd, mr->ioeventfds[i])) {
             break;
@@ -1271,7 +1276,7 @@ void memory_region_del_eventfd(MemoryRegion *mr,
     --mr->ioeventfd_nb;
     mr->ioeventfds = g_realloc(mr->ioeventfds,
                                   sizeof(*mr->ioeventfds)*mr->ioeventfd_nb + 1);
-    memory_region_update_topology(mr);
+    memory_region_transaction_commit();
 }
 
 static void memory_region_add_subregion_common(MemoryRegion *mr,
@@ -1280,6 +1285,8 @@ static void memory_region_add_subregion_common(MemoryRegion *mr,
 {
     MemoryRegion *other;
 
+    memory_region_transaction_begin();
+
     assert(!subregion->parent);
     subregion->parent = mr;
     subregion->addr = offset;
@@ -1312,7 +1319,7 @@ static void memory_region_add_subregion_common(MemoryRegion *mr,
     }
     QTAILQ_INSERT_TAIL(&mr->subregions, subregion, subregions_link);
 done:
-    memory_region_update_topology(mr);
+    memory_region_transaction_commit();
 }
 
 
@@ -1338,10 +1345,11 @@ void memory_region_add_subregion_overlap(MemoryRegion *mr,
 void memory_region_del_subregion(MemoryRegion *mr,
                                  MemoryRegion *subregion)
 {
+    memory_region_transaction_begin();
     assert(subregion->parent == mr);
     subregion->parent = NULL;
     QTAILQ_REMOVE(&mr->subregions, subregion, subregions_link);
-    memory_region_update_topology(mr);
+    memory_region_transaction_commit();
 }
 
 void memory_region_set_enabled(MemoryRegion *mr, bool enabled)
@@ -1349,8 +1357,9 @@ void memory_region_set_enabled(MemoryRegion *mr, bool enabled)
     if (enabled == mr->enabled) {
         return;
     }
+    memory_region_transaction_begin();
     mr->enabled = enabled;
-    memory_region_update_topology(NULL);
+    memory_region_transaction_commit();
 }
 
 void memory_region_set_address(MemoryRegion *mr, target_phys_addr_t addr)
@@ -1376,16 +1385,15 @@ void memory_region_set_address(MemoryRegion *mr, target_phys_addr_t addr)
 
 void memory_region_set_alias_offset(MemoryRegion *mr, target_phys_addr_t offset)
 {
-    target_phys_addr_t old_offset = mr->alias_offset;
-
     assert(mr->alias);
-    mr->alias_offset = offset;
 
-    if (offset == old_offset || !mr->parent) {
+    if (offset == mr->alias_offset) {
         return;
     }
 
-    memory_region_update_topology(mr);
+    memory_region_transaction_begin();
+    mr->alias_offset = offset;
+    memory_region_transaction_commit();
 }
 
 ram_addr_t memory_region_get_ram_addr(MemoryRegion *mr)
@@ -1517,14 +1525,16 @@ void memory_listener_unregister(MemoryListener *listener)
 
 void set_system_memory_map(MemoryRegion *mr)
 {
+    memory_region_transaction_begin();
     address_space_memory.root = mr;
-    memory_region_update_topology(NULL);
+    memory_region_transaction_commit();
 }
 
 void set_system_io_map(MemoryRegion *mr)
 {
+    memory_region_transaction_begin();
     address_space_io.root = mr;
-    memory_region_update_topology(NULL);
+    memory_region_transaction_commit();
 }
 
 uint64_t io_mem_read(MemoryRegion *mr, target_phys_addr_t addr, unsigned size)
-- 
1.7.3.4

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

* [Qemu-devel] [PATCH v3 uq/master 3/6] memory: Fold memory_region_update_topology into memory_region_transaction_commit
  2012-08-23 11:02 [Qemu-devel] [PATCH v3 uq/master 0/6] kvm: Get coalesced MMIO flushing out of the hot-path Jan Kiszka
  2012-08-23 11:02 ` [Qemu-devel] [PATCH v3 uq/master 1/6] memory: Flush coalesced MMIO on selected region access Jan Kiszka
  2012-08-23 11:02 ` [Qemu-devel] [PATCH v3 uq/master 2/6] memory: Use transaction_begin/commit also for single-step operations Jan Kiszka
@ 2012-08-23 11:02 ` Jan Kiszka
  2012-08-23 11:02 ` [Qemu-devel] [PATCH v3 uq/master 4/6] memory: Flush coalesced MMIO on mapping and state changes Jan Kiszka
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Jan Kiszka @ 2012-08-23 11:02 UTC (permalink / raw)
  To: Avi Kivity, Marcelo Tosatti
  Cc: Anthony Liguori, Liu Ping Fan, qemu-devel, kvm

Simplify the code as we are using now only a subset of the original
features of memory_region_update_topology.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
 memory.c |   39 +++++++++++----------------------------
 1 files changed, 11 insertions(+), 28 deletions(-)

diff --git a/memory.c b/memory.c
index 58583cf..e29c193 100644
--- a/memory.c
+++ b/memory.c
@@ -24,7 +24,6 @@
 #include "exec-obsolete.h"
 
 unsigned memory_region_transaction_depth = 0;
-static bool memory_region_update_pending = false;
 static bool global_dirty_log = false;
 
 static QTAILQ_HEAD(memory_listeners, MemoryListener) memory_listeners
@@ -732,31 +731,6 @@ static void address_space_update_topology(AddressSpace *as)
     address_space_update_ioeventfds(as);
 }
 
-static void memory_region_update_topology(MemoryRegion *mr)
-{
-    if (memory_region_transaction_depth) {
-        memory_region_update_pending |= !mr || mr->enabled;
-        return;
-    }
-
-    if (mr && !mr->enabled) {
-        return;
-    }
-
-    MEMORY_LISTENER_CALL_GLOBAL(begin, Forward);
-
-    if (address_space_memory.root) {
-        address_space_update_topology(&address_space_memory);
-    }
-    if (address_space_io.root) {
-        address_space_update_topology(&address_space_io);
-    }
-
-    MEMORY_LISTENER_CALL_GLOBAL(commit, Forward);
-
-    memory_region_update_pending = false;
-}
-
 void memory_region_transaction_begin(void)
 {
     ++memory_region_transaction_depth;
@@ -766,8 +740,17 @@ void memory_region_transaction_commit(void)
 {
     assert(memory_region_transaction_depth);
     --memory_region_transaction_depth;
-    if (!memory_region_transaction_depth && memory_region_update_pending) {
-        memory_region_update_topology(NULL);
+    if (!memory_region_transaction_depth) {
+        MEMORY_LISTENER_CALL_GLOBAL(begin, Forward);
+
+        if (address_space_memory.root) {
+            address_space_update_topology(&address_space_memory);
+        }
+        if (address_space_io.root) {
+            address_space_update_topology(&address_space_io);
+        }
+
+        MEMORY_LISTENER_CALL_GLOBAL(commit, Forward);
     }
 }
 
-- 
1.7.3.4

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

* [Qemu-devel] [PATCH v3 uq/master 4/6] memory: Flush coalesced MMIO on mapping and state changes
  2012-08-23 11:02 [Qemu-devel] [PATCH v3 uq/master 0/6] kvm: Get coalesced MMIO flushing out of the hot-path Jan Kiszka
                   ` (2 preceding siblings ...)
  2012-08-23 11:02 ` [Qemu-devel] [PATCH v3 uq/master 3/6] memory: Fold memory_region_update_topology into memory_region_transaction_commit Jan Kiszka
@ 2012-08-23 11:02 ` Jan Kiszka
  2012-08-23 11:02 ` [Qemu-devel] [PATCH v3 uq/master 5/6] VGA: Flush coalesced MMIO on related MMIO/PIO accesses Jan Kiszka
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Jan Kiszka @ 2012-08-23 11:02 UTC (permalink / raw)
  To: Avi Kivity, Marcelo Tosatti
  Cc: Anthony Liguori, Liu Ping Fan, qemu-devel, kvm

Flush pending coalesced MMIO before performing mapping or state changes
that could affect the event orderings or route the buffered requests to
a wrong region.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
 memory.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/memory.c b/memory.c
index e29c193..c5bcf45 100644
--- a/memory.c
+++ b/memory.c
@@ -733,6 +733,7 @@ static void address_space_update_topology(AddressSpace *as)
 
 void memory_region_transaction_begin(void)
 {
+    qemu_flush_coalesced_mmio_buffer();
     ++memory_region_transaction_depth;
 }
 
-- 
1.7.3.4

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

* [Qemu-devel] [PATCH v3 uq/master 5/6] VGA: Flush coalesced MMIO on related MMIO/PIO accesses
  2012-08-23 11:02 [Qemu-devel] [PATCH v3 uq/master 0/6] kvm: Get coalesced MMIO flushing out of the hot-path Jan Kiszka
                   ` (3 preceding siblings ...)
  2012-08-23 11:02 ` [Qemu-devel] [PATCH v3 uq/master 4/6] memory: Flush coalesced MMIO on mapping and state changes Jan Kiszka
@ 2012-08-23 11:02 ` Jan Kiszka
  2012-08-23 11:02 ` [Qemu-devel] [PATCH v3 uq/master 6/6] kvm: Stop flushing coalesced MMIO on vmexit Jan Kiszka
  2012-08-23 14:01 ` [Qemu-devel] [PATCH v3 uq/master 0/6] kvm: Get coalesced MMIO flushing out of the hot-path Marcelo Tosatti
  6 siblings, 0 replies; 8+ messages in thread
From: Jan Kiszka @ 2012-08-23 11:02 UTC (permalink / raw)
  To: Avi Kivity, Marcelo Tosatti
  Cc: Anthony Liguori, Liu Ping Fan, qemu-devel, kvm

In preparation of stopping to flush coalesced MMIO unconditionally on
vmexits, mark VGA MMIO and PIO regions as synchronous /wrt coalesced
MMIO and flush the buffer explicitly on PIO accesses that do not use
generic memory regions yet.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
 hw/cirrus_vga.c |    7 +++++++
 hw/qxl.c        |    1 +
 hw/vga-isa-mm.c |    1 +
 hw/vga.c        |    5 +++++
 hw/vmware_vga.c |    1 +
 5 files changed, 15 insertions(+), 0 deletions(-)

diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c
index e8dcc6b..9a0a565 100644
--- a/hw/cirrus_vga.c
+++ b/hw/cirrus_vga.c
@@ -2441,6 +2441,8 @@ static uint32_t cirrus_vga_ioport_read(void *opaque, uint32_t addr)
     VGACommonState *s = &c->vga;
     int val, index;
 
+    qemu_flush_coalesced_mmio_buffer();
+
     if (vga_ioport_invalid(s, addr)) {
 	val = 0xff;
     } else {
@@ -2534,6 +2536,8 @@ static void cirrus_vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
     VGACommonState *s = &c->vga;
     int index;
 
+    qemu_flush_coalesced_mmio_buffer();
+
     /* check port range access depending on color/monochrome mode */
     if (vga_ioport_invalid(s, addr)) {
 	return;
@@ -2854,6 +2858,7 @@ static void cirrus_init_common(CirrusVGAState * s, int device_id, int is_pci,
     /* I/O handler for LFB */
     memory_region_init_io(&s->cirrus_linear_io, &cirrus_linear_io_ops, s,
                           "cirrus-linear-io", VGA_RAM_SIZE);
+    memory_region_set_flush_coalesced(&s->cirrus_linear_io);
 
     /* I/O handler for LFB */
     memory_region_init_io(&s->cirrus_linear_bitblt_io,
@@ -2861,10 +2866,12 @@ static void cirrus_init_common(CirrusVGAState * s, int device_id, int is_pci,
                           s,
                           "cirrus-bitblt-mmio",
                           0x400000);
+    memory_region_set_flush_coalesced(&s->cirrus_linear_bitblt_io);
 
     /* I/O handler for memory-mapped I/O */
     memory_region_init_io(&s->cirrus_mmio_io, &cirrus_mmio_io_ops, s,
                           "cirrus-mmio", CIRRUS_PNPMMIO_SIZE);
+    memory_region_set_flush_coalesced(&s->cirrus_mmio_io);
 
     s->real_vram_size =
         (s->device_id == CIRRUS_ID_CLGD5446) ? 4096 * 1024 : 2048 * 1024;
diff --git a/hw/qxl.c b/hw/qxl.c
index c2dd3b4..05da2df 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -1810,6 +1810,7 @@ static int qxl_init_common(PCIQXLDevice *qxl)
     if (qxl->id == 0) {
         vga_dirty_log_start(&qxl->vga);
     }
+    memory_region_set_flush_coalesced(&qxl->io_bar);
 
 
     pci_register_bar(&qxl->pci, QXL_IO_RANGE_INDEX,
diff --git a/hw/vga-isa-mm.c b/hw/vga-isa-mm.c
index 44ae7d9..306e6ba 100644
--- a/hw/vga-isa-mm.c
+++ b/hw/vga-isa-mm.c
@@ -107,6 +107,7 @@ static void vga_mm_init(ISAVGAMMState *s, target_phys_addr_t vram_base,
     s_ioport_ctrl = g_malloc(sizeof(*s_ioport_ctrl));
     memory_region_init_io(s_ioport_ctrl, &vga_mm_ctrl_ops, s,
                           "vga-mm-ctrl", 0x100000);
+    memory_region_set_flush_coalesced(s_ioport_ctrl);
 
     vga_io_memory = g_malloc(sizeof(*vga_io_memory));
     /* XXX: endianness? */
diff --git a/hw/vga.c b/hw/vga.c
index f82ced8..ffb5a7a 100644
--- a/hw/vga.c
+++ b/hw/vga.c
@@ -360,6 +360,8 @@ uint32_t vga_ioport_read(void *opaque, uint32_t addr)
     VGACommonState *s = opaque;
     int val, index;
 
+    qemu_flush_coalesced_mmio_buffer();
+
     if (vga_ioport_invalid(s, addr)) {
         val = 0xff;
     } else {
@@ -452,6 +454,8 @@ void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
     VGACommonState *s = opaque;
     int index;
 
+    qemu_flush_coalesced_mmio_buffer();
+
     /* check port range access depending on color/monochrome mode */
     if (vga_ioport_invalid(s, addr)) {
         return;
@@ -2337,6 +2341,7 @@ MemoryRegion *vga_init_io(VGACommonState *s,
     vga_mem = g_malloc(sizeof(*vga_mem));
     memory_region_init_io(vga_mem, &vga_mem_ops, s,
                           "vga-lowmem", 0x20000);
+    memory_region_set_flush_coalesced(vga_mem);
 
     return vga_mem;
 }
diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c
index f5e4f44..848ac4e 100644
--- a/hw/vmware_vga.c
+++ b/hw/vmware_vga.c
@@ -1185,6 +1185,7 @@ static int pci_vmsvga_initfn(PCIDevice *dev)
 
     memory_region_init_io(&s->io_bar, &vmsvga_io_ops, &s->chip,
                           "vmsvga-io", 0x10);
+    memory_region_set_flush_coalesced(&s->io_bar);
     pci_register_bar(&s->card, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->io_bar);
 
     vmsvga_init(&s->chip, pci_address_space(dev),
-- 
1.7.3.4

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

* [Qemu-devel] [PATCH v3 uq/master 6/6] kvm: Stop flushing coalesced MMIO on vmexit
  2012-08-23 11:02 [Qemu-devel] [PATCH v3 uq/master 0/6] kvm: Get coalesced MMIO flushing out of the hot-path Jan Kiszka
                   ` (4 preceding siblings ...)
  2012-08-23 11:02 ` [Qemu-devel] [PATCH v3 uq/master 5/6] VGA: Flush coalesced MMIO on related MMIO/PIO accesses Jan Kiszka
@ 2012-08-23 11:02 ` Jan Kiszka
  2012-08-23 14:01 ` [Qemu-devel] [PATCH v3 uq/master 0/6] kvm: Get coalesced MMIO flushing out of the hot-path Marcelo Tosatti
  6 siblings, 0 replies; 8+ messages in thread
From: Jan Kiszka @ 2012-08-23 11:02 UTC (permalink / raw)
  To: Avi Kivity, Marcelo Tosatti
  Cc: Anthony Liguori, Liu Ping Fan, qemu-devel, kvm

The memory subsystem will now take care of flushing whenever affected
regions are accessed or the memory mapping changes.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
 kvm-all.c |    2 --
 1 files changed, 0 insertions(+), 2 deletions(-)

diff --git a/kvm-all.c b/kvm-all.c
index e0244b6..432b84f 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -1541,8 +1541,6 @@ int kvm_cpu_exec(CPUArchState *env)
         qemu_mutex_lock_iothread();
         kvm_arch_post_run(env, run);
 
-        kvm_flush_coalesced_mmio_buffer();
-
         if (run_ret < 0) {
             if (run_ret == -EINTR || run_ret == -EAGAIN) {
                 DPRINTF("io window exit\n");
-- 
1.7.3.4

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

* Re: [Qemu-devel] [PATCH v3 uq/master 0/6] kvm: Get coalesced MMIO flushing out of the hot-path
  2012-08-23 11:02 [Qemu-devel] [PATCH v3 uq/master 0/6] kvm: Get coalesced MMIO flushing out of the hot-path Jan Kiszka
                   ` (5 preceding siblings ...)
  2012-08-23 11:02 ` [Qemu-devel] [PATCH v3 uq/master 6/6] kvm: Stop flushing coalesced MMIO on vmexit Jan Kiszka
@ 2012-08-23 14:01 ` Marcelo Tosatti
  6 siblings, 0 replies; 8+ messages in thread
From: Marcelo Tosatti @ 2012-08-23 14:01 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: Anthony Liguori, Liu Ping Fan, Avi Kivity, kvm, qemu-devel

On Thu, Aug 23, 2012 at 01:02:28PM +0200, Jan Kiszka wrote:
> This is just a repost, now targeting uq/master as agreed. No changes
> compared to v2 except that "i82378: Remove bogus MMIO coalescing" was
> dropped as it is already in QEMU upstream by now.
> 
> Original description:
> 
> We currently flush the coalesced MMIO buffer on every vmexit to
> userspace. KVM only provides a single buffer per VM, so a central lock
> is required to read from it. This is a contention point given a large
> enough VCPU set. Moreover, we need to hold the BQL while replaying the
> queued requests, probably for a long time until there is more fine
> grained locking available. Good reasons to overcome the unconditional
> flush.
> 
> The series achieves this by flushing only on selected memory region
> accesses, either generically via the memory access dispatcher or
> directly on certain VGA PIO accesses that are not yet fully converted.
> Another reason to flush are remappings or other relevant region state
> changes.
> 
> Jan Kiszka (6):
>   memory: Flush coalesced MMIO on selected region access
>   memory: Use transaction_begin/commit also for single-step operations
>   memory: Fold memory_region_update_topology into
>     memory_region_transaction_commit
>   memory: Flush coalesced MMIO on mapping and state changes
>   VGA: Flush coalesced MMIO on related MMIO/PIO accesses
>   kvm: Stop flushing coalesced MMIO on vmexit
> 
>  hw/cirrus_vga.c |    7 ++++
>  hw/qxl.c        |    1 +
>  hw/vga-isa-mm.c |    1 +
>  hw/vga.c        |    5 +++
>  hw/vmware_vga.c |    1 +
>  kvm-all.c       |    2 -
>  memory.c        |  104 ++++++++++++++++++++++++++++++++-----------------------
>  memory.h        |   26 ++++++++++++++
>  8 files changed, 102 insertions(+), 45 deletions(-)
> 
> -- 
> 1.7.3.4

Applied, thanks.

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

end of thread, other threads:[~2012-08-23 14:01 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-08-23 11:02 [Qemu-devel] [PATCH v3 uq/master 0/6] kvm: Get coalesced MMIO flushing out of the hot-path Jan Kiszka
2012-08-23 11:02 ` [Qemu-devel] [PATCH v3 uq/master 1/6] memory: Flush coalesced MMIO on selected region access Jan Kiszka
2012-08-23 11:02 ` [Qemu-devel] [PATCH v3 uq/master 2/6] memory: Use transaction_begin/commit also for single-step operations Jan Kiszka
2012-08-23 11:02 ` [Qemu-devel] [PATCH v3 uq/master 3/6] memory: Fold memory_region_update_topology into memory_region_transaction_commit Jan Kiszka
2012-08-23 11:02 ` [Qemu-devel] [PATCH v3 uq/master 4/6] memory: Flush coalesced MMIO on mapping and state changes Jan Kiszka
2012-08-23 11:02 ` [Qemu-devel] [PATCH v3 uq/master 5/6] VGA: Flush coalesced MMIO on related MMIO/PIO accesses Jan Kiszka
2012-08-23 11:02 ` [Qemu-devel] [PATCH v3 uq/master 6/6] kvm: Stop flushing coalesced MMIO on vmexit Jan Kiszka
2012-08-23 14:01 ` [Qemu-devel] [PATCH v3 uq/master 0/6] kvm: Get coalesced MMIO flushing out of the hot-path Marcelo Tosatti

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).