aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--exec.c8
-rw-r--r--memory.c26
-rw-r--r--memory.h9
3 files changed, 34 insertions, 9 deletions
diff --git a/exec.c b/exec.c
index 3ce35399d6..1e5bbd6378 100644
--- a/exec.c
+++ b/exec.c
@@ -3668,9 +3668,13 @@ static void io_commit(MemoryListener *listener)
static void io_region_add(MemoryListener *listener,
MemoryRegionSection *section)
{
- iorange_init(&section->mr->iorange, &memory_region_iorange_ops,
+ MemoryRegionIORange *mrio = g_new(MemoryRegionIORange, 1);
+
+ mrio->mr = section->mr;
+ mrio->offset = section->offset_within_region;
+ iorange_init(&mrio->iorange, &memory_region_iorange_ops,
section->offset_within_address_space, section->size);
- ioport_register(&section->mr->iorange);
+ ioport_register(&mrio->iorange);
}
static void io_region_del(MemoryListener *listener,
diff --git a/memory.c b/memory.c
index 6565e2e696..4c3dc49262 100644
--- a/memory.c
+++ b/memory.c
@@ -382,16 +382,20 @@ static void memory_region_iorange_read(IORange *iorange,
unsigned width,
uint64_t *data)
{
- MemoryRegion *mr = container_of(iorange, MemoryRegion, iorange);
+ MemoryRegionIORange *mrio
+ = container_of(iorange, MemoryRegionIORange, iorange);
+ MemoryRegion *mr = mrio->mr;
+ offset += mrio->offset;
if (mr->ops->old_portio) {
- const MemoryRegionPortio *mrp = find_portio(mr, offset, width, false);
+ const MemoryRegionPortio *mrp = find_portio(mr, offset - mrio->offset,
+ width, false);
*data = ((uint64_t)1 << (width * 8)) - 1;
if (mrp) {
*data = mrp->read(mr->opaque, offset);
} else if (width == 2) {
- mrp = find_portio(mr, offset, 1, false);
+ mrp = find_portio(mr, offset - mrio->offset, 1, false);
assert(mrp);
*data = mrp->read(mr->opaque, offset) |
(mrp->read(mr->opaque, offset + 1) << 8);
@@ -410,15 +414,19 @@ static void memory_region_iorange_write(IORange *iorange,
unsigned width,
uint64_t data)
{
- MemoryRegion *mr = container_of(iorange, MemoryRegion, iorange);
+ MemoryRegionIORange *mrio
+ = container_of(iorange, MemoryRegionIORange, iorange);
+ MemoryRegion *mr = mrio->mr;
+ offset += mrio->offset;
if (mr->ops->old_portio) {
- const MemoryRegionPortio *mrp = find_portio(mr, offset, width, true);
+ const MemoryRegionPortio *mrp = find_portio(mr, offset - mrio->offset,
+ width, true);
if (mrp) {
mrp->write(mr->opaque, offset, data);
} else if (width == 2) {
- mrp = find_portio(mr, offset, 1, false);
+ mrp = find_portio(mr, offset - mrio->offset, 1, false);
assert(mrp);
mrp->write(mr->opaque, offset, data & 0xff);
mrp->write(mr->opaque, offset + 1, data >> 8);
@@ -431,9 +439,15 @@ static void memory_region_iorange_write(IORange *iorange,
memory_region_write_accessor, mr);
}
+static void memory_region_iorange_destructor(IORange *iorange)
+{
+ g_free(container_of(iorange, MemoryRegionIORange, iorange));
+}
+
const IORangeOps memory_region_iorange_ops = {
.read = memory_region_iorange_read,
.write = memory_region_iorange_write,
+ .destructor = memory_region_iorange_destructor,
};
static AddressSpace address_space_io;
diff --git a/memory.h b/memory.h
index b7bccd1968..53ff62b6c0 100644
--- a/memory.h
+++ b/memory.h
@@ -43,6 +43,14 @@ struct MemoryRegionMmio {
CPUWriteMemoryFunc *write[3];
};
+/* Internal use; thunks between old-style IORange and MemoryRegions. */
+typedef struct MemoryRegionIORange MemoryRegionIORange;
+struct MemoryRegionIORange {
+ IORange iorange;
+ MemoryRegion *mr;
+ target_phys_addr_t offset;
+};
+
/*
* Memory region callbacks
*/
@@ -117,7 +125,6 @@ struct MemoryRegion {
target_phys_addr_t addr;
void (*destructor)(MemoryRegion *mr);
ram_addr_t ram_addr;
- IORange iorange;
bool subpage;
bool terminates;
bool readable;