Add a binding (target_is_big_endian()) to check whether target is big
endian or not. This could help user to adjust endian before calling
AddresssSpace::store() or after calling AddressSpace::load().

Add the example in the documentation of AddresssSpace::store() to help
explain how to use it.

Signed-off-by: Zhao Liu <zhao1....@intel.com>
---
 rust/qemu-api/src/memory.rs | 28 +++++++++++++++++++++++++---
 rust/qemu-api/wrapper.h     |  1 +
 2 files changed, 26 insertions(+), 3 deletions(-)

diff --git a/rust/qemu-api/src/memory.rs b/rust/qemu-api/src/memory.rs
index 42bba23cf3f8..a8eb83c95ead 100644
--- a/rust/qemu-api/src/memory.rs
+++ b/rust/qemu-api/src/memory.rs
@@ -31,7 +31,7 @@
         memory_region_init_io, section_access_allowed, 
section_covers_region_addr,
         section_fuzz_dma_read, section_get_host_addr, section_rust_load,
         section_rust_read_continue_step, section_rust_store, 
section_rust_write_continue_step,
-        MEMTX_OK,
+        target_big_endian, MEMTX_OK,
     },
     callbacks::FnCall,
     cell::Opaque,
@@ -1107,9 +1107,25 @@ pub fn read(&self, buf: &mut [u8], addr: GuestAddress) 
-> Result<usize> {
     /// This function is similar to `address_space_st{size}` in C side.
     ///
     /// But it only assumes @val follows target-endian by default. So ensure
-    /// the endian of `val` aligned with target, before using this method.
+    /// the endian of `val` aligned with target, before using this method.  The
+    /// taget-endian can be checked with [`target_is_big_endian`].
     ///
     /// And it assumes the memory attributes is MEMTXATTRS_UNSPECIFIED.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use qemu_api::memory::{ADDRESS_SPACE_MEMORY, target_is_big_endian};
+    ///
+    /// let addr = GuestAddress(0x123438000);
+    /// let val: u32 = 5;
+    /// let val_end = if target_is_big_endian() {
+    ///     val.to_be()
+    /// } else {
+    ///     val.to_le()
+    /// }
+    ///
+    /// assert!(ADDRESS_SPACE_MEMORY.store(addr, val_end).is_ok());
     pub fn store<T: AtomicAccess>(&self, addr: GuestAddress, val: T) -> 
Result<()> {
         rcu_read_lock();
         let r = self.memory().deref().store(val, addr, Ordering::Relaxed);
@@ -1122,7 +1138,8 @@ pub fn store<T: AtomicAccess>(&self, addr: GuestAddress, 
val: T) -> Result<()> {
     /// This function is similar to `address_space_ld{size}` in C side.
     ///
     /// But it only support target-endian by default.  The returned value is
-    /// with target-endian.
+    /// with target-endian.  The taget-endian can be checked with
+    /// [`target_is_big_endian`].
     ///
     /// And it assumes the memory attributes is MEMTXATTRS_UNSPECIFIED.
     pub fn load<T: AtomicAccess>(&self, addr: GuestAddress) -> Result<T> {
@@ -1147,3 +1164,8 @@ pub fn load<T: AtomicAccess>(&self, addr: GuestAddress) 
-> Result<T> {
     // the whole QEMU life.
     &*wrapper_ptr
 };
+
+pub fn target_is_big_endian() -> bool {
+    // SAFETY: the return value is boolean, so it is always valid.
+    unsafe { target_big_endian() }
+}
diff --git a/rust/qemu-api/wrapper.h b/rust/qemu-api/wrapper.h
index ce0ac8d3f550..c466b93054aa 100644
--- a/rust/qemu-api/wrapper.h
+++ b/rust/qemu-api/wrapper.h
@@ -70,3 +70,4 @@ typedef enum memory_order {
 #include "system/address-spaces.h"
 #include "hw/char/pl011.h"
 #include "qemu/rcu.h"
+#include "qemu/target-info.h"
-- 
2.34.1


Reply via email to