|
26 | 26 | //! - hide the detail of accessing guest's physical address.
|
27 | 27 | //! - map a request address to a GuestMemoryRegion object and relay the request to it.
|
28 | 28 | //! - handle cases where an access request spanning two or more GuestMemoryRegion objects.
|
| 29 | +//! |
| 30 | +//! Whenever a collection of GuestMemoryRegion objects is mutable, |
| 31 | +//! [GuestAddressSpace](trait.GuestAddressSpace.html) should be implemented |
| 32 | +//! for clients to obtain a [GuestMemory] reference or smart pointer. |
29 | 33 |
|
30 | 34 | use std::convert::From;
|
31 | 35 | use std::fmt::{self, Display};
|
32 | 36 | use std::fs::File;
|
33 | 37 | use std::io::{self, Read, Write};
|
34 |
| -use std::ops::{BitAnd, BitOr}; |
| 38 | +use std::ops::{BitAnd, BitOr, Deref}; |
| 39 | +use std::rc::Rc; |
35 | 40 | use std::sync::Arc;
|
36 | 41 |
|
37 | 42 | use crate::address::{Address, AddressValue};
|
@@ -243,14 +248,104 @@ pub trait GuestMemoryRegion: Bytes<MemoryRegionAddress, E = Error> {
|
243 | 248 | }
|
244 | 249 | }
|
245 | 250 |
|
246 |
| -/// Represents a container for a collection of GuestMemoryRegion objects. |
| 251 | +/// GuestAddressSpace provides a way to retrieve a GuestMemory object. |
| 252 | +/// The vm-memory crate already provides trivial implementation for |
| 253 | +/// references to GuestMemory or reference-counted GuestMemory objects, |
| 254 | +/// but the trait can also be implemented by any other struct in order |
| 255 | +/// to provide temporary access to a snapshot of the memory map. |
| 256 | +/// |
| 257 | +/// In order to support generic mutable memory maps, devices (or other things |
| 258 | +/// that access memory) should store the memory as a GuestAddressSpace<M>. |
| 259 | +/// This example shows that references can also be used as the GuestAddressSpace |
| 260 | +/// implementation, providing a zero-cost abstraction whenever immutable memory |
| 261 | +/// maps are sufficient. |
| 262 | +/// |
| 263 | +/// ``` |
| 264 | +/// # use std::sync::Arc; |
| 265 | +/// # #[cfg(feature = "backend-mmap")] |
| 266 | +/// # use vm_memory::GuestMemoryMmap; |
| 267 | +/// # use vm_memory::{GuestAddress, GuestMemory, GuestAddressSpace}; |
| 268 | +/// |
| 269 | +/// pub struct VirtioDevice<AS: GuestAddressSpace> { |
| 270 | +/// mem: Option<AS>, |
| 271 | +/// } |
| 272 | +/// |
| 273 | +/// impl<AS: GuestAddressSpace> VirtioDevice<AS> { |
| 274 | +/// fn new() -> Self { |
| 275 | +/// VirtioDevice { mem: None } |
| 276 | +/// } |
| 277 | +/// fn activate(&mut self, mem: AS) { |
| 278 | +/// self.mem = Some(mem) |
| 279 | +/// } |
| 280 | +/// } |
| 281 | +/// |
| 282 | +/// # #[cfg(feature = "backend-mmap")] |
| 283 | +/// # fn get_mmap() -> GuestMemoryMmap { |
| 284 | +/// # GuestMemoryMmap::from_ranges(&[(GuestAddress(0),0)]).unwrap() |
| 285 | +/// # } |
| 286 | +/// |
| 287 | +/// # #[cfg(feature = "backend-mmap")] |
| 288 | +/// # fn test_1() { |
| 289 | +/// // Using `VirtioDevice` with an immutable GuestMemoryMmap: |
| 290 | +/// let mut for_immutable_mmap: VirtioDevice<&GuestMemoryMmap> = |
| 291 | +/// VirtioDevice::new(); |
| 292 | +/// let mmap = get_mmap(); |
| 293 | +/// for_immutable_mmap.activate(&mmap); |
| 294 | +/// let mut another: VirtioDevice<&GuestMemoryMmap> = |
| 295 | +/// VirtioDevice::new(); |
| 296 | +/// another.activate(&mmap); |
| 297 | +/// # } |
| 298 | +/// ``` |
| 299 | +
|
| 300 | +pub trait GuestAddressSpace { |
| 301 | + /// The type that will be used to access guest memory. |
| 302 | + type M: GuestMemory; |
| 303 | + |
| 304 | + /// A type that provides access to the memory. |
| 305 | + type T: Deref<Target = Self::M>; |
| 306 | + |
| 307 | + /// Return an object (e.g. a reference or guard) that can be used |
| 308 | + /// to access memory through this address space. The object provides |
| 309 | + /// a consistent snapshot of the memory map. |
| 310 | + fn memory(&self) -> Self::T; |
| 311 | +} |
| 312 | + |
| 313 | +impl<M: GuestMemory> GuestAddressSpace for &M { |
| 314 | + type T = Self; |
| 315 | + type M = M; |
| 316 | + |
| 317 | + fn memory(&self) -> Self { |
| 318 | + self |
| 319 | + } |
| 320 | +} |
| 321 | + |
| 322 | +impl<M: GuestMemory> GuestAddressSpace for Rc<M> { |
| 323 | + type T = Self; |
| 324 | + type M = M; |
| 325 | + |
| 326 | + fn memory(&self) -> Self { |
| 327 | + self.clone() |
| 328 | + } |
| 329 | +} |
| 330 | + |
| 331 | +impl<M: GuestMemory> GuestAddressSpace for Arc<M> { |
| 332 | + type T = Self; |
| 333 | + type M = M; |
| 334 | + |
| 335 | + fn memory(&self) -> Self { |
| 336 | + self.clone() |
| 337 | + } |
| 338 | +} |
| 339 | + |
| 340 | +/// GuestMemory represents a container for an *immutable* collection of |
| 341 | +/// GuestMemoryRegion objects. GuestMemory provides the `Bytes<GuestAddress>` |
| 342 | +/// trait to hide the details of accessing guest memory by physical address. |
| 343 | +/// Interior mutability is not allowed for implementations of GuestMemory so |
| 344 | +/// that they always provide a consistent view of the memory map. |
247 | 345 | ///
|
248 |
| -/// The main responsibilities of the GuestMemory trait are: |
249 |
| -/// - hide the detail of accessing guest's physical address. |
| 346 | +/// The task of the GuestMemory trait are: |
250 | 347 | /// - map a request address to a GuestMemoryRegion object and relay the request to it.
|
251 | 348 | /// - handle cases where an access request spanning two or more GuestMemoryRegion objects.
|
252 |
| -/// |
253 |
| -/// Note: the regions inside a [`GuestMemory`](trait.GuestMemory.html) object must not overlap. |
254 | 349 | pub trait GuestMemory {
|
255 | 350 | /// Type of objects hosted by the address space.
|
256 | 351 | type R: GuestMemoryRegion;
|
|
0 commit comments