diff options
Diffstat (limited to 'memory.c')
-rw-r--r-- | memory.c | 107 |
1 files changed, 59 insertions, 48 deletions
@@ -18,7 +18,7 @@ #include "exec/ioport.h" #include "qemu/bitops.h" #include "qom/object.h" -#include "sysemu/kvm.h" +#include "trace.h" #include <assert.h> #include "exec/memory-internal.h" @@ -339,65 +339,104 @@ static void flatview_simplify(FlatView *view) } } -static void memory_region_oldmmio_read_accessor(void *opaque, +static bool memory_region_big_endian(MemoryRegion *mr) +{ +#ifdef TARGET_WORDS_BIGENDIAN + return mr->ops->endianness != DEVICE_LITTLE_ENDIAN; +#else + return mr->ops->endianness == DEVICE_BIG_ENDIAN; +#endif +} + +static bool memory_region_wrong_endianness(MemoryRegion *mr) +{ +#ifdef TARGET_WORDS_BIGENDIAN + return mr->ops->endianness == DEVICE_LITTLE_ENDIAN; +#else + return mr->ops->endianness == DEVICE_BIG_ENDIAN; +#endif +} + +static void adjust_endianness(MemoryRegion *mr, uint64_t *data, unsigned size) +{ + if (memory_region_wrong_endianness(mr)) { + switch (size) { + case 1: + break; + case 2: + *data = bswap16(*data); + break; + case 4: + *data = bswap32(*data); + break; + case 8: + *data = bswap64(*data); + break; + default: + abort(); + } + } +} + +static void memory_region_oldmmio_read_accessor(MemoryRegion *mr, 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); + trace_memory_region_ops_read(mr, addr, tmp, size); *value |= (tmp & mask) << shift; } -static void memory_region_read_accessor(void *opaque, +static void memory_region_read_accessor(MemoryRegion *mr, hwaddr addr, uint64_t *value, unsigned size, unsigned shift, uint64_t mask) { - MemoryRegion *mr = opaque; uint64_t tmp; if (mr->flush_coalesced_mmio) { qemu_flush_coalesced_mmio_buffer(); } tmp = mr->ops->read(mr->opaque, addr, size); + trace_memory_region_ops_read(mr, addr, tmp, size); *value |= (tmp & mask) << shift; } -static void memory_region_oldmmio_write_accessor(void *opaque, +static void memory_region_oldmmio_write_accessor(MemoryRegion *mr, hwaddr addr, uint64_t *value, unsigned size, unsigned shift, uint64_t mask) { - MemoryRegion *mr = opaque; uint64_t tmp; tmp = (*value >> shift) & mask; + trace_memory_region_ops_write(mr, addr, tmp, size); mr->ops->old_mmio.write[ctz32(size)](mr->opaque, addr, tmp); } -static void memory_region_write_accessor(void *opaque, +static void memory_region_write_accessor(MemoryRegion *mr, hwaddr addr, uint64_t *value, unsigned size, unsigned shift, uint64_t mask) { - MemoryRegion *mr = opaque; uint64_t tmp; if (mr->flush_coalesced_mmio) { qemu_flush_coalesced_mmio_buffer(); } tmp = (*value >> shift) & mask; + trace_memory_region_ops_write(mr, addr, tmp, size); mr->ops->write(mr->opaque, addr, tmp, size); } @@ -406,13 +445,13 @@ static void access_with_adjusted_size(hwaddr addr, unsigned size, unsigned access_size_min, unsigned access_size_max, - void (*access)(void *opaque, + void (*access)(MemoryRegion *mr, hwaddr addr, uint64_t *value, unsigned size, unsigned shift, uint64_t mask), - void *opaque) + MemoryRegion *mr) { uint64_t access_mask; unsigned access_size; @@ -428,13 +467,15 @@ static void access_with_adjusted_size(hwaddr addr, /* 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) { -#ifdef TARGET_WORDS_BIGENDIAN - access(opaque, addr + i, value, access_size, - (size - access_size - i) * 8, access_mask); -#else - access(opaque, addr + i, value, access_size, i * 8, access_mask); -#endif + if (memory_region_big_endian(mr)) { + for (i = 0; i < size; i += access_size) { + access(mr, addr + i, value, access_size, + (size - access_size - i) * 8, access_mask); + } + } else { + for (i = 0; i < size; i += access_size) { + access(mr, addr + i, value, access_size, i * 8, access_mask); + } } } @@ -786,15 +827,6 @@ static void memory_region_destructor_rom_device(MemoryRegion *mr) qemu_ram_free(mr->ram_addr & TARGET_PAGE_MASK); } -static bool memory_region_wrong_endianness(MemoryRegion *mr) -{ -#ifdef TARGET_WORDS_BIGENDIAN - return mr->ops->endianness == DEVICE_LITTLE_ENDIAN; -#else - return mr->ops->endianness == DEVICE_BIG_ENDIAN; -#endif -} - void memory_region_init(MemoryRegion *mr, Object *owner, const char *name, @@ -921,27 +953,6 @@ static uint64_t memory_region_dispatch_read1(MemoryRegion *mr, return data; } -static void adjust_endianness(MemoryRegion *mr, uint64_t *data, unsigned size) -{ - if (memory_region_wrong_endianness(mr)) { - switch (size) { - case 1: - break; - case 2: - *data = bswap16(*data); - break; - case 4: - *data = bswap32(*data); - break; - case 8: - *data = bswap64(*data); - break; - default: - abort(); - } - } -} - static bool memory_region_dispatch_read(MemoryRegion *mr, hwaddr addr, uint64_t *pval, |