This will be needed for some corner cases with para-virtual the I/O ports. Signed-off-by: Jan Kiszka <jan.kis...@siemens.com> --- exec.c | 33 ++++++++++++++++++--------------- 1 files changed, 18 insertions(+), 15 deletions(-)
diff --git a/exec.c b/exec.c index 3ee1f3f..9c582b1 100644 --- a/exec.c +++ b/exec.c @@ -1833,38 +1833,41 @@ void address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf, uint8_t *ptr; uint32_t val; MemoryRegionSection *section; + MemoryRegion *mr; while (len > 0) { l = ((addr & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE) - addr; if (l > len) l = len; section = address_space_lookup_region(as, addr); + mr = section->mr; if (is_write) { - if (!memory_region_is_ram(section->mr)) { + if (!memory_region_is_ram(mr)) { hwaddr addr1; addr1 = memory_region_section_addr(section, addr); /* XXX: could force cpu_single_env to NULL to avoid potential bugs */ - if (l >= 4 && ((addr1 & 3) == 0)) { + if (l >= 4 && ((addr1 & 3) == 0 || mr->ops->impl.unaligned)) { /* 32 bit write access */ val = ldl_p(buf); - io_mem_write(section->mr, addr1, val, 4); + io_mem_write(mr, addr1, val, 4); l = 4; - } else if (l >= 2 && ((addr1 & 1) == 0)) { + } else if (l >= 2 && + ((addr1 & 1) == 0 || mr->ops->impl.unaligned)) { /* 16 bit write access */ val = lduw_p(buf); - io_mem_write(section->mr, addr1, val, 2); + io_mem_write(mr, addr1, val, 2); l = 2; } else { /* 8 bit write access */ val = ldub_p(buf); - io_mem_write(section->mr, addr1, val, 1); + io_mem_write(mr, addr1, val, 1); l = 1; } } else if (!section->readonly) { ram_addr_t addr1; - addr1 = memory_region_get_ram_addr(section->mr) + addr1 = memory_region_get_ram_addr(mr) + memory_region_section_addr(section, addr); /* RAM case */ ptr = qemu_get_ram_ptr(addr1); @@ -1873,30 +1876,30 @@ void address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf, qemu_put_ram_ptr(ptr); } } else { - if (!(memory_region_is_ram(section->mr) || - memory_region_is_romd(section->mr))) { + if (!(memory_region_is_ram(mr) || memory_region_is_romd(mr))) { hwaddr addr1; /* I/O case */ addr1 = memory_region_section_addr(section, addr); - if (l >= 4 && ((addr1 & 3) == 0)) { + if (l >= 4 && ((addr1 & 3) == 0 || mr->ops->impl.unaligned)) { /* 32 bit read access */ - val = io_mem_read(section->mr, addr1, 4); + val = io_mem_read(mr, addr1, 4); stl_p(buf, val); l = 4; - } else if (l >= 2 && ((addr1 & 1) == 0)) { + } else if (l >= 2 && + ((addr1 & 1) == 0 || mr->ops->impl.unaligned)) { /* 16 bit read access */ - val = io_mem_read(section->mr, addr1, 2); + val = io_mem_read(mr, addr1, 2); stw_p(buf, val); l = 2; } else { /* 8 bit read access */ - val = io_mem_read(section->mr, addr1, 1); + val = io_mem_read(mr, addr1, 1); stb_p(buf, val); l = 1; } } else { /* RAM case */ - ptr = qemu_get_ram_ptr(section->mr->ram_addr + ptr = qemu_get_ram_ptr(mr->ram_addr + memory_region_section_addr(section, addr)); memcpy(buf, ptr, l); -- 1.7.3.4