提交 eb7eeb88 编写于 作者: P Paolo Bonzini

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: NPaolo Bonzini <pbonzini@redhat.com>
上级 612263cf
...@@ -392,11 +392,10 @@ address_space_translate_internal(AddressSpaceDispatch *d, hwaddr addr, hwaddr *x ...@@ -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) static inline bool memory_access_is_direct(MemoryRegion *mr, bool is_write)
{ {
if (memory_region_is_ram(mr)) { if (is_write) {
return !(is_write && mr->readonly); return memory_region_is_ram(mr) && !mr->readonly;
} } else {
if (memory_region_is_romd(mr)) { return memory_region_is_ram(mr) || memory_region_is_romd(mr);
return !is_write;
} }
return false; return false;
...@@ -2469,8 +2468,8 @@ static bool prepare_mmio_access(MemoryRegion *mr) ...@@ -2469,8 +2468,8 @@ static bool prepare_mmio_access(MemoryRegion *mr)
return release_lock; return release_lock;
} }
MemTxResult address_space_rw(AddressSpace *as, hwaddr addr, MemTxAttrs attrs, MemTxResult address_space_write(AddressSpace *as, hwaddr addr, MemTxAttrs attrs,
uint8_t *buf, int len, bool is_write) const uint8_t *buf, int len)
{ {
hwaddr l; hwaddr l;
uint8_t *ptr; uint8_t *ptr;
...@@ -2483,10 +2482,9 @@ MemTxResult address_space_rw(AddressSpace *as, hwaddr addr, MemTxAttrs attrs, ...@@ -2483,10 +2482,9 @@ MemTxResult address_space_rw(AddressSpace *as, hwaddr addr, MemTxAttrs attrs,
rcu_read_lock(); rcu_read_lock();
while (len > 0) { while (len > 0) {
l = len; 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, true)) {
if (!memory_access_is_direct(mr, is_write)) {
release_lock |= prepare_mmio_access(mr); release_lock |= prepare_mmio_access(mr);
l = memory_access_size(mr, l, addr1); l = memory_access_size(mr, l, addr1);
/* XXX: could force current_cpu to NULL to avoid /* XXX: could force current_cpu to NULL to avoid
...@@ -2526,8 +2524,38 @@ MemTxResult address_space_rw(AddressSpace *as, hwaddr addr, MemTxAttrs attrs, ...@@ -2526,8 +2524,38 @@ MemTxResult address_space_rw(AddressSpace *as, hwaddr addr, MemTxAttrs attrs,
memcpy(ptr, buf, l); memcpy(ptr, buf, l);
invalidate_and_set_dirty(mr, addr1, l); invalidate_and_set_dirty(mr, addr1, l);
} }
} else {
if (!memory_access_is_direct(mr, is_write)) { if (release_lock) {
qemu_mutex_unlock_iothread();
release_lock = false;
}
len -= l;
buf += l;
addr += l;
}
rcu_read_unlock();
return result;
}
MemTxResult address_space_read(AddressSpace *as, hwaddr addr, MemTxAttrs attrs,
uint8_t *buf, int len)
{
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 */ /* I/O case */
release_lock |= prepare_mmio_access(mr); release_lock |= prepare_mmio_access(mr);
l = memory_access_size(mr, l, addr1); l = memory_access_size(mr, l, addr1);
...@@ -2564,7 +2592,6 @@ MemTxResult address_space_rw(AddressSpace *as, hwaddr addr, MemTxAttrs attrs, ...@@ -2564,7 +2592,6 @@ MemTxResult address_space_rw(AddressSpace *as, hwaddr addr, MemTxAttrs attrs,
ptr = qemu_get_ram_ptr(mr->ram_addr + addr1); ptr = qemu_get_ram_ptr(mr->ram_addr + addr1);
memcpy(buf, ptr, l); memcpy(buf, ptr, l);
} }
}
if (release_lock) { if (release_lock) {
qemu_mutex_unlock_iothread(); qemu_mutex_unlock_iothread();
...@@ -2580,19 +2607,16 @@ MemTxResult address_space_rw(AddressSpace *as, hwaddr addr, MemTxAttrs attrs, ...@@ -2580,19 +2607,16 @@ MemTxResult address_space_rw(AddressSpace *as, hwaddr addr, MemTxAttrs attrs,
return result; return result;
} }
MemTxResult address_space_write(AddressSpace *as, hwaddr addr, MemTxAttrs attrs, MemTxResult address_space_rw(AddressSpace *as, hwaddr addr, MemTxAttrs attrs,
const uint8_t *buf, int len) uint8_t *buf, int len, bool is_write)
{
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); 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, void cpu_physical_memory_rw(hwaddr addr, uint8_t *buf,
int len, int is_write) int len, int is_write)
{ {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册