Add 2 patches to support QEMU memory backend implementation. Signed-off-by: Zhao Liu <zhao1....@intel.com> --- .../packagefiles/vm-memory-0.16-rs/0001.diff | 81 +++++++++++++ .../packagefiles/vm-memory-0.16-rs/0002.diff | 111 ++++++++++++++++++ subprojects/vm-memory-0.16-rs.wrap | 2 + 3 files changed, 194 insertions(+) create mode 100644 subprojects/packagefiles/vm-memory-0.16-rs/0001.diff create mode 100644 subprojects/packagefiles/vm-memory-0.16-rs/0002.diff
diff --git a/subprojects/packagefiles/vm-memory-0.16-rs/0001.diff b/subprojects/packagefiles/vm-memory-0.16-rs/0001.diff new file mode 100644 index 000000000000..037193108d45 --- /dev/null +++ b/subprojects/packagefiles/vm-memory-0.16-rs/0001.diff @@ -0,0 +1,81 @@ +From 298f8ba019b2fe159fa943e0ae4dfd3c83ee64e0 Mon Sep 17 00:00:00 2001 +From: Zhao Liu <zhao1....@intel.com> +Date: Wed, 6 Aug 2025 11:31:11 +0800 +Subject: [PATCH 1/2] guest_memory: Add a marker tarit to implement + Bytes<GuestAddress> for GuestMemory + +At present, Bytes<GuestAddress> is implemented as the blanet trait for +all types which implemented GuestMemory. + +QEMU needs to customize its own Bytes<GuestAddress> implementation. + +So add a marker trait to still provide the default implementation for +GuestRegionCollection and GuestMemoryMmap, and QEMU could have its own +implementation. + +Signed-off-by: Zhao Liu <zhao1....@intel.com> +--- + src/guest_memory.rs | 8 +++++++- + src/lib.rs | 2 +- + src/region.rs | 6 ++++-- + 3 files changed, 12 insertions(+), 4 deletions(-) + +diff --git a/src/guest_memory.rs b/src/guest_memory.rs +index 39e4f10a89d6..5b78038c3c92 100644 +--- a/src/guest_memory.rs ++++ b/src/guest_memory.rs +@@ -457,7 +457,13 @@ pub trait GuestMemory { + } + } + +-impl<T: GuestMemory + ?Sized> Bytes<GuestAddress> for T { ++/// A marker trait that if implemented on a type `M` makes available a default ++/// implementation of `Bytes<GuestAddress>` for `M`, based on the assumption ++/// that the entire `GuestMemory` is just traditional Guest memory abstraction ++/// without any special access requirements. ++pub trait GuestMemoryBytes: GuestMemory {} ++ ++impl<M: GuestMemoryBytes + ?Sized> Bytes<GuestAddress> for M { + type E = Error; + + fn write(&self, buf: &[u8], addr: GuestAddress) -> Result<usize> { +diff --git a/src/lib.rs b/src/lib.rs +index 2f87f4c8482f..64ed3ec27a36 100644 +--- a/src/lib.rs ++++ b/src/lib.rs +@@ -47,7 +47,7 @@ pub use endian::{Be16, Be32, Be64, BeSize, Le16, Le32, Le64, LeSize}; + pub mod guest_memory; + pub use guest_memory::{ + Error as GuestMemoryError, FileOffset, GuestAddress, GuestAddressSpace, GuestMemory, +- GuestUsize, MemoryRegionAddress, Result as GuestMemoryResult, ++ GuestMemoryBytes, GuestUsize, MemoryRegionAddress, Result as GuestMemoryResult, + }; + + pub mod region; +diff --git a/src/region.rs b/src/region.rs +index e716a6290e75..7114dfbe15a7 100644 +--- a/src/region.rs ++++ b/src/region.rs +@@ -3,8 +3,8 @@ + use crate::bitmap::{Bitmap, BS}; + use crate::guest_memory::Result; + use crate::{ +- Address, AtomicAccess, Bytes, FileOffset, GuestAddress, GuestMemory, GuestMemoryError, +- GuestUsize, MemoryRegionAddress, ReadVolatile, VolatileSlice, WriteVolatile, ++ Address, AtomicAccess, Bytes, FileOffset, GuestAddress, GuestMemory, GuestMemoryBytes, ++ GuestMemoryError, GuestUsize, MemoryRegionAddress, ReadVolatile, VolatileSlice, WriteVolatile, + }; + use std::sync::atomic::Ordering; + use std::sync::Arc; +@@ -322,6 +322,8 @@ impl<R: GuestMemoryRegion> GuestMemory for GuestRegionCollection<R> { + } + } + ++impl<R: GuestMemoryRegion> GuestMemoryBytes for GuestRegionCollection<R> {} ++ + /// A marker trait that if implemented on a type `R` makes available a default + /// implementation of `Bytes<MemoryRegionAddress>` for `R`, based on the assumption + /// that the entire `GuestMemoryRegion` is just traditional memory without any +-- +2.34.1 + diff --git a/subprojects/packagefiles/vm-memory-0.16-rs/0002.diff b/subprojects/packagefiles/vm-memory-0.16-rs/0002.diff new file mode 100644 index 000000000000..bfef1bf1fee3 --- /dev/null +++ b/subprojects/packagefiles/vm-memory-0.16-rs/0002.diff @@ -0,0 +1,111 @@ +From 2af7ea12a589fde619690e5060c01710cb6f2e0e Mon Sep 17 00:00:00 2001 +From: Zhao Liu <zhao1....@intel.com> +Date: Wed, 6 Aug 2025 14:27:14 +0800 +Subject: [PATCH 2/2] guest_memory: Add is_write argument for + GuestMemory::try_access() + +QEMU needs to know whether the memory access is for write or not, e.g., +memory region may be read-only, or iommu needs to distinguish write +access. + +The alternative option is to move try_access() into Bytes trait, and +implement Bytes<(GuestAddress, is_write)> for QEMU's GuestMemory +abstraction. However, try_access() seems to lack generality in the +abstraction of Bytes, as only GuestMemory needs it. + +Therefore, just add another argument in try_access() to help handle +more complex memory backend. + +Signed-off-by: Zhao Liu <zhao1....@intel.com> +--- + src/bitmap/mod.rs | 17 +++++++++++------ + src/guest_memory.rs | 10 ++++++---- + 2 files changed, 17 insertions(+), 10 deletions(-) + +diff --git a/src/bitmap/mod.rs b/src/bitmap/mod.rs +index cf1555b29350..de4203166304 100644 +--- a/src/bitmap/mod.rs ++++ b/src/bitmap/mod.rs +@@ -287,12 +287,17 @@ pub(crate) mod tests { + // Finally, let's invoke the generic tests for `Bytes`. + let check_range_closure = |m: &M, start: usize, len: usize, clean: bool| -> bool { + let mut check_result = true; +- m.try_access(len, GuestAddress(start as u64), |_, size, reg_addr, reg| { +- if !check_range(®.bitmap(), reg_addr.0 as usize, size, clean) { +- check_result = false; +- } +- Ok(size) +- }) ++ m.try_access( ++ len, ++ GuestAddress(start as u64), ++ false, ++ |_, size, reg_addr, reg| { ++ if !check_range(®.bitmap(), reg_addr.0 as usize, size, clean) { ++ check_result = false; ++ } ++ Ok(size) ++ }, ++ ) + .unwrap(); + + check_result +diff --git a/src/guest_memory.rs b/src/guest_memory.rs +index 5b78038c3c92..53981c4e8e94 100644 +--- a/src/guest_memory.rs ++++ b/src/guest_memory.rs +@@ -353,7 +353,7 @@ pub trait GuestMemory { + + /// Check whether the range [base, base + len) is valid. + fn check_range(&self, base: GuestAddress, len: usize) -> bool { +- match self.try_access(len, base, |_, count, _, _| -> Result<usize> { Ok(count) }) { ++ match self.try_access(len, base, false, |_, count, _, _| -> Result<usize> { Ok(count) }) { + Ok(count) => count == len, + _ => false, + } +@@ -374,7 +374,7 @@ pub trait GuestMemory { + /// - the error code returned by the callback 'f' + /// - the size of the already handled data when encountering the first hole + /// - the size of the already handled data when the whole range has been handled +- fn try_access<F>(&self, count: usize, addr: GuestAddress, mut f: F) -> Result<usize> ++ fn try_access<F>(&self, count: usize, addr: GuestAddress, _is_write: bool, mut f: F) -> Result<usize> + where + F: FnMut(usize, usize, MemoryRegionAddress, &Self::R) -> Result<usize>, + { +@@ -470,6 +470,7 @@ impl<M: GuestMemoryBytes + ?Sized> Bytes<GuestAddress> for M { + self.try_access( + buf.len(), + addr, ++ true, + |offset, _count, caddr, region| -> Result<usize> { + region.write(&buf[offset..], caddr) + }, +@@ -480,6 +481,7 @@ impl<M: GuestMemoryBytes + ?Sized> Bytes<GuestAddress> for M { + self.try_access( + buf.len(), + addr, ++ false, + |offset, _count, caddr, region| -> Result<usize> { + region.read(&mut buf[offset..], caddr) + }, +@@ -547,7 +549,7 @@ impl<M: GuestMemoryBytes + ?Sized> Bytes<GuestAddress> for M { + where + F: ReadVolatile, + { +- self.try_access(count, addr, |_, len, caddr, region| -> Result<usize> { ++ self.try_access(count, addr, false, |_, len, caddr, region| -> Result<usize> { + region.read_volatile_from(caddr, src, len) + }) + } +@@ -575,7 +577,7 @@ impl<M: GuestMemoryBytes + ?Sized> Bytes<GuestAddress> for M { + where + F: WriteVolatile, + { +- self.try_access(count, addr, |_, len, caddr, region| -> Result<usize> { ++ self.try_access(count, addr, true, |_, len, caddr, region| -> Result<usize> { + // For a non-RAM region, reading could have side effects, so we + // must use write_all(). + region.write_all_volatile_to(caddr, dst, len).map(|()| len) +-- +2.34.1 + diff --git a/subprojects/vm-memory-0.16-rs.wrap b/subprojects/vm-memory-0.16-rs.wrap index a057c8c9efc1..592271300294 100644 --- a/subprojects/vm-memory-0.16-rs.wrap +++ b/subprojects/vm-memory-0.16-rs.wrap @@ -8,5 +8,7 @@ revision = 5eb996a060d7ca3844cbd2f10b1d048c0c91942f patch_directory = vm-memory-0.16-rs depth = 1 +diff_files = vm-memory-0.16-rs/0001.diff, vm-memory-0.16-rs/0002.diff + # bump this version number on every change to meson.build or the patches: # v2 -- 2.34.1