Replace the ldn_he_p/stn_he_p() calls by their explicit endianness
variants. Duplicate the MemoryRegionOps, using one entry for BIG
and another for LITTLE endianness. Select the proper MemoryRegionOps
in memory_region_init_ram_device_ptr().
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
system/memory.c | 68 ++++++++++++++++++++++++++++++++++---------------
1 file changed, 48 insertions(+), 20 deletions(-)
diff --git a/system/memory.c b/system/memory.c
index 8b84661ae36..5bcdeaf0bee 100644
--- a/system/memory.c
+++ b/system/memory.c
@@ -1361,41 +1361,69 @@ const MemoryRegionOps unassigned_mem_ops = {
.endianness = DEVICE_NATIVE_ENDIAN,
};
-static uint64_t memory_region_ram_device_read(void *opaque,
- hwaddr addr, unsigned size)
+static uint64_t memory_region_ram_device_read_le(void *opaque,
+ hwaddr addr, unsigned size)
{
MemoryRegion *mr = opaque;
- uint64_t data = ldn_he_p(mr->ram_block->host + addr, size);
+ uint64_t data = ldn_le_p(mr->ram_block->host + addr, size);
trace_memory_region_ram_device_read(get_cpu_index(), mr, addr, data, size);
return data;
}
-static void memory_region_ram_device_write(void *opaque, hwaddr addr,
- uint64_t data, unsigned size)
+static uint64_t memory_region_ram_device_read_be(void *opaque,
+ hwaddr addr, unsigned size)
+{
+ MemoryRegion *mr = opaque;
+ uint64_t data = ldn_be_p(mr->ram_block->host + addr, size);
+
+ trace_memory_region_ram_device_read(get_cpu_index(), mr, addr, data, size);
+
+ return data;
+}
+
+static void memory_region_ram_device_write_le(void *opaque, hwaddr addr,
+ uint64_t data, unsigned size)
{
MemoryRegion *mr = opaque;
trace_memory_region_ram_device_write(get_cpu_index(), mr, addr, data, size);
- stn_he_p(mr->ram_block->host + addr, size, data);
+ stn_le_p(mr->ram_block->host + addr, size, data);
}
-static const MemoryRegionOps ram_device_mem_ops = {
- .read = memory_region_ram_device_read,
- .write = memory_region_ram_device_write,
- .endianness = HOST_BIG_ENDIAN ? DEVICE_BIG_ENDIAN : DEVICE_LITTLE_ENDIAN,
- .valid = {
- .min_access_size = 1,
- .max_access_size = 8,
- .unaligned = true,
- },
- .impl = {
- .min_access_size = 1,
- .max_access_size = 8,
- .unaligned = true,
+static void memory_region_ram_device_write_be(void *opaque, hwaddr addr,
+ uint64_t data, unsigned size)
+{
+ MemoryRegion *mr = opaque;
+
+ trace_memory_region_ram_device_write(get_cpu_index(), mr, addr, data, size);
+
+ stn_be_p(mr->ram_block->host + addr, size, data);
+}
+
+static const MemoryRegionOps ram_device_mem_ops[2] = {
+ [0 ... 1] = {
+ .valid = {
+ .min_access_size = 1,
+ .max_access_size = 8,
+ .unaligned = true,
+ },
+ .impl = {
+ .min_access_size = 1,
+ .max_access_size = 8,
+ .unaligned = true,
+ },
},
+
+ [0].endianness = DEVICE_LITTLE_ENDIAN,
+ [0].read = memory_region_ram_device_read_le,
+ [0].write = memory_region_ram_device_write_le,
+
+ [1].endianness = DEVICE_BIG_ENDIAN,
+ [1].read = memory_region_ram_device_read_be,
+ [1].write = memory_region_ram_device_write_be,
};
bool memory_region_access_valid(MemoryRegion *mr,
@@ -1712,7 +1740,7 @@ void memory_region_init_ram_device_ptr(MemoryRegion *mr,
mr->ram = true;
mr->terminates = true;
mr->ram_device = true;
- mr->ops = &ram_device_mem_ops;
+ mr->ops = &ram_device_mem_ops[HOST_BIG_ENDIAN];
mr->opaque = mr;
mr->destructor = memory_region_destructor_ram;
--
2.52.0
On 12/19/25 08:28, Philippe Mathieu-Daudé wrote:
> Replace the ldn_he_p/stn_he_p() calls by their explicit endianness
> variants. Duplicate the MemoryRegionOps, using one entry for BIG
> and another for LITTLE endianness. Select the proper MemoryRegionOps
> in memory_region_init_ram_device_ptr().
...
> -static const MemoryRegionOps ram_device_mem_ops = {
> - .read = memory_region_ram_device_read,
> - .write = memory_region_ram_device_write,
> - .endianness = HOST_BIG_ENDIAN ? DEVICE_BIG_ENDIAN : DEVICE_LITTLE_ENDIAN,
How is the choice here different than ...
> - mr->ops = &ram_device_mem_ops;
> + mr->ops = &ram_device_mem_ops[HOST_BIG_ENDIAN];
... here?
One of those two sets of functions is always dead.
r~
© 2016 - 2026 Red Hat, Inc.