MemoryRegionOps (and its builder type) only support read/write callbacks. Add the ability to define {read,write}_with_attrs callbacks for devices that need them.
Signed-off-by: Manos Pitsidianakis <manos.pitsidiana...@linaro.org> --- rust/qemu-api/meson.build | 1 + rust/qemu-api/src/memory.rs | 52 ++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/rust/qemu-api/meson.build b/rust/qemu-api/meson.build index a090297c458b1a282211b9e241c0e447dd594167..95c097ec8f8dd31a863339d58eaa8bfc4d4dea18 100644 --- a/rust/qemu-api/meson.build +++ b/rust/qemu-api/meson.build @@ -26,6 +26,7 @@ foreach enum : c_enums endforeach c_bitfields = [ 'ClockEvent', + 'MemTxResult', 'VMStateFlags', ] foreach enum : c_bitfields diff --git a/rust/qemu-api/src/memory.rs b/rust/qemu-api/src/memory.rs index b1907aa01300a3fac8e1f3b69c5d50da631a556d..98d1e116147aba2c9034a61159492382b1ee0e5e 100644 --- a/rust/qemu-api/src/memory.rs +++ b/rust/qemu-api/src/memory.rs @@ -9,7 +9,7 @@ marker::PhantomData, }; -pub use bindings::{hwaddr, MemTxAttrs}; +pub use bindings::{hwaddr, MemTxAttrs, MemTxResult}; use crate::{ bindings::{self, device_endian, memory_region_init_io}, @@ -59,6 +59,20 @@ unsafe impl<T: Sync> Sync for MemoryRegionOps<T> {} F::call((unsafe { &*(opaque.cast::<T>()) }, addr, size)) } +unsafe extern "C" fn memory_region_ops_read_with_attrs_cb< + T, + F: for<'a> FnCall<(&'a T, hwaddr, *mut u64, Bits, MemTxAttrs), MemTxResult>, +>( + opaque: *mut c_void, + addr: hwaddr, + data: *mut u64, + size: c_uint, + attrs: MemTxAttrs, +) -> MemTxResult { + let size = Bits::try_from(size).expect("invalid size argument"); + F::call((unsafe { &*(opaque.cast::<T>()) }, addr, data, size, attrs)) +} + unsafe extern "C" fn memory_region_ops_write_cb< T, F: for<'a> FnCall<(&'a T, hwaddr, u64, Bits)>, @@ -72,6 +86,20 @@ unsafe impl<T: Sync> Sync for MemoryRegionOps<T> {} F::call((unsafe { &*(opaque.cast::<T>()) }, addr, data, size)) } +unsafe extern "C" fn memory_region_ops_write_with_attrs_cb< + T, + F: for<'a> FnCall<(&'a T, hwaddr, u64, Bits, MemTxAttrs), MemTxResult>, +>( + opaque: *mut c_void, + addr: hwaddr, + data: u64, + size: c_uint, + attrs: MemTxAttrs, +) -> MemTxResult { + let size = Bits::try_from(size).expect("invalid size argument"); + F::call((unsafe { &*(opaque.cast::<T>()) }, addr, data, size, attrs)) +} + impl<T> MemoryRegionOpsBuilder<T> { #[must_use] pub const fn read<F: for<'a> FnCall<(&'a T, hwaddr, Bits), u64>>(mut self, _f: &F) -> Self { @@ -86,6 +114,28 @@ pub const fn write<F: for<'a> FnCall<(&'a T, hwaddr, u64, Bits)>>(mut self, _f: } #[must_use] + pub const fn read_with_attrs< + F: for<'a> FnCall<(&'a T, hwaddr, *mut u64, Bits, MemTxAttrs), MemTxResult>, + >( + mut self, + _f: &F, + ) -> Self { + self.0.read_with_attrs = Some(memory_region_ops_read_with_attrs_cb::<T, F>); + self + } + + #[must_use] + pub const fn write_with_attrs< + F: for<'a> FnCall<(&'a T, hwaddr, u64, Bits, MemTxAttrs), MemTxResult>, + >( + mut self, + _f: &F, + ) -> Self { + self.0.write_with_attrs = Some(memory_region_ops_write_with_attrs_cb::<T, F>); + self + } + + #[must_use] pub const fn big_endian(mut self) -> Self { self.0.endianness = device_endian::DEVICE_BIG_ENDIAN; self -- 2.47.2