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


Reply via email to