From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:59955) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YYDvB-0002zY-I8 for qemu-devel@nongnu.org; Wed, 18 Mar 2015 09:22:06 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1YYDvA-0003cb-E9 for qemu-devel@nongnu.org; Wed, 18 Mar 2015 09:22:05 -0400 Received: from mail-wg0-x230.google.com ([2a00:1450:400c:c00::230]:34865) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YYDvA-0003cS-3J for qemu-devel@nongnu.org; Wed, 18 Mar 2015 09:22:04 -0400 Received: by wgdm6 with SMTP id m6so35181212wgd.2 for ; Wed, 18 Mar 2015 06:22:03 -0700 (PDT) Sender: Paolo Bonzini From: Paolo Bonzini Date: Wed, 18 Mar 2015 14:21:44 +0100 Message-Id: <1426684909-95030-4-git-send-email-pbonzini@redhat.com> In-Reply-To: <1426684909-95030-1-git-send-email-pbonzini@redhat.com> References: <1426684909-95030-1-git-send-email-pbonzini@redhat.com> Subject: [Qemu-devel] [PATCH 3/8] memory: Provide address_space_rw_unlocked List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: Jan Kiszka From: Jan Kiszka 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 Signed-off-by: Paolo Bonzini --- 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