The subpage memory region wrapper dispatches MMIO accesses through
flatview_read/write, which re-enters memory_region_dispatch_read/write
on the underlying device MR. The inner dispatch uses size_memop() which
strips endianness bits (effectively MO_LE), causing adjust_endianness to
apply a byte-swap for DEVICE_NATIVE_ENDIAN devices on big-endian targets.
The outer dispatch's adjust_endianness then sees matching endianness
(MO_BE == devend_BE) and does nothing, leaving the data incorrectly swapped.
Fix by changing subpage_ops from DEVICE_NATIVE_ENDIAN to DEVICE_LITTLE_ENDIAN.
This matches the implicit LE semantics of size_memop() used in the inner
dispatch, so the outer adjust_endianness correctly compensates with a
second swap, yielding the correct net result.
For little-endian targets, DEVICE_NATIVE_ENDIAN already equals LE, so
this change has zero behavioral impact.
---
system/physmem.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/system/physmem.c b/system/physmem.c
index 2fb0c25c93..5d917482eb 100644
--- a/system/physmem.c
+++ b/system/physmem.c
@@ -2929,7 +2929,7 @@ static const MemoryRegionOps subpage_ops = {
.valid.min_access_size = 1,
.valid.max_access_size = 8,
.valid.accepts = subpage_accepts,
- .endianness = DEVICE_NATIVE_ENDIAN,
+ .endianness = DEVICE_LITTLE_ENDIAN,
};
static int subpage_register(subpage_t *mmio, uint32_t start, uint32_t end,
--
2.34.1