Skip to content

Commit 87ce16c

Browse files
committed
refactor: scatter mmap.rs contents to unix/windows modules
This is some duplication, but it once and for all eliminates all cfg fuckery and code that expects precisely one module to be defined. Admittedly, for windows/unix we could have stuck with the cfg stuff, but I wanted a clean slate for now. The windows parts are compile-tested only, as I do not have a windows system available. The handling of various from_range functions is based on the assumption that these were only used in test code and nowhere else (hence all the preceding refactors of test code). In unit tests, their use has been eliminated, and doc tests now got a cfg(unix. not(feature="xen")) so that they only run when mmap_unix is available. This is fine, because they are examples of how to use specific functions, and not any serious tests (e.g. dont need to run for all supported backends). Signed-off-by: Patrick Roy <[email protected]>
1 parent 4ab3783 commit 87ce16c

File tree

8 files changed

+286
-202
lines changed

8 files changed

+286
-202
lines changed

src/bitmap/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,7 @@ pub(crate) mod tests {
274274
// them to test the mmap-based backend implementations for now. Going forward, the generic
275275
// test functions defined here can be placed in a separate module (i.e. `test_utilities`)
276276
// which is gated by a feature and can be used for testing purposes by other crates as well.
277-
#[cfg(feature = "backend-mmap")]
277+
#[cfg(all(feature = "backend-mmap", unix))]
278278
fn test_guest_memory_region<R: GuestMemoryRegion>(region: &R) {
279279
let dirty_addr = MemoryRegionAddress(0x0);
280280
let val = 123u64;
@@ -308,7 +308,7 @@ pub(crate) mod tests {
308308
);
309309
}
310310

311-
#[cfg(feature = "backend-mmap")]
311+
#[cfg(all(feature = "backend-mmap", unix))]
312312
// Assumptions about M generated by f ...
313313
pub fn test_guest_memory_and_region<M, F>(f: F)
314314
where

src/bytes.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -330,7 +330,7 @@ pub trait Bytes<A> {
330330
/// * Read bytes from /dev/urandom (uses the `backend-mmap` feature)
331331
///
332332
/// ```
333-
/// # #[cfg(all(feature = "backend-mmap", feature = "rawfd"))]
333+
/// # #[cfg(all(feature = "backend-mmap", feature = "rawfd", unix, not(feature = "xen")))]
334334
/// # {
335335
/// # use vm_memory::{Address, GuestMemory, Bytes, GuestAddress, GuestMemoryMmap};
336336
/// # use std::fs::File;

src/guest_memory.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ impl FileOffset {
174174
/// # Examples (uses the `backend-mmap` and `backend-atomic` features)
175175
///
176176
/// ```
177-
/// # #[cfg(feature = "backend-mmap")]
177+
/// # #[cfg(all(feature = "backend-mmap", unix, not(feature = "xen")))]
178178
/// # {
179179
/// # use std::sync::Arc;
180180
/// # use vm_memory::{GuestAddress, GuestAddressSpace, GuestMemory, GuestMemoryMmap};
@@ -290,7 +290,7 @@ pub trait GuestMemory {
290290
/// `backend-mmap` feature)
291291
///
292292
/// ```
293-
/// # #[cfg(feature = "backend-mmap")]
293+
/// # #[cfg(all(feature = "backend-mmap", unix, not(feature = "xen")))]
294294
/// # {
295295
/// # use vm_memory::{GuestAddress, GuestMemory, GuestMemoryRegion, GuestMemoryMmap};
296296
/// #
@@ -314,7 +314,7 @@ pub trait GuestMemory {
314314
/// # Examples (uses the `backend-mmap` feature)
315315
///
316316
/// ```
317-
/// # #[cfg(feature = "backend-mmap")]
317+
/// # #[cfg(all(feature = "backend-mmap", unix, not(feature = "xen")))]
318318
/// # {
319319
/// # use vm_memory::{Address, GuestAddress, GuestMemory, GuestMemoryMmap};
320320
/// #
@@ -426,7 +426,7 @@ pub trait GuestMemory {
426426
/// # Examples (uses the `backend-mmap` feature)
427427
///
428428
/// ```
429-
/// # #[cfg(feature = "backend-mmap")]
429+
/// # #[cfg(all(feature = "backend-mmap", unix, not(feature = "xen")))]
430430
/// # {
431431
/// # use vm_memory::{GuestAddress, GuestMemory, GuestMemoryMmap};
432432
/// #
@@ -483,7 +483,7 @@ impl<T: GuestMemory + ?Sized> Bytes<GuestAddress> for T {
483483
/// * Write a slice at guestaddress 0x1000. (uses the `backend-mmap` feature)
484484
///
485485
/// ```
486-
/// # #[cfg(feature = "backend-mmap")]
486+
/// # #[cfg(all(feature = "backend-mmap", unix, not(feature = "xen")))]
487487
/// # {
488488
/// # use vm_memory::{Bytes, GuestAddress, mmap::GuestMemoryMmap};
489489
/// #
@@ -511,7 +511,7 @@ impl<T: GuestMemory + ?Sized> Bytes<GuestAddress> for T {
511511
/// * Read a slice of length 16 at guestaddress 0x1000. (uses the `backend-mmap` feature)
512512
///
513513
/// ```
514-
/// # #[cfg(feature = "backend-mmap")]
514+
/// # #[cfg(all(feature = "backend-mmap", unix, not(feature = "xen")))]
515515
/// # {
516516
/// # use vm_memory::{Bytes, GuestAddress, mmap::GuestMemoryMmap};
517517
/// #

src/lib.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,14 +68,22 @@ mod mmap_windows;
6868
#[cfg(feature = "backend-mmap")]
6969
pub mod mmap;
7070

71-
#[cfg(feature = "backend-mmap")]
72-
pub use mmap::{GuestMemoryMmap, GuestRegionMmap, MmapRegion};
7371
#[cfg(all(feature = "backend-mmap", feature = "xen", unix))]
7472
pub use mmap::{MmapRange, MmapXenFlags};
7573

7674
#[cfg(all(feature = "xen", unix))]
7775
pub use mmap_xen::{GuestMemoryXen, MmapRegion as MmapRegionXen};
7876

77+
#[cfg(all(feature = "backend-mmap", unix, not(feature = "xen")))]
78+
pub use mmap_unix::{Error as MmapRegionError, GuestMemoryMmap, GuestRegionMmap, MmapRegion};
79+
80+
#[cfg(windows)]
81+
pub use crate::mmap_windows::{
82+
GuestMemoryWindows as GuestMemoryMmap, GuestRegionWindows as GuestRegionMmap, MmapRegion,
83+
}; // rename for backwards compat
84+
#[cfg(windows)]
85+
pub use std::io::Error as MmapRegionError;
86+
7987
pub mod volatile_memory;
8088
pub use volatile_memory::{
8189
Error as VolatileMemoryError, Result as VolatileMemoryResult, VolatileArrayRef, VolatileMemory,

src/mmap.rs

Lines changed: 26 additions & 182 deletions
Original file line numberDiff line numberDiff line change
@@ -12,30 +12,19 @@
1212
//!
1313
//! This implementation is mmap-ing the memory of the guest into the current process.
1414
15-
use std::borrow::Borrow;
1615
#[cfg(unix)]
1716
use std::io::{Seek, SeekFrom};
18-
use std::ops::Deref;
1917
use std::result;
2018

21-
use crate::address::Address;
22-
use crate::bitmap::{Bitmap, BS};
23-
use crate::guest_memory::{self, FileOffset, GuestAddress, GuestUsize, MemoryRegionAddress};
24-
use crate::region::GuestMemoryRegion;
25-
use crate::volatile_memory::{VolatileMemory, VolatileSlice};
26-
use crate::{Error, GuestRegionCollection};
19+
use crate::bitmap::Bitmap;
20+
use crate::guest_memory::FileOffset;
2721

2822
#[cfg(all(not(feature = "xen"), unix))]
2923
pub use crate::mmap_unix::{Error as MmapRegionError, MmapRegion, MmapRegionBuilder};
3024

3125
#[cfg(all(feature = "xen", unix))]
3226
pub use crate::mmap_xen::{Error as MmapRegionError, MmapRange, MmapRegion, MmapXenFlags};
3327

34-
#[cfg(windows)]
35-
pub use crate::mmap_windows::MmapRegion;
36-
#[cfg(windows)]
37-
pub use std::io::Error as MmapRegionError;
38-
3928
/// A `Bitmap` that can be created starting from an initial size.
4029
pub trait NewBitmap: Bitmap + Default {
4130
/// Create a new object based on the specified length in bytes.
@@ -91,166 +80,18 @@ pub fn check_file_offset(
9180
Ok(())
9281
}
9382

94-
/// [`GuestMemoryRegion`](trait.GuestMemoryRegion.html) implementation that mmaps the guest's
95-
/// memory region in the current process.
96-
///
97-
/// Represents a continuous region of the guest's physical memory that is backed by a mapping
98-
/// in the virtual address space of the calling process.
99-
#[derive(Debug)]
100-
pub struct GuestRegionMmap<B = ()> {
101-
mapping: MmapRegion<B>,
102-
guest_base: GuestAddress,
103-
}
104-
105-
impl<B> Deref for GuestRegionMmap<B> {
106-
type Target = MmapRegion<B>;
107-
108-
fn deref(&self) -> &MmapRegion<B> {
109-
&self.mapping
110-
}
111-
}
112-
113-
impl<B: Bitmap> GuestRegionMmap<B> {
114-
/// Create a new memory-mapped memory region for the guest's physical memory.
115-
pub fn new(mapping: MmapRegion<B>, guest_base: GuestAddress) -> result::Result<Self, Error> {
116-
if guest_base.0.checked_add(mapping.size() as u64).is_none() {
117-
return Err(Error::InvalidGuestRegion);
118-
}
119-
120-
Ok(GuestRegionMmap {
121-
mapping,
122-
guest_base,
123-
})
124-
}
125-
}
126-
127-
#[cfg(not(feature = "xen"))]
128-
impl<B: NewBitmap> GuestRegionMmap<B> {
129-
/// Create a new memory-mapped memory region from guest's physical memory, size and file.
130-
pub fn from_range(
131-
addr: GuestAddress,
132-
size: usize,
133-
file: Option<FileOffset>,
134-
) -> result::Result<Self, Error> {
135-
let region = if let Some(ref f_off) = file {
136-
MmapRegion::from_file(f_off.clone(), size)
137-
} else {
138-
MmapRegion::new(size)
139-
}
140-
.map_err(Error::MmapRegion)?;
141-
142-
Self::new(region, addr)
143-
}
144-
}
145-
146-
#[cfg(feature = "xen")]
147-
impl<B: NewBitmap> GuestRegionMmap<B> {
148-
/// Create a new Unix memory-mapped memory region from guest's physical memory, size and file.
149-
/// This must only be used for tests, doctests, benches and is not designed for end consumers.
150-
pub fn from_range(
151-
addr: GuestAddress,
152-
size: usize,
153-
file: Option<FileOffset>,
154-
) -> result::Result<Self, Error> {
155-
let range = MmapRange::new_unix(size, file, addr);
156-
157-
let region = MmapRegion::from_range(range).map_err(Error::MmapRegion)?;
158-
Self::new(region, addr)
159-
}
160-
}
161-
162-
impl<B: Bitmap> GuestMemoryRegion for GuestRegionMmap<B> {
163-
type B = B;
164-
165-
fn len(&self) -> GuestUsize {
166-
self.mapping.size() as GuestUsize
167-
}
168-
169-
fn start_addr(&self) -> GuestAddress {
170-
self.guest_base
171-
}
172-
173-
fn bitmap(&self) -> &Self::B {
174-
self.mapping.bitmap()
175-
}
176-
177-
fn get_host_address(&self, addr: MemoryRegionAddress) -> guest_memory::Result<*mut u8> {
178-
// Not sure why wrapping_offset is not unsafe. Anyway this
179-
// is safe because we've just range-checked addr using check_address.
180-
self.check_address(addr)
181-
.ok_or(guest_memory::Error::InvalidBackendAddress)
182-
.map(|addr| {
183-
self.mapping
184-
.as_ptr()
185-
.wrapping_offset(addr.raw_value() as isize)
186-
})
187-
}
188-
189-
fn file_offset(&self) -> Option<&FileOffset> {
190-
self.mapping.file_offset()
191-
}
192-
193-
fn get_slice(
194-
&self,
195-
offset: MemoryRegionAddress,
196-
count: usize,
197-
) -> guest_memory::Result<VolatileSlice<BS<B>>> {
198-
let slice = VolatileMemory::get_slice(&self.mapping, offset.raw_value() as usize, count)?;
199-
Ok(slice)
200-
}
201-
202-
#[cfg(target_os = "linux")]
203-
fn is_hugetlbfs(&self) -> Option<bool> {
204-
self.mapping.is_hugetlbfs()
205-
}
206-
}
207-
208-
/// [`GuestMemory`](trait.GuestMemory.html) implementation that mmaps the guest's memory
209-
/// in the current process.
210-
///
211-
/// Represents the entire physical memory of the guest by tracking all its memory regions.
212-
/// Each region is an instance of `GuestRegionMmap`, being backed by a mapping in the
213-
/// virtual address space of the calling process.
214-
pub type GuestMemoryMmap<B = ()> = GuestRegionCollection<GuestRegionMmap<B>>;
215-
216-
impl<B: NewBitmap> GuestMemoryMmap<B> {
217-
/// Creates a container and allocates anonymous memory for guest memory regions.
218-
///
219-
/// Valid memory regions are specified as a slice of (Address, Size) tuples sorted by Address.
220-
pub fn from_ranges(ranges: &[(GuestAddress, usize)]) -> result::Result<Self, Error> {
221-
Self::from_ranges_with_files(ranges.iter().map(|r| (r.0, r.1, None)))
222-
}
223-
224-
/// Creates a container and allocates anonymous memory for guest memory regions.
225-
///
226-
/// Valid memory regions are specified as a sequence of (Address, Size, [`Option<FileOffset>`])
227-
/// tuples sorted by Address.
228-
pub fn from_ranges_with_files<A, T>(ranges: T) -> result::Result<Self, Error>
229-
where
230-
A: Borrow<(GuestAddress, usize, Option<FileOffset>)>,
231-
T: IntoIterator<Item = A>,
232-
{
233-
Self::from_regions(
234-
ranges
235-
.into_iter()
236-
.map(|x| {
237-
GuestRegionMmap::from_range(x.borrow().0, x.borrow().1, x.borrow().2.clone())
238-
})
239-
.collect::<result::Result<Vec<_>, Error>>()?,
240-
)
241-
}
242-
}
243-
24483
#[cfg(test)]
24584
pub(crate) mod tests {
24685
#![allow(clippy::undocumented_unsafe_blocks)]
24786
extern crate vmm_sys_util;
24887

24988
use super::*;
25089

251-
use crate::bitmap::tests::test_guest_memory_and_region;
252-
use crate::bitmap::AtomicBitmap;
253-
use crate::{Bytes, GuestMemory, GuestMemoryError};
90+
use crate::bitmap::BS;
91+
use crate::{
92+
guest_memory, Address, Bytes, GuestAddress, GuestMemory, GuestMemoryError,
93+
GuestMemoryRegion, GuestUsize, MemoryRegionAddress, VolatileMemory, VolatileSlice,
94+
};
25495

25596
use std::io::Write;
25697
use std::mem;
@@ -312,9 +153,9 @@ pub(crate) mod tests {
312153

313154
any_backend! {
314155
#[cfg(all(windows, feature = "backend-mmap"))]
315-
Windows[GuestRegionMmap<()>],
156+
Windows[crate::mmap_windows::GuestRegionWindows<()>],
316157
#[cfg(all(unix, feature = "backend-mmap", not(feature = "xen")))]
317-
Mmap[GuestRegionMmap<()>],
158+
Mmap[crate::mmap_unix::GuestRegionMmap<()>],
318159
#[cfg(all(unix, feature = "backend-mmap", feature = "xen"))]
319160
Xen[crate::mmap_xen::MmapRegion]
320161
}
@@ -326,13 +167,19 @@ pub(crate) mod tests {
326167
let mut regions = Vec::new();
327168
#[cfg(all(windows, feature = "backend-mmap"))]
328169
regions.push(AnyRegion::Windows(
329-
GuestRegionMmap::new(MmapRegion::from_file(f_off.clone(), size).unwrap(), addr)
330-
.unwrap(),
170+
crate::mmap_windows::GuestRegionWindows::new(
171+
crate::mmap_windows::MmapRegion::from_file(f_off.clone(), size).unwrap(),
172+
addr,
173+
)
174+
.unwrap(),
331175
));
332176
#[cfg(all(unix, feature = "backend-mmap", not(feature = "xen")))]
333177
regions.push(AnyRegion::Mmap(
334-
GuestRegionMmap::new(MmapRegion::from_file(f_off.clone(), size).unwrap(), addr)
335-
.unwrap(),
178+
crate::mmap_unix::GuestRegionMmap::new(
179+
MmapRegion::from_file(f_off.clone(), size).unwrap(),
180+
addr,
181+
)
182+
.unwrap(),
336183
));
337184
#[cfg(all(unix, feature = "backend-mmap", feature = "xen"))]
338185
regions.push(AnyRegion::Xen(
@@ -350,11 +197,16 @@ pub(crate) mod tests {
350197
};
351198
#[cfg(all(windows, feature = "backend-mmap"))]
352199
regions.push(AnyRegion::Windows(
353-
GuestRegionMmap::new(MmapRegion::new(size).unwrap(), addr).unwrap(),
200+
crate::mmap_windows::GuestRegionWindows::new(
201+
crate::mmap_windows::MmapRegion::new(size).unwrap(),
202+
addr,
203+
)
204+
.unwrap(),
354205
));
355206
#[cfg(all(unix, feature = "backend-mmap", not(feature = "xen")))]
356207
regions.push(AnyRegion::Mmap(
357-
GuestRegionMmap::new(MmapRegion::new(size).unwrap(), addr).unwrap(),
208+
crate::mmap_unix::GuestRegionMmap::new(MmapRegion::new(size).unwrap(), addr)
209+
.unwrap(),
358210
));
359211
#[cfg(all(unix, feature = "backend-mmap", feature = "xen"))]
360212
regions.push(AnyRegion::Xen(
@@ -731,12 +583,4 @@ pub(crate) mod tests {
731583
);
732584
}
733585
}
734-
735-
#[test]
736-
fn test_dirty_tracking() {
737-
test_guest_memory_and_region(|| {
738-
crate::GuestMemoryMmap::<AtomicBitmap>::from_ranges(&[(GuestAddress(0), 0x1_0000)])
739-
.unwrap()
740-
});
741-
}
742586
}

0 commit comments

Comments
 (0)