On 11/3/26 12:59, Djordje Todorovic wrote:
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,
NAck, this likely break big-endian hosts.
};
