diff options
author | Paolo Bonzini <pbonzini@redhat.com> | 2013-05-24 17:45:48 +0200 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2013-05-29 16:27:24 +0200 |
commit | ce5d2f331ec42b43f92aa4c57fdaaf4c34ccb377 (patch) | |
tree | 12322456a33a321528b4668f2e0fc0e1ee3fea39 /memory.c | |
parent | 08521e28c7e6e8cc1f53424a0f845f58d2ed9546 (diff) |
memory: split accesses even when the old MMIO callbacks are used
This is useful for 64-bit memory accesses.
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'memory.c')
-rw-r--r-- | memory.c | 63 |
1 files changed, 46 insertions, 17 deletions
@@ -302,6 +302,20 @@ static void flatview_simplify(FlatView *view) } } +static void memory_region_oldmmio_read_accessor(void *opaque, + hwaddr addr, + uint64_t *value, + unsigned size, + unsigned shift, + uint64_t mask) +{ + MemoryRegion *mr = opaque; + uint64_t tmp; + + tmp = mr->ops->old_mmio.read[ctz32(size)](mr->opaque, addr); + *value |= (tmp & mask) << shift; +} + static void memory_region_read_accessor(void *opaque, hwaddr addr, uint64_t *value, @@ -319,6 +333,20 @@ static void memory_region_read_accessor(void *opaque, *value |= (tmp & mask) << shift; } +static void memory_region_oldmmio_write_accessor(void *opaque, + hwaddr addr, + uint64_t *value, + unsigned size, + unsigned shift, + uint64_t mask) +{ + MemoryRegion *mr = opaque; + uint64_t tmp; + + tmp = (*value >> shift) & mask; + mr->ops->old_mmio.write[ctz32(size)](mr->opaque, addr, tmp); +} + static void memory_region_write_accessor(void *opaque, hwaddr addr, uint64_t *value, @@ -359,6 +387,8 @@ static void access_with_adjusted_size(hwaddr addr, if (!access_size_max) { access_size_max = 4; } + + /* FIXME: support unaligned access? */ access_size = MAX(MIN(size, access_size_max), access_size_min); access_mask = -1ULL >> (64 - access_size * 8); for (i = 0; i < size; i += access_size) { @@ -902,16 +932,16 @@ static uint64_t memory_region_dispatch_read1(MemoryRegion *mr, return unassigned_mem_read(mr, addr, size); } - if (!mr->ops->read) { - return mr->ops->old_mmio.read[ctz32(size)](mr->opaque, addr); + if (mr->ops->read) { + access_with_adjusted_size(addr, &data, size, + mr->ops->impl.min_access_size, + mr->ops->impl.max_access_size, + memory_region_read_accessor, mr); + } else { + access_with_adjusted_size(addr, &data, size, 1, 4, + memory_region_oldmmio_read_accessor, mr); } - /* FIXME: support unaligned access */ - access_with_adjusted_size(addr, &data, size, - mr->ops->impl.min_access_size, - mr->ops->impl.max_access_size, - memory_region_read_accessor, mr); - return data; } @@ -956,16 +986,15 @@ static void memory_region_dispatch_write(MemoryRegion *mr, adjust_endianness(mr, &data, size); - if (!mr->ops->write) { - mr->ops->old_mmio.write[ctz32(size)](mr->opaque, addr, data); - return; + if (mr->ops->write) { + access_with_adjusted_size(addr, &data, size, + mr->ops->impl.min_access_size, + mr->ops->impl.max_access_size, + memory_region_write_accessor, mr); + } else { + access_with_adjusted_size(addr, &data, size, 1, 4, + memory_region_oldmmio_write_accessor, mr); } - - /* FIXME: support unaligned access */ - access_with_adjusted_size(addr, &data, size, - mr->ops->impl.min_access_size, - mr->ops->impl.max_access_size, - memory_region_write_accessor, mr); } void memory_region_init_io(MemoryRegion *mr, |