@@ -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);
This will be needed for some corner cases with para-virtual the I/O ports. Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com> --- exec.c | 33 ++++++++++++++++++--------------- 1 files changed, 18 insertions(+), 15 deletions(-)