From: Ruslan Ruslichenko <[email protected]> Introduce a unified 'MemoryTransaction' structure to encapsulate all parameters of a memory access, including address, data, size, and attributes.
The logic in memory_region_dispatch_read/write is updated to prioritize the new 'access' callback when available. This change simplifies the integration of transaction-based subsystems, such as the Remote Port, by providing a standard container for memory access metadata. Signed-off-by: Edgar E. Iglesias <[email protected]> Signed-off-by: Takahiro Nakata <[email protected]> Signed-off-by: Ruslan Ruslichenko <[email protected]> --- include/system/memory.h | 23 ++++++++++++++ system/memory.c | 66 +++++++++++++++++++++++++++++++++++++++-- 2 files changed, 87 insertions(+), 2 deletions(-) diff --git a/include/system/memory.h b/include/system/memory.h index 0562af3136..e1fb82608d 100644 --- a/include/system/memory.h +++ b/include/system/memory.h @@ -84,6 +84,28 @@ extern unsigned int global_dirty_tracking; typedef struct MemoryRegionOps MemoryRegionOps; +typedef struct MemoryTransaction { + union { + /* + * Data is passed by values up to 64bit sizes. Beyond + * that, a pointer is passed in p8. + * + * Note that p8 has no alignment restrictions. + */ + uint8_t *p8; + uint64_t u64; + uint32_t u32; + uint16_t u16; + uint8_t u8; + } data; + bool rw; + hwaddr addr; + unsigned int size; + MemTxAttrs attr; + void *opaque; +} MemoryTransaction; + + struct ReservedRegion { Range range; unsigned type; @@ -298,6 +320,7 @@ static inline void iommu_notifier_init(IOMMUNotifier *n, IOMMUNotify fn, * Memory region callbacks */ struct MemoryRegionOps { + MemTxResult (*access)(MemoryTransaction *tr); /* Read from the memory region. @addr is relative to @mr; @size is * in bytes. */ uint64_t (*read)(void *opaque, diff --git a/system/memory.c b/system/memory.c index 0b1462f028..4f62796cd3 100644 --- a/system/memory.c +++ b/system/memory.c @@ -431,6 +431,31 @@ static int get_cpu_index(void) return -1; } +static MemTxResult memory_region_read_accessor_attr(MemoryRegion *mr, + hwaddr addr, + uint64_t *value, + unsigned size, + signed shift, + uint64_t mask, + MemTxAttrs attrs) +{ + MemoryTransaction tr = { { 0 } }; + MemTxResult ret; + + if (mr->flush_coalesced_mmio) { + qemu_flush_coalesced_mmio_buffer(); + } + + tr.opaque = mr->opaque; + tr.addr = addr; + tr.size = size; + tr.attr = attrs; + ret = mr->ops->access(&tr); + *value |= (tr.data.u64 & mask) << shift; + + return ret; +} + static MemTxResult memory_region_read_accessor(MemoryRegion *mr, hwaddr addr, uint64_t *value, @@ -476,6 +501,31 @@ static MemTxResult memory_region_read_with_attrs_accessor(MemoryRegion *mr, return r; } +static MemTxResult memory_region_write_accessor_attr(MemoryRegion *mr, + hwaddr addr, + uint64_t *value, + unsigned size, + signed shift, + uint64_t mask, + MemTxAttrs attrs) +{ + MemoryTransaction tr = { { 0 } }; + + if (mr->flush_coalesced_mmio) { + qemu_flush_coalesced_mmio_buffer(); + } + + tr.opaque = mr->opaque; + tr.rw = true; + tr.addr = addr; + tr.size = size; + tr.attr = attrs; + tr.data.u64 = (*value >> shift) & mask; + trace_memory_region_ops_write(get_cpu_index(), mr, tr.addr, tr.data.u64, + tr.size, memory_region_name(mr)); + return mr->ops->access(&tr); +} + static MemTxResult memory_region_write_accessor(MemoryRegion *mr, hwaddr addr, uint64_t *value, @@ -1603,7 +1653,13 @@ static MemTxResult memory_region_dispatch_read1(MemoryRegion *mr, { *pval = 0; - if (mr->ops->read) { + if (mr->ops->access) { + return access_with_adjusted_size(addr, pval, size, + mr->ops->impl.min_access_size, + mr->ops->impl.max_access_size, + memory_region_read_accessor_attr, + mr, attrs); + } else if (mr->ops->read) { return access_with_adjusted_size(addr, pval, size, mr->ops->impl.min_access_size, mr->ops->impl.max_access_size, @@ -1698,7 +1754,13 @@ MemTxResult memory_region_dispatch_write(MemoryRegion *mr, return MEMTX_OK; } - if (mr->ops->write) { + if (mr->ops->access) { + return access_with_adjusted_size(addr, &data, size, + mr->ops->impl.min_access_size, + mr->ops->impl.max_access_size, + memory_region_write_accessor_attr, + mr, attrs); + } else if (mr->ops->write) { return access_with_adjusted_size(addr, &data, size, mr->ops->impl.min_access_size, mr->ops->impl.max_access_size, -- 2.43.0
