From 1a59bdba4bf476c242fbf88283a71427c0160f06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Sun, 16 Aug 2020 19:07:11 +0200 Subject: [PATCH] memory: Directly dispatch alias accesses on origin memory region MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since commit 2cdfcf272d ("memory: assign MemoryRegionOps to all regions"), all newly created regions are assigned with unassigned_mem_ops (which might be then overwritten). When using aliased container regions, and there is no region mapped at address 0 in the container, the memory_region_dispatch_read() and memory_region_dispatch_write() calls incorrectly return the container unassigned_mem_ops, because the alias offset is not used. Consider the following setup: +--------------------+ < - - - - - - - - - - - + | Container | mr | (unassigned_mem) | | | | | | | | | alias_offset + + <- - - - - - +----------+---------+ | +----------------+ | | | | | MemoryRegion0 | | | | | +----------------+ | | Alias | addr1 | | MemoryRegion1 | | <~ ~ ~ ~ ~ | | <~~~~~~ | +----------------+ | | | | | +--------------------+ | | | | | | | | | +----------------+ | | | MemoryRegionX | | | +----------------+ | | | MemoryRegionY | | | +----------------+ | | | MemoryRegionZ | | | +----------------+ | +--------------------+ The memory_region_init_alias() flow is: memory_region_init_alias() -> memory_region_init() -> object_initialize(TYPE_MEMORY_REGION) -> memory_region_initfn() -> mr->ops = &unassigned_mem_ops; Later when accessing offset=addr1 via the alias, we expect to hit MemoryRegion1. The memory_region_dispatch_read() flow is: memory_region_dispatch_read(addr1) -> memory_region_access_valid(mr) <- addr1 offset is ignored -> mr->ops->valid.accepts() -> unassigned_mem_accepts() <- false <- false <- MEMTX_DECODE_ERROR The caller gets a MEMTX_DECODE_ERROR while the access is OK. Fix by dispatching aliases recursively, accessing its origin region after adding the alias offset. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Peter Xu Message-Id: <20210418055708.820980-1-f4bug@amsat.org> --- softmmu/memory.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/softmmu/memory.c b/softmmu/memory.c index 7340e19ff5..0c463e0fe5 100644 --- a/softmmu/memory.c +++ b/softmmu/memory.c @@ -1444,6 +1444,11 @@ MemTxResult memory_region_dispatch_read(MemoryRegion *mr, unsigned size = memop_size(op); MemTxResult r; + if (mr->alias) { + return memory_region_dispatch_read(mr->alias, + mr->alias_offset + addr, + pval, op, attrs); + } if (!memory_region_access_valid(mr, addr, size, false, attrs)) { *pval = unassigned_mem_read(mr, addr, size); return MEMTX_DECODE_ERROR; @@ -1488,6 +1493,11 @@ MemTxResult memory_region_dispatch_write(MemoryRegion *mr, { unsigned size = memop_size(op); + if (mr->alias) { + return memory_region_dispatch_write(mr->alias, + mr->alias_offset + addr, + data, op, attrs); + } if (!memory_region_access_valid(mr, addr, size, true, attrs)) { unassigned_mem_write(mr, addr, data, size); return MEMTX_DECODE_ERROR;