From 2f4e96ce7618283dfab8246284d71807bcb5393c Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 7 Nov 2025 10:03:54 +0100 Subject: [PATCH 1/5] clippy: allow mut_from_ref The purpose of the function is exactly to change a pointer obtained from a mutable VolatileSlice into a reference, and doing so is unsafe. So just shut up clippy. Signed-off-by: Paolo Bonzini --- CHANGELOG.md | 4 ++++ src/volatile_memory.rs | 3 +++ 2 files changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c38b2710..7b5796f7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ - \[[#327](https://github.com/rust-vmm/vm-memory/pull/327)\] I/O virtual memory support via `IoMemory`, `IommuMemory`, and `Iommu`/`Iotlb` +### Fixed + +- \[[#361](https://github.com/rust-vmm/vm-memory/pull/361)\] clippy: allow mut_from_ref + ## \[v0.17.1\] No visible changes. diff --git a/src/volatile_memory.rs b/src/volatile_memory.rs index 15772cb1..c4a24ae7 100644 --- a/src/volatile_memory.rs +++ b/src/volatile_memory.rs @@ -228,6 +228,9 @@ pub trait VolatileMemory { /// /// If the resulting pointer is not aligned, this method will return an /// [`Error`](enum.Error.html). + // the function is unsafe, and the conversion is safe if following the safety + // instrutions above + #[allow(clippy::mut_from_ref)] unsafe fn aligned_as_mut(&self, offset: usize) -> Result<&mut T> { let slice = self.get_slice(offset, size_of::())?; slice.check_alignment(align_of::())?; From 8c359c3d87ce62005d6d799beb3204c80ecdc8a5 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 7 Nov 2025 10:27:54 +0100 Subject: [PATCH 2/5] The great rename Rename GuestMemory to GuestMemoryBackend, IoMemory to GuestMemory. This allows users of vm-memory to be aware of access permissions for memory, with no change to callers that just use the `Bytes` interface. Signed-off-by: Paolo Bonzini --- DESIGN.md | 22 ++++----- README.md | 4 +- benches/guest_memory.rs | 2 +- benches/mmap/mod.rs | 2 +- src/atomic.rs | 36 +++++++------- src/bitmap/mod.rs | 10 ++-- src/bytes.rs | 2 +- src/guest_memory.rs | 102 ++++++++++++++++++++-------------------- src/iommu.rs | 56 +++++++++++----------- src/lib.rs | 4 +- src/mmap/mod.rs | 6 +-- src/region.rs | 12 ++--- 12 files changed, 129 insertions(+), 129 deletions(-) diff --git a/DESIGN.md b/DESIGN.md index c3098d85..4ee859be 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -74,8 +74,8 @@ of the VM using the following traits: `u64` is used to store the the raw value no matter if it is a 32-bit or a 64-bit virtual machine. - `GuestMemoryRegion`: represents a continuous region of the VM memory. -- `GuestMemory`: represents a collection of `GuestMemoryRegion` objects. The - main responsibilities of the `GuestMemory` trait are: +- `GuestMemoryBackend`: represents a collection of `GuestMemoryRegion` objects. The + main responsibilities of the `GuestMemoryBackend` trait are: - hide the detail of accessing physical addresses (for example complex hierarchical structures). - map an address request to a `GuestMemoryRegion` object and relay the @@ -88,14 +88,14 @@ access VM's physical memory and not on the implementation of the traits. ### Backend Implementation Based on `mmap` -Provides an implementation of the `GuestMemory` trait by mmapping the VM's physical +Provides an implementation of the `GuestMemoryBackend` trait by mmapping the VM's physical memory into the current process. - `MmapRegion`: implementation of mmap a continuous range of physical memory with methods for accessing the mapped memory. - `GuestRegionMmap`: implementation of `GuestMemoryRegion` providing a wrapper used to map VM's physical address into a `(mmap_region, offset)` tuple. -- `GuestMemoryMmap`: implementation of `GuestMemory` that manages a collection +- `GuestMemoryMmap`: implementation of `GuestMemoryBackend` that manages a collection of `GuestRegionMmap` objects for a VM. One of the main responsibilities of `GuestMemoryMmap` is to handle the use @@ -127,18 +127,18 @@ let result = guest_memory_mmap.write(buf, addr); When using an IOMMU, there no longer is direct access to the guest (physical) address space, but instead only to I/O virtual address space. In this case: -- `IoMemory` replaces `GuestMemory`: It requires specifying the required access +- `GuestMemory` replaces `GuestMemoryBackend`: It requires specifying the required access permissions (which are relevant for virtual memory). It also removes interfaces that imply a mostly linear memory layout, because virtual memory is fragmented into many pages instead of few (large) memory regions. - - Any `IoMemory` still has a `GuestMemory` inside as the underlying address + - Any `GuestMemory` still has a `GuestMemoryBackend` inside as the underlying address space, but if an IOMMU is used, that will generally not be guest physical address space. With vhost-user, for example, it will be the VMM’s user address space instead. - - `IommuMemory` as our only actually IOMMU-supporting `IoMemory` + - `IommuMemory` as our only actually IOMMU-supporting `GuestMemory` implementation uses an `Iommu` object to translate I/O virtual addresses (IOVAs) into VMM user addresses (VUAs), which are then passed to the inner - `GuestMemory` implementation (like `GuestMemoryMmap`). + `GuestMemoryBackend` implementation (like `GuestMemoryMmap`). - `GuestAddress` (for compatibility) refers to an address in any of these address spaces: - Guest physical addresses (GPAs) when no IOMMU is used, @@ -166,8 +166,8 @@ with minor changes: - `Address` inherits `AddressValue` - `GuestMemoryRegion` inherits `Bytes`. The `Bytes` trait must be implemented. -- `GuestMemory` has a generic implementation of `IoMemory` -- `IoMemory` has a generic implementation of `Bytes`. +- `GuestMemoryBackend` has a generic implementation of `GuestMemory` +- `GuestMemory` has a generic implementation of `Bytes`. **Types**: @@ -178,6 +178,6 @@ with minor changes: - `MmapRegion` implements `VolatileMemory` - `GuestRegionMmap` implements `Bytes + GuestMemoryRegion` -- `GuestMemoryMmap` implements `GuestMemory` +- `GuestMemoryMmap` implements `GuestMemoryBackend` - `VolatileSlice` implements `Bytes + VolatileMemory` diff --git a/README.md b/README.md index b390cafd..544911b6 100644 --- a/README.md +++ b/README.md @@ -62,7 +62,7 @@ Then add `extern crate vm-memory;` to your crate root. ## Examples - Creating a VM physical memory object in hypervisor specific ways using the - `GuestMemoryMmap` implementation of the `GuestMemory` trait: + `GuestMemoryMmap` implementation of the `GuestMemoryBackend` trait: ```rust fn provide_mem_to_virt_dev() { @@ -77,7 +77,7 @@ fn provide_mem_to_virt_dev() { - Consumers accessing the VM's physical memory: ```rust -fn virt_device_io(mem: &T) { +fn virt_device_io(mem: &T) { let sample_buf = &[1, 2, 3, 4, 5]; assert_eq!(mem.write(sample_buf, GuestAddress(0xffc)).unwrap(), 5); let buf = &mut [0u8; 5]; diff --git a/benches/guest_memory.rs b/benches/guest_memory.rs index 4fdce1f5..e2e7d505 100644 --- a/benches/guest_memory.rs +++ b/benches/guest_memory.rs @@ -7,7 +7,7 @@ use core::hint::black_box; pub use criterion::Criterion; use vm_memory::bitmap::Bitmap; -use vm_memory::{GuestAddress, GuestMemory, GuestMemoryMmap}; +use vm_memory::{GuestAddress, GuestMemoryBackend, GuestMemoryMmap}; const REGION_SIZE: usize = 0x10_0000; const REGIONS_COUNT: u64 = 256; diff --git a/benches/mmap/mod.rs b/benches/mmap/mod.rs index 4fdb8001..2b38dceb 100644 --- a/benches/mmap/mod.rs +++ b/benches/mmap/mod.rs @@ -17,7 +17,7 @@ use std::path::Path; use core::hint::black_box; use criterion::Criterion; -use vm_memory::{ByteValued, Bytes, GuestAddress, GuestMemory}; +use vm_memory::{ByteValued, Bytes, GuestAddress, GuestMemoryBackend}; const REGION_SIZE: usize = 0x8000_0000; const REGIONS_COUNT: u64 = 8; diff --git a/src/atomic.rs b/src/atomic.rs index 9ea4abb4..56f15391 100644 --- a/src/atomic.rs +++ b/src/atomic.rs @@ -2,7 +2,7 @@ // Copyright (C) 2020 Red Hat, Inc. All rights reserved. // SPDX-License-Identifier: Apache-2.0 -//! A wrapper over an `ArcSwap` struct to support RCU-style mutability. +//! A wrapper over an `ArcSwap` struct to support RCU-style mutability. //! //! With the `backend-atomic` feature enabled, simply replacing `GuestMemoryMmap` //! with `GuestMemoryAtomic` will enable support for mutable memory maps. @@ -15,17 +15,17 @@ use arc_swap::{ArcSwap, Guard}; use std::ops::Deref; use std::sync::{Arc, LockResult, Mutex, MutexGuard, PoisonError}; -use crate::{GuestAddressSpace, IoMemory}; +use crate::{GuestAddressSpace, GuestMemory}; /// A fast implementation of a mutable collection of memory regions. /// /// This implementation uses `ArcSwap` to provide RCU-like snapshotting of the memory map: -/// every update of the memory map creates a completely new `IoMemory` object, and +/// every update of the memory map creates a completely new `GuestMemory` object, and /// readers will not be blocked because the copies they retrieved will be collected once /// no one can access them anymore. Under the assumption that updates to the memory map /// are rare, this allows a very efficient implementation of the `memory()` method. #[derive(Debug)] -pub struct GuestMemoryAtomic { +pub struct GuestMemoryAtomic { // GuestAddressSpace, which we want to implement, is basically a drop-in // replacement for &M. Therefore, we need to pass to devices the `GuestMemoryAtomic` // rather than a reference to it. To obtain this effect we wrap the actual fields @@ -34,9 +34,9 @@ pub struct GuestMemoryAtomic { inner: Arc<(ArcSwap, Mutex<()>)>, } -impl From> for GuestMemoryAtomic { +impl From> for GuestMemoryAtomic { /// create a new `GuestMemoryAtomic` object whose initial contents come from - /// the `map` reference counted `IoMemory`. + /// the `map` reference counted `GuestMemory`. fn from(map: Arc) -> Self { let inner = (ArcSwap::new(map), Mutex::new(())); GuestMemoryAtomic { @@ -45,9 +45,9 @@ impl From> for GuestMemoryAtomic { } } -impl GuestMemoryAtomic { +impl GuestMemoryAtomic { /// create a new `GuestMemoryAtomic` object whose initial contents come from - /// the `map` `IoMemory`. + /// the `map` `GuestMemory`. pub fn new(map: M) -> Self { Arc::new(map).into() } @@ -75,7 +75,7 @@ impl GuestMemoryAtomic { } } -impl Clone for GuestMemoryAtomic { +impl Clone for GuestMemoryAtomic { fn clone(&self) -> Self { Self { inner: self.inner.clone(), @@ -83,7 +83,7 @@ impl Clone for GuestMemoryAtomic { } } -impl GuestAddressSpace for GuestMemoryAtomic { +impl GuestAddressSpace for GuestMemoryAtomic { type T = GuestMemoryLoadGuard; type M = M; @@ -94,14 +94,14 @@ impl GuestAddressSpace for GuestMemoryAtomic { /// A guard that provides temporary access to a `GuestMemoryAtomic`. This /// object is returned from the `memory()` method. It dereference to -/// a snapshot of the `IoMemory`, so it can be used transparently to +/// a snapshot of the `GuestMemory`, so it can be used transparently to /// access memory. #[derive(Debug)] -pub struct GuestMemoryLoadGuard { +pub struct GuestMemoryLoadGuard { guard: Guard>, } -impl GuestMemoryLoadGuard { +impl GuestMemoryLoadGuard { /// Make a clone of the held pointer and returns it. This is more /// expensive than just using the snapshot, but it allows to hold on /// to the snapshot outside the scope of the guard. It also allows @@ -112,7 +112,7 @@ impl GuestMemoryLoadGuard { } } -impl Clone for GuestMemoryLoadGuard { +impl Clone for GuestMemoryLoadGuard { fn clone(&self) -> Self { GuestMemoryLoadGuard { guard: Guard::from_inner(Arc::clone(&*self.guard)), @@ -120,7 +120,7 @@ impl Clone for GuestMemoryLoadGuard { } } -impl Deref for GuestMemoryLoadGuard { +impl Deref for GuestMemoryLoadGuard { type Target = M; fn deref(&self) -> &Self::Target { @@ -133,12 +133,12 @@ impl Deref for GuestMemoryLoadGuard { /// possibly after updating the memory map represented by the /// `GuestMemoryAtomic` that created the guard. #[derive(Debug)] -pub struct GuestMemoryExclusiveGuard<'a, M: IoMemory> { +pub struct GuestMemoryExclusiveGuard<'a, M: GuestMemory> { parent: &'a GuestMemoryAtomic, _guard: MutexGuard<'a, ()>, } -impl GuestMemoryExclusiveGuard<'_, M> { +impl GuestMemoryExclusiveGuard<'_, M> { /// Replace the memory map in the `GuestMemoryAtomic` that created the guard /// with the new memory map, `map`. The lock is then dropped since this /// method consumes the guard. @@ -151,7 +151,7 @@ impl GuestMemoryExclusiveGuard<'_, M> { mod tests { use super::*; use crate::region::tests::{new_guest_memory_collection_from_regions, Collection, MockRegion}; - use crate::{GuestAddress, GuestMemory, GuestMemoryRegion, GuestUsize, IoMemory}; + use crate::{GuestAddress, GuestMemoryBackend, GuestMemoryRegion, GuestUsize, GuestMemory}; type GuestMemoryMmapAtomic = GuestMemoryAtomic; diff --git a/src/bitmap/mod.rs b/src/bitmap/mod.rs index d4e3942c..860f25b2 100644 --- a/src/bitmap/mod.rs +++ b/src/bitmap/mod.rs @@ -4,14 +4,14 @@ //! This module holds abstractions that enable tracking the areas dirtied by writes of a specified //! length to a given offset. In particular, this is used to track write accesses within a //! `GuestMemoryRegion` object, and the resulting bitmaps can then be aggregated to build the -//! global view for an entire `GuestMemory` object. +//! global view for an entire `GuestMemoryBackend` object. #[cfg(feature = "backend-bitmap")] mod backend; use std::fmt::Debug; -use crate::{GuestMemory, GuestMemoryRegion}; +use crate::{GuestMemoryBackend, GuestMemoryRegion}; #[cfg(feature = "backend-bitmap")] pub use backend::{ArcSlice, AtomicBitmap, RefSlice}; @@ -113,8 +113,8 @@ impl Bitmap for Option { pub type BS<'a, B> = >::S; /// Helper type alias for referring to the `BitmapSlice` concrete type associated with -/// the memory regions of an object `M: GuestMemory`. -pub type MS<'a, M> = BS<'a, <::R as GuestMemoryRegion>::B>; +/// the memory regions of an object `M: GuestMemoryBackend`. +pub type MS<'a, M> = BS<'a, <::R as GuestMemoryRegion>::B>; #[cfg(test)] #[cfg(feature = "backend-bitmap")] @@ -257,7 +257,7 @@ pub(crate) mod tests { // Assumptions about M generated by f ... pub fn test_guest_memory_and_region(f: F) where - M: GuestMemory, + M: GuestMemoryBackend, F: Fn() -> M, { let m = f(); diff --git a/src/bytes.rs b/src/bytes.rs index 9c0eca9f..dc92a05f 100644 --- a/src/bytes.rs +++ b/src/bytes.rs @@ -333,7 +333,7 @@ pub trait Bytes { /// ``` /// # #[cfg(all(feature = "backend-mmap", feature = "rawfd"))] /// # { - /// # use vm_memory::{Address, GuestMemory, Bytes, GuestAddress, GuestMemoryMmap}; + /// # use vm_memory::{Address, GuestMemoryBackend, Bytes, GuestAddress, GuestMemoryMmap}; /// # use std::fs::File; /// # use std::path::Path; /// # diff --git a/src/guest_memory.rs b/src/guest_memory.rs index 219b9d00..6e9ce525 100644 --- a/src/guest_memory.rs +++ b/src/guest_memory.rs @@ -22,23 +22,23 @@ //! region. //! - [`GuestMemoryRegion`](trait.GuestMemoryRegion.html): represent a continuous region of guest's //! physical memory. -//! - [`GuestMemory`](trait.GuestMemory.html): represent a collection of `GuestMemoryRegion` +//! - [`GuestMemoryBackend`](trait.GuestMemory.html): represent a collection of `GuestMemoryRegion` //! objects. -//! The main responsibilities of the `GuestMemory` trait are: +//! The main responsibilities of the `GuestMemoryBackend` trait are: //! - hide the detail of accessing guest's physical address. //! - map a request address to a `GuestMemoryRegion` object and relay the request to it. //! - handle cases where an access request spanning two or more `GuestMemoryRegion` objects. //! //! Whenever a collection of `GuestMemoryRegion` objects is mutable, //! [`GuestAddressSpace`](trait.GuestAddressSpace.html) should be implemented -//! for clients to obtain a [`GuestMemory`] reference or smart pointer. +//! for clients to obtain a [`GuestMemoryBackend`] reference or smart pointer. //! //! The `GuestMemoryRegion` trait has an associated `B: Bitmap` type which is used to handle //! dirty bitmap tracking. Backends are free to define the granularity (or whether tracking is //! actually performed at all). Those that do implement tracking functionality are expected to //! ensure the correctness of the underlying `Bytes` implementation. The user has to explicitly //! record (using the handle returned by `GuestRegionMmap::bitmap`) write accesses performed -//! via pointers, references, or slices returned by methods of `GuestMemory`,`GuestMemoryRegion`, +//! via pointers, references, or slices returned by methods of `GuestMemoryBackend`,`GuestMemoryRegion`, //! `VolatileSlice`, `VolatileRef`, or `VolatileArrayRef`. use std::convert::From; @@ -167,9 +167,9 @@ impl FileOffset { } } -/// `GuestAddressSpace` provides a way to retrieve a `GuestMemory` object. +/// `GuestAddressSpace` provides a way to retrieve a `GuestMemoryBackend` object. /// The vm-memory crate already provides trivial implementation for -/// references to `GuestMemory` or reference-counted `GuestMemory` objects, +/// references to `GuestMemoryBackend` or reference-counted `GuestMemory` objects, /// but the trait can also be implemented by any other struct in order /// to provide temporary access to a snapshot of the memory map. /// @@ -185,7 +185,7 @@ impl FileOffset { /// # #[cfg(feature = "backend-mmap")] /// # { /// # use std::sync::Arc; -/// # use vm_memory::{GuestAddress, GuestAddressSpace, GuestMemory, GuestMemoryMmap}; +/// # use vm_memory::{GuestAddress, GuestAddressSpace, GuestMemoryBackend, GuestMemoryMmap}; /// # /// pub struct VirtioDevice { /// mem: Option, @@ -229,7 +229,7 @@ impl FileOffset { /// ``` pub trait GuestAddressSpace: Clone { /// The type that will be used to access guest memory. - type M: IoMemory; + type M: GuestMemory; /// A type that provides access to the memory. type T: Clone + Deref; @@ -240,7 +240,7 @@ pub trait GuestAddressSpace: Clone { fn memory(&self) -> Self::T; } -impl GuestAddressSpace for &M { +impl GuestAddressSpace for &M { type M = M; type T = Self; @@ -249,7 +249,7 @@ impl GuestAddressSpace for &M { } } -impl GuestAddressSpace for Rc { +impl GuestAddressSpace for Rc { type M = M; type T = Self; @@ -258,7 +258,7 @@ impl GuestAddressSpace for Rc { } } -impl GuestAddressSpace for Arc { +impl GuestAddressSpace for Arc { type M = M; type T = Self; @@ -267,16 +267,16 @@ impl GuestAddressSpace for Arc { } } -/// `GuestMemory` represents a container for an *immutable* collection of -/// `GuestMemoryRegion` objects. `GuestMemory` provides the `Bytes` +/// `GuestMemoryBackend` represents a container for an *immutable* collection of +/// `GuestMemoryRegion` objects. `GuestMemoryBackend` provides the `Bytes` /// trait to hide the details of accessing guest memory by physical address. -/// Interior mutability is not allowed for implementations of `GuestMemory` so +/// Interior mutability is not allowed for implementations of `GuestMemoryBackend` so /// that they always provide a consistent view of the memory map. /// -/// The task of the `GuestMemory` trait are: +/// The task of the `GuestMemoryBackend` trait are: /// - map a request address to a `GuestMemoryRegion` object and relay the request to it. /// - handle cases where an access request spanning two or more `GuestMemoryRegion` objects. -pub trait GuestMemory { +pub trait GuestMemoryBackend { /// Type of objects hosted by the address space. type R: GuestMemoryRegion; @@ -302,7 +302,7 @@ pub trait GuestMemory { /// ``` /// # #[cfg(feature = "backend-mmap")] /// # { - /// # use vm_memory::{GuestAddress, GuestMemory, GuestMemoryRegion, GuestMemoryMmap}; + /// # use vm_memory::{GuestAddress, GuestMemoryBackend, GuestMemoryRegion, GuestMemoryMmap}; /// # /// let start_addr1 = GuestAddress(0x0); /// let start_addr2 = GuestAddress(0x400); @@ -319,14 +319,14 @@ pub trait GuestMemory { fn iter(&self) -> impl Iterator; /// Returns the maximum (inclusive) address managed by the - /// [`GuestMemory`](trait.GuestMemory.html). + /// [`GuestMemoryBackend`](trait.GuestMemory.html). /// /// # Examples (uses the `backend-mmap` feature) /// /// ``` /// # #[cfg(feature = "backend-mmap")] /// # { - /// # use vm_memory::{Address, GuestAddress, GuestMemory, GuestMemoryMmap}; + /// # use vm_memory::{Address, GuestAddress, GuestMemoryBackend, GuestMemoryMmap}; /// # /// let start_addr = GuestAddress(0x1000); /// let mut gm = GuestMemoryMmap::<()>::from_ranges(&vec![(start_addr, 0x400)]) @@ -376,7 +376,7 @@ pub trait GuestMemory { /// /// The address range `[addr, addr + count)` may span more than one /// [`GuestMemoryRegion`](trait.GuestMemoryRegion.html) object, or even have holes in it. - /// So [`try_access()`](trait.GuestMemory.html#method.try_access) invokes the callback 'f' + /// So [`try_access()`](trait.GuestMemoryBackend.html#method.try_access) invokes the callback 'f' /// for each [`GuestMemoryRegion`](trait.GuestMemoryRegion.html) object involved and returns: /// - the error code returned by the callback 'f' /// - the size of the already handled data when encountering the first hole @@ -423,7 +423,7 @@ pub trait GuestMemory { /// Get the host virtual address corresponding to the guest address. /// - /// Some [`GuestMemory`](trait.GuestMemory.html) implementations, like `GuestMemoryMmap`, + /// Some [`GuestMemoryBackend`](trait.GuestMemory.html) implementations, like `GuestMemoryMmap`, /// have the capability to mmap the guest address range into virtual address space of the host /// for direct access, so the corresponding host virtual address may be passed to other /// subsystems. @@ -441,7 +441,7 @@ pub trait GuestMemory { /// ``` /// # #[cfg(feature = "backend-mmap")] /// # { - /// # use vm_memory::{GuestAddress, GuestMemory, GuestMemoryMmap}; + /// # use vm_memory::{GuestAddress, GuestMemoryBackend, GuestMemoryMmap}; /// # /// # let start_addr = GuestAddress(0x1000); /// # let mut gm = GuestMemoryMmap::<()>::from_ranges(&vec![(start_addr, 0x500)]) @@ -495,9 +495,9 @@ pub trait GuestMemory { /// Iterates over [`VolatileSlice`]s that together form a guest memory area. /// -/// Returned by [`GuestMemory::get_slices()`]. +/// Returned by [`GuestMemoryBackend::get_slices()`]. #[derive(Debug)] -pub struct GuestMemorySliceIterator<'a, M: GuestMemory + ?Sized> { +pub struct GuestMemorySliceIterator<'a, M: GuestMemoryBackend + ?Sized> { /// Underlying memory mem: &'a M, /// Next address in the guest memory area @@ -506,7 +506,7 @@ pub struct GuestMemorySliceIterator<'a, M: GuestMemory + ?Sized> { count: usize, } -impl<'a, M: GuestMemory + ?Sized> GuestMemorySliceIterator<'a, M> { +impl<'a, M: GuestMemoryBackend + ?Sized> GuestMemorySliceIterator<'a, M> { /// Helper function for [`::next()`](GuestMemorySliceIterator::next). /// /// Get the next slice (i.e. the one starting from `self.addr` with a length up to @@ -555,7 +555,7 @@ impl<'a, M: GuestMemory + ?Sized> GuestMemorySliceIterator<'a, M> { } } -impl<'a, M: GuestMemory + ?Sized> Iterator for GuestMemorySliceIterator<'a, M> { +impl<'a, M: GuestMemoryBackend + ?Sized> Iterator for GuestMemorySliceIterator<'a, M> { type Item = Result>>; fn next(&mut self) -> Option { @@ -572,7 +572,7 @@ impl<'a, M: GuestMemory + ?Sized> Iterator for GuestMemorySliceIterator<'a, M> { } } -impl<'a, M: GuestMemory + ?Sized> IoMemorySliceIterator<'a, MS<'a, M>> +impl<'a, M: GuestMemoryBackend + ?Sized> IoMemorySliceIterator<'a, MS<'a, M>> for GuestMemorySliceIterator<'a, M> { } @@ -581,14 +581,14 @@ impl<'a, M: GuestMemory + ?Sized> IoMemorySliceIterator<'a, MS<'a, M>> /// /// [`::next()`](GuestMemorySliceIterator::next) sets `self.count` to 0 when /// returning `None`, ensuring that it will only return `None` from that point on. -impl FusedIterator for GuestMemorySliceIterator<'_, M> {} +impl FusedIterator for GuestMemorySliceIterator<'_, M> {} -/// Allow accessing [`IoMemory`] (and [`GuestMemory`]) objects via [`Bytes`]. +/// Allow accessing [`GuestMemory`] (and [`GuestMemoryBackend`]) objects via [`Bytes`]. /// -/// Thanks to the [blanket implementation of `IoMemory` for all `GuestMemory` -/// types](../io_memory/trait.IoMemory.html#impl-IoMemory-for-M), this blanket implementation -/// extends to all [`GuestMemory`] types. -impl Bytes for T { +/// Thanks to the [blanket implementation of `GuestMemory` for all `GuestMemoryBackend` +/// types](../io_memory/trait.GuestMemory.html#impl-IoMemory-for-M), this blanket implementation +/// extends to all [`GuestMemoryBackend`] types. +impl Bytes for T { type E = Error; fn write(&self, buf: &[u8], addr: GuestAddress) -> Result { @@ -802,19 +802,19 @@ impl std::ops::BitAnd for Permissions { /// Represents virtual I/O memory. /// -/// `IoMemory` is generally backed by some “physical” `GuestMemory`, which then consists for +/// `GuestMemory` is generally backed by some “physical” `GuestMemoryBackend`, which then consists for /// `GuestMemoryRegion` objects. However, the mapping from I/O virtual addresses (IOVAs) to /// physical addresses may be arbitrarily fragmented. Translation is done via an IOMMU. /// -/// Note in contrast to `GuestMemory`: +/// Note in contrast to `GuestMemoryBackend`: /// - Any IOVA range may consist of arbitrarily many underlying ranges in physical memory. /// - Accessing an IOVA requires passing the intended access mode, and the IOMMU will check whether /// the given access mode is permitted for the given IOVA. /// - The translation result for a given IOVA may change over time (i.e. the physical address /// associated with an IOVA may change). -pub trait IoMemory { - /// Underlying `GuestMemory` type. - type PhysicalMemory: GuestMemory + ?Sized; +pub trait GuestMemory { + /// Underlying `GuestMemoryBackend` type. + type PhysicalMemory: GuestMemoryBackend + ?Sized; /// Dirty bitmap type for tracking writes to the IOVA address space. type Bitmap: Bitmap; @@ -841,8 +841,8 @@ pub trait IoMemory { access: Permissions, ) -> Result>>; - /// If this virtual memory is just a plain `GuestMemory` object underneath without an IOMMU - /// translation layer in between, return that `GuestMemory` object. + /// If this virtual memory is just a plain `GuestMemoryBackend` object underneath without an IOMMU + /// translation layer in between, return that `GuestMemoryBackend` object. fn physical_memory(&self) -> Option<&Self::PhysicalMemory> { None } @@ -850,7 +850,7 @@ pub trait IoMemory { /// Iterates over [`VolatileSlice`]s that together form an I/O memory area. /// -/// Returned by [`IoMemory::get_slices()`]. +/// Returned by [`GuestMemory::get_slices()`]. pub trait IoMemorySliceIterator<'a, B: BitmapSlice>: Iterator>> + FusedIterator + Sized { @@ -866,22 +866,22 @@ pub trait IoMemorySliceIterator<'a, B: BitmapSlice>: } } -/// Allow accessing every [`GuestMemory`] via [`IoMemory`]. +/// Allow accessing every [`GuestMemoryBackend`] via [`GuestMemory`]. /// -/// [`IoMemory`] is a generalization of [`GuestMemory`]: Every object implementing the former is a -/// subset of an object implementing the latter (there always is an underlying [`GuestMemory`]), +/// [`GuestMemory`] is a generalization of [`GuestMemoryBackend`]: Every object implementing the former is a +/// subset of an object implementing the latter (there always is an underlying [`GuestMemoryBackend`]), /// with an opaque internal mapping on top, e.g. provided by an IOMMU. /// -/// Every [`GuestMemory`] is therefore trivially also an [`IoMemory`], assuming a complete identity +/// Every [`GuestMemoryBackend`] is therefore trivially also an [`GuestMemory`], assuming a complete identity /// mapping (which we must assume, so that accessing such objects via either trait will yield the -/// same result): Basically, all [`IoMemory`] methods are implemented as trivial wrappers around -/// the same [`GuestMemory`] methods (if available), discarding the `access` parameter. -impl IoMemory for M { +/// same result): Basically, all [`GuestMemory`] methods are implemented as trivial wrappers around +/// the same [`GuestMemoryBackend`] methods (if available), discarding the `access` parameter. +impl GuestMemory for M { type PhysicalMemory = M; type Bitmap = ::B; fn check_range(&self, addr: GuestAddress, count: usize, _access: Permissions) -> bool { - ::check_range(self, addr, count) + ::check_range(self, addr, count) } fn get_slices<'a>( @@ -890,7 +890,7 @@ impl IoMemory for M { count: usize, _access: Permissions, ) -> Result>> { - Ok(::get_slices(self, addr, count)) + Ok(::get_slices(self, addr, count)) } fn physical_memory(&self) -> Option<&Self::PhysicalMemory> { @@ -902,7 +902,7 @@ impl IoMemory for M { mod tests { #![allow(clippy::undocumented_unsafe_blocks)] - // Note that `IoMemory` is tested primarily in src/iommu.rs via `IommuMemory`. + // Note that `GuestMemory` is tested primarily in src/iommu.rs via `IommuMemory`. use super::*; #[cfg(feature = "backend-mmap")] diff --git a/src/iommu.rs b/src/iommu.rs index d2c2bbf2..81abc14f 100644 --- a/src/iommu.rs +++ b/src/iommu.rs @@ -18,7 +18,7 @@ use crate::guest_memory::{ Result as GuestMemoryResult, }; use crate::{ - Address, GuestAddress, GuestMemory, GuestMemoryRegion, GuestUsize, IoMemory, Permissions, + Address, GuestAddress, GuestMemoryBackend, GuestMemoryRegion, GuestUsize, GuestMemory, Permissions, VolatileSlice, }; use rangemap::RangeMap; @@ -182,25 +182,25 @@ pub struct IotlbFails { pub access_fails: Vec, } -/// [`IoMemory`] type that consists of an underlying [`GuestMemory`] object plus an [`Iommu`]. +/// [`GuestMemory`] type that consists of an underlying [`GuestMemoryBackend`] object plus an [`Iommu`]. /// -/// The underlying [`GuestMemory`] is basically the physical memory, and the [`Iommu`] translates +/// The underlying [`GuestMemoryBackend`] is basically the physical memory, and the [`Iommu`] translates /// the I/O virtual address space that `IommuMemory` provides into that underlying physical address /// space. /// /// Note that this type’s implementation of memory write tracking (“logging”) is specific to what /// is required by vhost-user: /// - When the IOMMU is disabled ([`IommuMemory::set_iommu_enabled()`]), writes to memory are -/// tracked by the underlying [`GuestMemory`] in its bitmap(s). +/// tracked by the underlying [`GuestMemoryBackend`] in its bitmap(s). /// - When it is enabled, they are instead tracked in the [`IommuMemory`]’s dirty bitmap; the /// offset in the bitmap is calculated from the write’s IOVA. /// -/// That is, there are two bitmap levels, one in the underlying [`GuestMemory`], and one in +/// That is, there are two bitmap levels, one in the underlying [`GuestMemoryBackend`], and one in /// [`IommuMemory`]. The former is used when the IOMMU is disabled, the latter when it is enabled. /// -/// If you need a different model (e.g. always use the [`GuestMemory`] bitmaps), you should not use +/// If you need a different model (e.g. always use the [`GuestMemoryBackend`] bitmaps), you should not use /// this type. -pub struct IommuMemory { +pub struct IommuMemory { /// Physical memory backend: M, /// IOMMU to translate IOVAs into physical addresses @@ -371,9 +371,9 @@ impl TryFrom> for IovaRange { } } -impl IommuMemory { +impl IommuMemory { /// Create a new `IommuMemory` instance. - pub fn new(backend: M, iommu: I, use_iommu: bool, bitmap: ::Bitmap) -> Self { + pub fn new(backend: M, iommu: I, use_iommu: bool, bitmap: ::Bitmap) -> Self { IommuMemory { backend, iommu: Arc::new(iommu), @@ -399,7 +399,7 @@ impl IommuMemory { /// Return a reference to the IOVA address space's dirty bitmap. /// /// This bitmap tracks write accesses done while the IOMMU is enabled. - pub fn bitmap(&self) -> &Arc<::Bitmap> { + pub fn bitmap(&self) -> &Arc<::Bitmap> { &self.bitmap } @@ -430,7 +430,7 @@ impl IommuMemory { } } -impl Clone for IommuMemory { +impl Clone for IommuMemory { fn clone(&self) -> Self { IommuMemory { backend: self.backend.clone(), @@ -441,7 +441,7 @@ impl Clone for IommuMemory { } } -impl Debug for IommuMemory +impl Debug for IommuMemory where ::B: Debug, { @@ -455,7 +455,7 @@ where } } -impl Default for IommuMemory +impl Default for IommuMemory where ::B: Default, { @@ -469,7 +469,7 @@ where } } -impl IoMemory for IommuMemory { +impl GuestMemory for IommuMemory { type PhysicalMemory = M; type Bitmap = ::B; @@ -512,7 +512,7 @@ impl IoMemory for IommuMemory { /// Iterates over [`VolatileSlice`]s that together form an area in an `IommuMemory`. /// /// Returned by [`IommuMemory::get_slices()`] -pub struct IommuMemorySliceIterator<'a, M: GuestMemory, I: Iommu + 'a> { +pub struct IommuMemorySliceIterator<'a, M: GuestMemoryBackend, I: Iommu + 'a> { /// Current IOVA (needed to access the right slice of the IOVA space dirty bitmap) iova: GuestAddress, /// IOVA space dirty bitmap @@ -525,11 +525,11 @@ pub struct IommuMemorySliceIterator<'a, M: GuestMemory, I: Iommu + 'a> { current_translated_iter: Option>, } -impl<'a, M: GuestMemory, I: Iommu> IommuMemorySliceIterator<'a, M, I> { +impl<'a, M: GuestMemoryBackend, I: Iommu> IommuMemorySliceIterator<'a, M, I> { /// Create an iterator over the physical region `[addr, addr + count)`. /// /// “Physical” means that the IOMMU is not used to translate this address range. The resulting - /// iterator is effectively the same as would be returned by [`GuestMemory::get_slices()`] on + /// iterator is effectively the same as would be returned by [`GuestMemoryBackend::get_slices()`] on /// the underlying physical memory for the given address range. fn phys(mem: &'a IommuMemory, addr: GuestAddress, count: usize) -> Self { IommuMemorySliceIterator { @@ -544,7 +544,7 @@ impl<'a, M: GuestMemory, I: Iommu> IommuMemorySliceIterator<'a, M, I> { /// Create an iterator over the IOVA region `[addr, addr + count)`. /// /// This address range is translated using the IOMMU, and the resulting mappings are then - /// separately visited via [`GuestMemory::get_slices()`]. + /// separately visited via [`GuestMemoryBackend::get_slices()`]. fn virt( mem: &'a IommuMemory, addr: GuestAddress, @@ -613,7 +613,7 @@ impl<'a, M: GuestMemory, I: Iommu> IommuMemorySliceIterator<'a, M, I> { } } -impl<'a, M: GuestMemory, I: Iommu> Iterator for IommuMemorySliceIterator<'a, M, I> { +impl<'a, M: GuestMemoryBackend, I: Iommu> Iterator for IommuMemorySliceIterator<'a, M, I> { type Item = GuestMemoryResult>>; fn next(&mut self) -> Option { @@ -636,14 +636,14 @@ impl<'a, M: GuestMemory, I: Iommu> Iterator for IommuMemorySliceIterator<'a, M, /// [`::next()`](IommuMemorySliceIterator::next) sets both /// `self.current_translated_iter` and `self.translation` to `None` when returning anything but /// `Some(Ok(_))`, ensuring that it will only return `None` from that point on. -impl FusedIterator for IommuMemorySliceIterator<'_, M, I> {} +impl FusedIterator for IommuMemorySliceIterator<'_, M, I> {} -impl<'a, M: GuestMemory, I: Iommu> IoMemorySliceIterator<'a, bitmap::MS<'a, M>> +impl<'a, M: GuestMemoryBackend, I: Iommu> IoMemorySliceIterator<'a, bitmap::MS<'a, M>> for IommuMemorySliceIterator<'a, M, I> { } -impl<'a, M: GuestMemory + Debug, I: Iommu> Debug for IommuMemorySliceIterator<'a, M, I> +impl<'a, M: GuestMemoryBackend + Debug, I: Iommu> Debug for IommuMemorySliceIterator<'a, M, I> where I::IotlbGuard<'a>: Debug, ::B: Debug, @@ -670,7 +670,7 @@ mod tests { use crate::GuestMemoryRegion; #[cfg(feature = "backend-mmap")] use crate::{ - Bytes, GuestMemoryError, GuestMemoryMmap, GuestMemoryResult, IoMemory, IommuMemory, + Bytes, GuestMemoryError, GuestMemoryMmap, GuestMemoryResult, GuestMemory, IommuMemory, }; use crate::{GuestAddress, Iommu, Iotlb, Permissions}; use std::fmt::Debug; @@ -1146,7 +1146,7 @@ mod tests { /// Return an error if mapping fails, but just panic if there is a content mismatch. #[cfg(feature = "backend-mmap")] fn check_virt_mem_content( - mem: &impl IoMemory, + mem: &impl GuestMemory, start: GuestAddress, len: usize, value_offset: u8, @@ -1169,7 +1169,7 @@ mod tests { #[cfg(feature = "backend-mmap")] fn verify_virt_mem_content( - m: &impl IoMemory, + m: &impl GuestMemory, start: GuestAddress, len: usize, value_offset: u8, @@ -1184,7 +1184,7 @@ mod tests { /// starting at `fail_start` (i.e. `start + len - fail_start`). #[cfg(feature = "backend-mmap")] fn verify_virt_mem_error( - m: &impl IoMemory, + m: &impl GuestMemory, start: GuestAddress, len: usize, fail_start: Option, @@ -1408,11 +1408,11 @@ mod tests { /// In `mem`'s dirty bitmap, verify that the given `clean` addresses are clean, and the `dirty` /// addresses are dirty. Auto-clear the dirty addresses checked. /// - /// Cannot import `GuestMemory` in this module, as that would interfere with `IoMemory` for + /// Cannot import `GuestMemoryBackend` in this module, as that would interfere with `GuestMemory` for /// methods that have the same name between the two. #[cfg(all(feature = "backend-bitmap", feature = "backend-mmap"))] fn verify_mem_bitmap< - M: crate::GuestMemory, + M: crate::GuestMemoryBackend, R: GuestMemoryRegion, I: Iommu, >( diff --git a/src/lib.rs b/src/lib.rs index bfe47ce6..cb576b92 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -52,8 +52,8 @@ 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, IoMemory, MemoryRegionAddress, Permissions, Result as GuestMemoryResult, + Error as GuestMemoryError, FileOffset, GuestAddress, GuestAddressSpace, GuestMemoryBackend, + GuestUsize, GuestMemory, MemoryRegionAddress, Permissions, Result as GuestMemoryResult, }; pub mod region; diff --git a/src/mmap/mod.rs b/src/mmap/mod.rs index 3739b2ec..75ae7d5c 100644 --- a/src/mmap/mod.rs +++ b/src/mmap/mod.rs @@ -8,7 +8,7 @@ // // SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause -//! The default implementation for the [`GuestMemory`](trait.GuestMemory.html) trait. +//! The default implementation for the [`GuestMemoryBackend`](trait.GuestMemory.html) trait. //! //! This implementation is mmap-ing the memory of the guest into the current process. @@ -179,7 +179,7 @@ impl GuestMemoryRegion for GuestRegionMmap { impl GuestMemoryRegionBytes for GuestRegionMmap {} -/// [`GuestMemory`](trait.GuestMemory.html) implementation that mmaps the guest's memory +/// [`GuestMemoryBackend`](trait.GuestMemory.html) implementation that mmaps the guest's memory /// in the current process. /// /// Represents the entire physical memory of the guest by tracking all its memory regions. @@ -239,7 +239,7 @@ mod tests { #[cfg(feature = "backend-bitmap")] use crate::bitmap::AtomicBitmap; - use crate::{Bytes, GuestMemory, GuestMemoryError}; + use crate::{Bytes, GuestMemoryBackend, GuestMemoryError}; use std::io::Write; #[cfg(feature = "rawfd")] diff --git a/src/region.rs b/src/region.rs index 565a14c0..764ce460 100644 --- a/src/region.rs +++ b/src/region.rs @@ -3,7 +3,7 @@ use crate::bitmap::{Bitmap, BS}; use crate::guest_memory::Result; use crate::{ - Address, AtomicAccess, Bytes, FileOffset, GuestAddress, GuestMemory, GuestMemoryError, + Address, AtomicAccess, Bytes, FileOffset, GuestAddress, GuestMemoryBackend, GuestMemoryError, GuestUsize, MemoryRegionAddress, ReadVolatile, VolatileSlice, WriteVolatile, }; use std::sync::atomic::Ordering; @@ -91,7 +91,7 @@ pub trait GuestMemoryRegion: Bytes { /// Returns the host virtual address corresponding to the region address. /// - /// Some [`GuestMemory`](trait.GuestMemory.html) implementations, like `GuestMemoryMmap`, + /// Some [`GuestMemoryBackend`](trait.GuestMemory.html) implementations, like `GuestMemoryMmap`, /// have the capability to mmap guest address range into host virtual address space for /// direct access, so the corresponding host virtual address may be passed to other subsystems. /// @@ -156,7 +156,7 @@ pub trait GuestMemoryRegion: Bytes { /// ``` /// # #[cfg(feature = "backend-mmap")] /// # { - /// # use vm_memory::{GuestAddress, GuestMemory, GuestMemoryMmap, GuestRegionMmap}; + /// # use vm_memory::{GuestAddress, GuestMemoryBackend, GuestMemoryMmap, GuestRegionMmap}; /// let addr = GuestAddress(0x1000); /// let mem = GuestMemoryMmap::<()>::from_ranges(&[(addr, 0x1000)]).unwrap(); /// let r = mem.find_region(addr).unwrap(); @@ -183,7 +183,7 @@ pub enum GuestRegionCollectionError { UnsortedMemoryRegions, } -/// [`GuestMemory`](trait.GuestMemory.html) implementation based on a homogeneous collection +/// [`GuestMemoryBackend`](trait.GuestMemory.html) implementation based on a homogeneous collection /// of [`GuestMemoryRegion`] implementations. /// /// Represents a sorted set of non-overlapping physical guest memory regions. @@ -300,7 +300,7 @@ impl GuestRegionCollection { } } -impl GuestMemory for GuestRegionCollection { +impl GuestMemoryBackend for GuestRegionCollection { type R = R; fn num_regions(&self) -> usize { @@ -476,7 +476,7 @@ impl Bytes for R { pub(crate) mod tests { use crate::region::{GuestMemoryRegionBytes, GuestRegionCollectionError}; use crate::{ - Address, GuestAddress, GuestMemory, GuestMemoryRegion, GuestRegionCollection, GuestUsize, + Address, GuestAddress, GuestMemoryBackend, GuestMemoryRegion, GuestRegionCollection, GuestUsize, }; use matches::assert_matches; use std::sync::Arc; From 5972e82b0b8d80ad965efd916ee7a2d0cb3b4dd8 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 7 Nov 2025 10:43:25 +0100 Subject: [PATCH 3/5] Reformat after the rename Signed-off-by: Paolo Bonzini --- src/atomic.rs | 2 +- src/iommu.rs | 13 +++++++++---- src/lib.rs | 4 ++-- src/region.rs | 3 ++- 4 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/atomic.rs b/src/atomic.rs index 56f15391..784b836f 100644 --- a/src/atomic.rs +++ b/src/atomic.rs @@ -151,7 +151,7 @@ impl GuestMemoryExclusiveGuard<'_, M> { mod tests { use super::*; use crate::region::tests::{new_guest_memory_collection_from_regions, Collection, MockRegion}; - use crate::{GuestAddress, GuestMemoryBackend, GuestMemoryRegion, GuestUsize, GuestMemory}; + use crate::{GuestAddress, GuestMemory, GuestMemoryBackend, GuestMemoryRegion, GuestUsize}; type GuestMemoryMmapAtomic = GuestMemoryAtomic; diff --git a/src/iommu.rs b/src/iommu.rs index 81abc14f..aaf6f602 100644 --- a/src/iommu.rs +++ b/src/iommu.rs @@ -18,8 +18,8 @@ use crate::guest_memory::{ Result as GuestMemoryResult, }; use crate::{ - Address, GuestAddress, GuestMemoryBackend, GuestMemoryRegion, GuestUsize, GuestMemory, Permissions, - VolatileSlice, + Address, GuestAddress, GuestMemory, GuestMemoryBackend, GuestMemoryRegion, GuestUsize, + Permissions, VolatileSlice, }; use rangemap::RangeMap; use std::cmp; @@ -373,7 +373,12 @@ impl TryFrom> for IovaRange { impl IommuMemory { /// Create a new `IommuMemory` instance. - pub fn new(backend: M, iommu: I, use_iommu: bool, bitmap: ::Bitmap) -> Self { + pub fn new( + backend: M, + iommu: I, + use_iommu: bool, + bitmap: ::Bitmap, + ) -> Self { IommuMemory { backend, iommu: Arc::new(iommu), @@ -670,7 +675,7 @@ mod tests { use crate::GuestMemoryRegion; #[cfg(feature = "backend-mmap")] use crate::{ - Bytes, GuestMemoryError, GuestMemoryMmap, GuestMemoryResult, GuestMemory, IommuMemory, + Bytes, GuestMemory, GuestMemoryError, GuestMemoryMmap, GuestMemoryResult, IommuMemory, }; use crate::{GuestAddress, Iommu, Iotlb, Permissions}; use std::fmt::Debug; diff --git a/src/lib.rs b/src/lib.rs index cb576b92..dad56293 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -52,8 +52,8 @@ 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, GuestMemoryBackend, - GuestUsize, GuestMemory, MemoryRegionAddress, Permissions, Result as GuestMemoryResult, + Error as GuestMemoryError, FileOffset, GuestAddress, GuestAddressSpace, GuestMemory, + GuestMemoryBackend, GuestUsize, MemoryRegionAddress, Permissions, Result as GuestMemoryResult, }; pub mod region; diff --git a/src/region.rs b/src/region.rs index 764ce460..d3d13796 100644 --- a/src/region.rs +++ b/src/region.rs @@ -476,7 +476,8 @@ impl Bytes for R { pub(crate) mod tests { use crate::region::{GuestMemoryRegionBytes, GuestRegionCollectionError}; use crate::{ - Address, GuestAddress, GuestMemoryBackend, GuestMemoryRegion, GuestRegionCollection, GuestUsize, + Address, GuestAddress, GuestMemoryBackend, GuestMemoryRegion, GuestRegionCollection, + GuestUsize, }; use matches::assert_matches; use std::sync::Arc; From a6cd7cd4779edfcea46e07368c6e632fb8b1e207 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 7 Nov 2025 10:29:35 +0100 Subject: [PATCH 4/5] Emphasize GuestMemory more in the documentation After the rename, the primary interface to vm-memory is almost completely absent in DESIGN.md. Give it more importance and remove some details of GuestMemoryBackend that are now obsolete. Signed-off-by: Paolo Bonzini --- CHANGELOG.md | 11 +++++++++++ DESIGN.md | 43 ++++++++++++++++++++++--------------------- 2 files changed, 33 insertions(+), 21 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7b5796f7..1513d7ad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,17 @@ ## Upcoming version +### Changed + +This release includes a major change to the `vm-memory` API in order to support +memory access permissions. The previous `GuestMemory` trait is now renamed +to `GuestMemoryBackend`, and `GuestMemory` has a completely new definition. +However, common interfaces such as `GuestAddressSpace` and `Bytes` remain on +`GuestMemory`; therefore, all callers that just use the `Bytes` interface +remain completely unchanged. + +- \[[#362](https://github.com/rust-vmm/vm-memory/pull/360)\] Rename `GuestMemory` to `GuestMemoryBackend`, `IoMemory` to `GuestMemoryBackend` + ### Added - \[[#327](https://github.com/rust-vmm/vm-memory/pull/327)\] I/O virtual memory support via `IoMemory`, `IommuMemory`, and `Iommu`/`Iotlb` diff --git a/DESIGN.md b/DESIGN.md index 4ee859be..bcb0c4ec 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -76,12 +76,13 @@ of the VM using the following traits: - `GuestMemoryRegion`: represents a continuous region of the VM memory. - `GuestMemoryBackend`: represents a collection of `GuestMemoryRegion` objects. The main responsibilities of the `GuestMemoryBackend` trait are: - - hide the detail of accessing physical addresses (for example complex - hierarchical structures). - map an address request to a `GuestMemoryRegion` object and relay the request to it. - handle cases where an access request is spanning two or more `GuestMemoryRegion` objects. +- `GuestMemory`: the primary external interface; it adds permission checks + to `GuestMemoryBackend`, and is more suited to implementations that + have a potentially very large set of non-continuous mappings. The VM memory consumers should only rely on traits and structs defined here to access VM's physical memory and not on the implementation of the traits. @@ -125,25 +126,25 @@ let result = guest_memory_mmap.write(buf, addr); ### I/O Virtual Address Space When using an IOMMU, there no longer is direct access to the guest (physical) -address space, but instead only to I/O virtual address space. In this case: - -- `GuestMemory` replaces `GuestMemoryBackend`: It requires specifying the required access - permissions (which are relevant for virtual memory). It also removes - interfaces that imply a mostly linear memory layout, because virtual memory is - fragmented into many pages instead of few (large) memory regions. - - Any `GuestMemory` still has a `GuestMemoryBackend` inside as the underlying address - space, but if an IOMMU is used, that will generally not be guest physical - address space. With vhost-user, for example, it will be the VMM’s user - address space instead. - - `IommuMemory` as our only actually IOMMU-supporting `GuestMemory` - implementation uses an `Iommu` object to translate I/O virtual addresses - (IOVAs) into VMM user addresses (VUAs), which are then passed to the inner - `GuestMemoryBackend` implementation (like `GuestMemoryMmap`). -- `GuestAddress` (for compatibility) refers to an address in any of these - address spaces: - - Guest physical addresses (GPAs) when no IOMMU is used, - - I/O virtual addresses (IOVAs), - - VMM user addresses (VUAs). +address space, but instead only to I/O virtual address space. In order to +support this usecase, `GuestMemory` (unlike `GuestMemoryBackend`) requires +specifying the required access permissions (which are relevant for virtual +memory). + +`GuestMemory` can still use `GuestMemoryBackend` inside as the underlying +address space, but if an IOMMU is used, that may not be the guest +physical address space. With vhost-user, for example, it will be the +VMM’s user address space instead. For compatibility, `GuestAddress` +can refer to an address in any address space: +- Guest physical addresses (GPAs) when no IOMMU is used, +- I/O virtual addresses (IOVAs), +- VMM user addresses (VUAs). + +`vm-memory` provides an example implementation of `GuestMemory` when +compiled with the `iommu` feature. `IommuMemory` uses an `Iommu` +object to translate I/O virtual addresses (IOVAs) into VMM user addresses +(VUAs), which are then passed to the inner `GuestMemoryBackend` +implementation (like `GuestMemoryMmap`). ### Utilities and Helpers From 569b637e481aad436b201b01d8d7fcffd1ff9dba Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 7 Nov 2025 10:44:52 +0100 Subject: [PATCH 5/5] Bump version to 0.18.0 Signed-off-by: Paolo Bonzini --- CHANGELOG.md | 4 ++-- Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1513d7ad..7ad61eb8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## Upcoming version +## 0.18.0 ### Changed @@ -11,7 +11,7 @@ However, common interfaces such as `GuestAddressSpace` and `Bytes` remain on `GuestMemory`; therefore, all callers that just use the `Bytes` interface remain completely unchanged. -- \[[#362](https://github.com/rust-vmm/vm-memory/pull/360)\] Rename `GuestMemory` to `GuestMemoryBackend`, `IoMemory` to `GuestMemoryBackend` +- \[[#362](https://github.com/rust-vmm/vm-memory/pull/362)\] Rename `GuestMemory` to `GuestMemoryBackend`, `IoMemory` to `GuestMemoryBackend` ### Added diff --git a/Cargo.toml b/Cargo.toml index 38f982de..856e55bc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "vm-memory" -version = "0.17.1" +version = "0.18.0" description = "Safe abstractions for accessing the VM physical memory" keywords = ["memory"] categories = ["memory-management"]