aboutsummaryrefslogtreecommitdiff
path: root/exec.c
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2015-12-09 10:06:31 +0100
committerPaolo Bonzini <pbonzini@redhat.com>2015-12-17 17:33:48 +0100
commiteb7eeb88628074207dd611472e712af775985e73 (patch)
tree9c7716bae80dc9d3eb21a6798b338fe9d2d162a8 /exec.c
parent612263cf33062f7441a5d0e3b37c65991fdc3210 (diff)
memory: split address_space_read and address_space_write
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 <pbonzini@redhat.com>
Diffstat (limited to 'exec.c')
-rw-r--r--exec.c208
1 files changed, 116 insertions, 92 deletions
diff --git a/exec.c b/exec.c
index 069848b26a..44e6e38f9f 100644
--- a/exec.c
+++ b/exec.c
@@ -392,11 +392,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;
@@ -2469,8 +2468,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;
@@ -2483,87 +2482,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) {
@@ -2580,18 +2539,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)