[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 5/8] memory: split address_space_read and address_sp
From: |
Paolo Bonzini |
Subject: |
[Qemu-devel] [PATCH 5/8] memory: split address_space_read and address_space_write |
Date: |
Wed, 16 Dec 2015 11:59:57 +0100 |
Rather than dispatching on is_write for every iteration, make
address_space_rw call one of the two functions. The amount of
duplicate logic is pretty small, and memory_access_is_direct can
be tweaked so that it inlines better in the callers.
Signed-off-by: Paolo Bonzini <address@hidden>
---
exec.c | 208 ++++++++++++++++++++++++++++++++++++-----------------------------
1 file changed, 116 insertions(+), 92 deletions(-)
diff --git a/exec.c b/exec.c
index 026a9f2..44b04ba 100644
--- a/exec.c
+++ b/exec.c
@@ -395,11 +395,10 @@ address_space_translate_internal(AddressSpaceDispatch *d,
hwaddr addr, hwaddr *x
static inline bool memory_access_is_direct(MemoryRegion *mr, bool is_write)
{
- if (memory_region_is_ram(mr)) {
- return !(is_write && mr->readonly);
- }
- if (memory_region_is_romd(mr)) {
- return !is_write;
+ if (is_write) {
+ return memory_region_is_ram(mr) && !mr->readonly;
+ } else {
+ return memory_region_is_ram(mr) || memory_region_is_romd(mr);
}
return false;
@@ -2496,8 +2495,8 @@ static bool prepare_mmio_access(MemoryRegion *mr)
return release_lock;
}
-MemTxResult address_space_rw(AddressSpace *as, hwaddr addr, MemTxAttrs attrs,
- uint8_t *buf, int len, bool is_write)
+MemTxResult address_space_write(AddressSpace *as, hwaddr addr, MemTxAttrs
attrs,
+ const uint8_t *buf, int len)
{
hwaddr l;
uint8_t *ptr;
@@ -2510,87 +2509,47 @@ MemTxResult address_space_rw(AddressSpace *as, hwaddr
addr, MemTxAttrs attrs,
rcu_read_lock();
while (len > 0) {
l = len;
- mr = address_space_translate(as, addr, &addr1, &l, is_write);
+ mr = address_space_translate(as, addr, &addr1, &l, true);
- if (is_write) {
- if (!memory_access_is_direct(mr, is_write)) {
- release_lock |= prepare_mmio_access(mr);
- l = memory_access_size(mr, l, addr1);
- /* XXX: could force current_cpu to NULL to avoid
- potential bugs */
- switch (l) {
- case 8:
- /* 64 bit write access */
- val = ldq_p(buf);
- result |= memory_region_dispatch_write(mr, addr1, val, 8,
- attrs);
- break;
- case 4:
- /* 32 bit write access */
- val = ldl_p(buf);
- result |= memory_region_dispatch_write(mr, addr1, val, 4,
- attrs);
- break;
- case 2:
- /* 16 bit write access */
- val = lduw_p(buf);
- result |= memory_region_dispatch_write(mr, addr1, val, 2,
- attrs);
- break;
- case 1:
- /* 8 bit write access */
- val = ldub_p(buf);
- result |= memory_region_dispatch_write(mr, addr1, val, 1,
- attrs);
- break;
- default:
- abort();
- }
- } else {
- addr1 += memory_region_get_ram_addr(mr);
- /* RAM case */
- ptr = qemu_get_ram_ptr(addr1);
- memcpy(ptr, buf, l);
- invalidate_and_set_dirty(mr, addr1, l);
+ if (!memory_access_is_direct(mr, true)) {
+ release_lock |= prepare_mmio_access(mr);
+ l = memory_access_size(mr, l, addr1);
+ /* XXX: could force current_cpu to NULL to avoid
+ potential bugs */
+ switch (l) {
+ case 8:
+ /* 64 bit write access */
+ val = ldq_p(buf);
+ result |= memory_region_dispatch_write(mr, addr1, val, 8,
+ attrs);
+ break;
+ case 4:
+ /* 32 bit write access */
+ val = ldl_p(buf);
+ result |= memory_region_dispatch_write(mr, addr1, val, 4,
+ attrs);
+ break;
+ case 2:
+ /* 16 bit write access */
+ val = lduw_p(buf);
+ result |= memory_region_dispatch_write(mr, addr1, val, 2,
+ attrs);
+ break;
+ case 1:
+ /* 8 bit write access */
+ val = ldub_p(buf);
+ result |= memory_region_dispatch_write(mr, addr1, val, 1,
+ attrs);
+ break;
+ default:
+ abort();
}
} else {
- if (!memory_access_is_direct(mr, is_write)) {
- /* I/O case */
- release_lock |= prepare_mmio_access(mr);
- l = memory_access_size(mr, l, addr1);
- switch (l) {
- case 8:
- /* 64 bit read access */
- result |= memory_region_dispatch_read(mr, addr1, &val, 8,
- attrs);
- stq_p(buf, val);
- break;
- case 4:
- /* 32 bit read access */
- result |= memory_region_dispatch_read(mr, addr1, &val, 4,
- attrs);
- stl_p(buf, val);
- break;
- case 2:
- /* 16 bit read access */
- result |= memory_region_dispatch_read(mr, addr1, &val, 2,
- attrs);
- stw_p(buf, val);
- break;
- case 1:
- /* 8 bit read access */
- result |= memory_region_dispatch_read(mr, addr1, &val, 1,
- attrs);
- stb_p(buf, val);
- break;
- default:
- abort();
- }
- } else {
- /* RAM case */
- ptr = qemu_get_ram_ptr(mr->ram_addr + addr1);
- memcpy(buf, ptr, l);
- }
+ addr1 += memory_region_get_ram_addr(mr);
+ /* RAM case */
+ ptr = qemu_get_ram_ptr(addr1);
+ memcpy(ptr, buf, l);
+ invalidate_and_set_dirty(mr, addr1, l);
}
if (release_lock) {
@@ -2607,18 +2566,83 @@ MemTxResult address_space_rw(AddressSpace *as, hwaddr
addr, MemTxAttrs attrs,
return result;
}
-MemTxResult address_space_write(AddressSpace *as, hwaddr addr, MemTxAttrs
attrs,
- const uint8_t *buf, int len)
-{
- return address_space_rw(as, addr, attrs, (uint8_t *)buf, len, true);
-}
-
MemTxResult address_space_read(AddressSpace *as, hwaddr addr, MemTxAttrs attrs,
uint8_t *buf, int len)
{
- return address_space_rw(as, addr, attrs, buf, len, false);
+ hwaddr l;
+ uint8_t *ptr;
+ uint64_t val;
+ hwaddr addr1;
+ MemoryRegion *mr;
+ MemTxResult result = MEMTX_OK;
+ bool release_lock = false;
+
+ rcu_read_lock();
+ while (len > 0) {
+ l = len;
+ mr = address_space_translate(as, addr, &addr1, &l, false);
+
+ if (!memory_access_is_direct(mr, false)) {
+ /* I/O case */
+ release_lock |= prepare_mmio_access(mr);
+ l = memory_access_size(mr, l, addr1);
+ switch (l) {
+ case 8:
+ /* 64 bit read access */
+ result |= memory_region_dispatch_read(mr, addr1, &val, 8,
+ attrs);
+ stq_p(buf, val);
+ break;
+ case 4:
+ /* 32 bit read access */
+ result |= memory_region_dispatch_read(mr, addr1, &val, 4,
+ attrs);
+ stl_p(buf, val);
+ break;
+ case 2:
+ /* 16 bit read access */
+ result |= memory_region_dispatch_read(mr, addr1, &val, 2,
+ attrs);
+ stw_p(buf, val);
+ break;
+ case 1:
+ /* 8 bit read access */
+ result |= memory_region_dispatch_read(mr, addr1, &val, 1,
+ attrs);
+ stb_p(buf, val);
+ break;
+ default:
+ abort();
+ }
+ } else {
+ /* RAM case */
+ ptr = qemu_get_ram_ptr(mr->ram_addr + addr1);
+ memcpy(buf, ptr, l);
+ }
+
+ if (release_lock) {
+ qemu_mutex_unlock_iothread();
+ release_lock = false;
+ }
+
+ len -= l;
+ buf += l;
+ addr += l;
+ }
+ rcu_read_unlock();
+
+ return result;
}
+MemTxResult address_space_rw(AddressSpace *as, hwaddr addr, MemTxAttrs attrs,
+ uint8_t *buf, int len, bool is_write)
+{
+ if (is_write) {
+ return address_space_write(as, addr, attrs, (uint8_t *)buf, len);
+ } else {
+ return address_space_read(as, addr, attrs, (uint8_t *)buf, len);
+ }
+}
void cpu_physical_memory_rw(hwaddr addr, uint8_t *buf,
int len, int is_write)
--
2.5.0
- [Qemu-devel] [PATCH 0/8] Optimize address_space_read/write/map, Paolo Bonzini, 2015/12/16
- [Qemu-devel] [PATCH 3/8] memory: reorder MemoryRegion fields, Paolo Bonzini, 2015/12/16
- [Qemu-devel] [PATCH 5/8] memory: split address_space_read and address_space_write,
Paolo Bonzini <=
- [Qemu-devel] [PATCH 1/8] exec: always call qemu_get_ram_ptr within rcu_read_lock, Paolo Bonzini, 2015/12/16
- [Qemu-devel] [PATCH 4/8] memory: avoid unnecessary object_ref/unref, Paolo Bonzini, 2015/12/16
- [Qemu-devel] [PATCH 2/8] exec: make qemu_ram_ptr_length more similar to qemu_get_ram_ptr, Paolo Bonzini, 2015/12/16
- [Qemu-devel] [PATCH 8/8] memory: try to inline constant-length reads, Paolo Bonzini, 2015/12/16
- [Qemu-devel] [PATCH 6/8] memory: extract first iteration of address_space_read and address_space_write, Paolo Bonzini, 2015/12/16
- [Qemu-devel] [PATCH] memory: try to inline constant-length reads, Paolo Bonzini, 2015/12/16
- [Qemu-devel] [PATCH 7/8] memory: inline a few small accessors, Paolo Bonzini, 2015/12/16