qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [PATCH 3/8] memory: Provide address_space_rw_unlocked


From: Paolo Bonzini
Subject: [Qemu-devel] [PATCH 3/8] memory: Provide address_space_rw_unlocked
Date: Wed, 18 Mar 2015 14:21:44 +0100

From: Jan Kiszka <address@hidden>

Break up address_space_rw into two version: The standard one continues
to require the caller to hold BQL on invocation, the unlocked one takes
or avoids BQL depending on the locking strategy of the target memory
region and its coalesced MMIO handling.

As memory_region_read/write_accessor may now also run without BQL held,
we need to move coalesced MMIO flushing earlier in the dispatch process.

Signed-off-by: Jan Kiszka <address@hidden>
Signed-off-by: Paolo Bonzini <address@hidden>
---
 exec.c                | 41 +++++++++++++++++++++++++++++++++++++++--
 include/exec/memory.h | 19 +++++++++++++++++++
 memory.c              |  6 ------
 3 files changed, 58 insertions(+), 8 deletions(-)

diff --git a/exec.c b/exec.c
index b264e76..d60abfc 100644
--- a/exec.c
+++ b/exec.c
@@ -48,6 +48,7 @@
 #endif
 #include "exec/cpu-all.h"
 #include "qemu/rcu_queue.h"
+#include "qemu/main-loop.h"
 #include "exec/cputlb.h"
 #include "translate-all.h"
 
@@ -2295,8 +2296,9 @@ static int memory_access_size(MemoryRegion *mr, unsigned 
l, hwaddr addr)
     return l;
 }
 
-bool address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,
-                      int len, bool is_write)
+static bool address_space_rw_internal(AddressSpace *as, hwaddr addr,
+                                      uint8_t *buf, int len, bool is_write,
+                                      bool unlocked)
 {
     hwaddr l;
     uint8_t *ptr;
@@ -2304,12 +2306,29 @@ bool address_space_rw(AddressSpace *as, hwaddr addr, 
uint8_t *buf,
     hwaddr addr1;
     MemoryRegion *mr;
     bool error = false;
+    bool release_lock;
 
     rcu_read_lock();
     while (len > 0) {
         l = len;
         mr = address_space_translate(as, addr, &addr1, &l, is_write);
 
+        release_lock = false;
+        if (unlocked && mr->global_locking) {
+            qemu_mutex_lock_iothread();
+            unlocked = false;
+            release_lock = true;
+        }
+        if (mr->flush_coalesced_mmio) {
+            if (unlocked) {
+                qemu_mutex_lock_iothread();
+            }
+            qemu_flush_coalesced_mmio_buffer();
+            if (unlocked) {
+                qemu_mutex_unlock_iothread();
+            }
+        }
+
         if (is_write) {
             if (!memory_access_is_direct(mr, is_write)) {
                 l = memory_access_size(mr, l, addr1);
@@ -2380,6 +2399,12 @@ bool address_space_rw(AddressSpace *as, hwaddr addr, 
uint8_t *buf,
                 memcpy(buf, ptr, l);
             }
         }
+
+        if (release_lock) {
+            qemu_mutex_unlock_iothread();
+            unlocked = true;
+        }
+
         len -= l;
         buf += l;
         addr += l;
@@ -2389,6 +2414,18 @@ bool address_space_rw(AddressSpace *as, hwaddr addr, 
uint8_t *buf,
     return error;
 }
 
+bool address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,
+                      int len, bool is_write)
+{
+    return address_space_rw_internal(as, addr, buf, len, is_write, false);
+}
+
+bool address_space_rw_unlocked(AddressSpace *as, hwaddr addr, uint8_t *buf,
+                               int len, bool is_write)
+{
+    return address_space_rw_internal(as, addr, buf, len, is_write, true);
+}
+
 bool address_space_write(AddressSpace *as, hwaddr addr,
                          const uint8_t *buf, int len)
 {
diff --git a/include/exec/memory.h b/include/exec/memory.h
index 0644dc6..cf39a40 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -1084,6 +1084,8 @@ void address_space_destroy(AddressSpace *as);
  * Return true if the operation hit any unassigned memory or encountered an
  * IOMMU fault.
  *
+ * NOTE: The iothread lock must be held when calling this function.
+ *
  * @as: #AddressSpace to be accessed
  * @addr: address within that address space
  * @buf: buffer with the data transferred
@@ -1093,6 +1095,23 @@ bool address_space_rw(AddressSpace *as, hwaddr addr, 
uint8_t *buf,
                       int len, bool is_write);
 
 /**
+ * address_space_rw_unlocked: read from or write to an address space outside
+ * of the iothread lock.
+ *
+ * Return true if the operation hit any unassigned memory or encountered an
+ * IOMMU fault.
+ *
+ * NOTE: The iothread lock *must not* be held when calling this function.
+ *
+ * @as: #AddressSpace to be accessed
+ * @addr: address within that address space
+ * @buf: buffer with the data transferred
+ * @is_write: indicates the transfer direction
+ */
+bool address_space_rw_unlocked(AddressSpace *as, hwaddr addr, uint8_t *buf,
+                               int len, bool is_write);
+
+/**
  * address_space_write: write to address space.
  *
  * Return true if the operation hit any unassigned memory or encountered an
diff --git a/memory.c b/memory.c
index cc798e1..838e2f1 100644
--- a/memory.c
+++ b/memory.c
@@ -391,9 +391,6 @@ static void memory_region_read_accessor(MemoryRegion *mr,
 {
     uint64_t tmp;
 
-    if (mr->flush_coalesced_mmio) {
-        qemu_flush_coalesced_mmio_buffer();
-    }
     tmp = mr->ops->read(mr->opaque, addr, size);
     trace_memory_region_ops_read(mr, addr, tmp, size);
     *value |= (tmp & mask) << shift;
@@ -422,9 +419,6 @@ static void memory_region_write_accessor(MemoryRegion *mr,
 {
     uint64_t tmp;
 
-    if (mr->flush_coalesced_mmio) {
-        qemu_flush_coalesced_mmio_buffer();
-    }
     tmp = (*value >> shift) & mask;
     trace_memory_region_ops_write(mr, addr, tmp, size);
     mr->ops->write(mr->opaque, addr, tmp, size);
-- 
2.3.0





reply via email to

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