Reviewed-by: Anthony Liguori <aligu...@us.ibm.com> Signed-off-by: Avi Kivity <a...@redhat.com> --- memory.c | 32 ++++++++++++++++++++++++++++++++ memory.h | 17 +++++++++++++++++ 2 files changed, 49 insertions(+), 0 deletions(-)
diff --git a/memory.c b/memory.c index df0ed0e..5f2c9ef 100644 --- a/memory.c +++ b/memory.c @@ -218,6 +218,21 @@ static AddressSpace address_space_memory = { .ops = &address_space_ops_memory, }; +static const MemoryRegionPortio *find_portio(MemoryRegion *mr, uint64_t offset, + unsigned width, bool write) +{ + const MemoryRegionPortio *mrp; + + for (mrp = mr->ops->old_portio; mrp->size; ++mrp) { + if (offset >= mrp->offset && offset < mrp->offset + mrp->len + && width == mrp->size + && (write ? (bool)mrp->write : (bool)mrp->read)) { + return mrp; + } + } + return NULL; +} + static void memory_region_iorange_read(IORange *iorange, uint64_t offset, unsigned width, @@ -225,6 +240,15 @@ static void memory_region_iorange_read(IORange *iorange, { MemoryRegion *mr = container_of(iorange, MemoryRegion, iorange); + if (mr->ops->old_portio) { + const MemoryRegionPortio *mrp = find_portio(mr, offset, width, false); + + *data = ((uint64_t)1 << (width * 8)) - 1; + if (mrp) { + *data = mrp->read(mr->opaque, offset - mrp->offset); + } + return; + } *data = mr->ops->read(mr->opaque, offset, width); } @@ -235,6 +259,14 @@ static void memory_region_iorange_write(IORange *iorange, { MemoryRegion *mr = container_of(iorange, MemoryRegion, iorange); + if (mr->ops->old_portio) { + const MemoryRegionPortio *mrp = find_portio(mr, offset, width, true); + + if (mrp) { + mrp->write(mr->opaque, offset - mrp->offset, data); + } + return; + } mr->ops->write(mr->opaque, offset, data, width); } diff --git a/memory.h b/memory.h index 88ba428..40ab95a 100644 --- a/memory.h +++ b/memory.h @@ -23,9 +23,11 @@ #include "targphys.h" #include "qemu-queue.h" #include "iorange.h" +#include "ioport.h" typedef struct MemoryRegionOps MemoryRegionOps; typedef struct MemoryRegion MemoryRegion; +typedef struct MemoryRegionPortio MemoryRegionPortio; /* Must match *_DIRTY_FLAGS in cpu-all.h. To be replaced with dynamic * registration. @@ -78,6 +80,11 @@ struct MemoryRegionOps { */ bool unaligned; } impl; + + /* If .read and .write are not present, old_portio may be used for + * backwards compatibility with old portio registration + */ + const MemoryRegionPortio *old_portio; }; typedef struct CoalescedMemoryRange CoalescedMemoryRange; @@ -105,6 +112,16 @@ struct MemoryRegion { uint8_t dirty_log_mask; }; +struct MemoryRegionPortio { + uint32_t offset; + uint32_t len; + unsigned size; + IOPortReadFunc *read; + IOPortWriteFunc *write; +}; + +#define PORTIO_END { } + /** * memory_region_init: Initialize a memory region * -- 1.7.5.3