Skip to content

Commit d1ebfbe

Browse files
committed
refactor: centralize GuestMemoryMmap creation
In this day and age, Firecracker supports theoretically 4 different ways of backing guest memory: 1. Normal MAP_ANONYMOUS | MAP_PRIVATE memory 2. memfd backed memory, mapped as shared 3. direct mapping of a snapshot file 4. MAP_ANONYMOUS again, but this time regions are described by snapshot file. We have 3 different functions for creating these different backing stores, which then call each other and vm_memory's APIs. Clean this up by consolidating these into just one function that can be called with a description of the memory regions, plus an enum argument stating how each region should be backed. Signed-off-by: Patrick Roy <[email protected]>
1 parent 88e0b6e commit d1ebfbe

File tree

7 files changed

+259
-262
lines changed

7 files changed

+259
-262
lines changed

src/vmm/src/devices/virtio/block/vhost_user/device.rs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -372,13 +372,15 @@ mod tests {
372372
use std::sync::atomic::Ordering;
373373

374374
use vhost::{VhostUserMemoryRegionInfo, VringConfigData};
375+
use vm_memory::GuestAddress;
375376
use vmm_sys_util::tempfile::TempFile;
376377

377378
use super::*;
378379
use crate::devices::virtio::block::virtio::device::FileEngineType;
379380
use crate::devices::virtio::mmio::VIRTIO_MMIO_INT_CONFIG;
380381
use crate::test_utils::create_tmp_socket;
381-
use crate::vstate::memory::{FileOffset, GuestAddress, GuestMemoryExtension};
382+
use crate::vmm_config::machine_config::HugePageConfig;
383+
use crate::vstate::memory::{GuestMemoryExtension, MemoryKind};
382384

383385
#[test]
384386
fn test_from_config() {
@@ -778,12 +780,13 @@ mod tests {
778780
let region_size = 0x10000;
779781
let file = TempFile::new().unwrap().into_file();
780782
file.set_len(region_size as u64).unwrap();
781-
let regions = vec![(
782-
FileOffset::new(file.try_clone().unwrap(), 0x0),
783-
GuestAddress(0x0),
784-
region_size,
785-
)];
786-
let guest_memory = GuestMemoryMmap::from_raw_regions_file(regions, false, false).unwrap();
783+
let guest_memory = GuestMemoryMmap::create(
784+
[(GuestAddress(0), region_size)].into_iter(),
785+
MemoryKind::FilePrivate(file),
786+
false,
787+
HugePageConfig::None,
788+
)
789+
.unwrap();
787790

788791
// During actiavion of the device features, memory and queues should be set and activated.
789792
vhost_block.activate(guest_memory).unwrap();

src/vmm/src/devices/virtio/block/virtio/io/mod.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ pub mod tests {
194194
use crate::devices::virtio::block::virtio::device::FileEngineType;
195195
use crate::utils::u64_to_usize;
196196
use crate::vmm_config::machine_config::HugePageConfig;
197-
use crate::vstate::memory::{Bitmap, Bytes, GuestMemory, GuestMemoryExtension};
197+
use crate::vstate::memory::{Bitmap, Bytes, GuestMemory, GuestMemoryExtension, MemoryKind};
198198

199199
const FILE_LEN: u32 = 1024;
200200
// 2 pages of memory should be enough to test read/write ops and also dirty tracking.
@@ -230,8 +230,13 @@ pub mod tests {
230230
}
231231

232232
fn create_mem() -> GuestMemoryMmap {
233-
GuestMemoryMmap::from_raw_regions(&[(GuestAddress(0), MEM_LEN)], true, HugePageConfig::None)
234-
.unwrap()
233+
GuestMemoryMmap::create(
234+
[(GuestAddress(0), MEM_LEN)].into_iter(),
235+
MemoryKind::MapAnonymous,
236+
true,
237+
HugePageConfig::None,
238+
)
239+
.unwrap()
235240
}
236241

237242
fn check_dirty_mem(mem: &GuestMemoryMmap, addr: GuestAddress, len: u32) {

src/vmm/src/devices/virtio/vhost_user.rs

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -466,7 +466,8 @@ mod tests {
466466

467467
use super::*;
468468
use crate::test_utils::create_tmp_socket;
469-
use crate::vstate::memory::{FileOffset, GuestAddress, GuestMemoryExtension};
469+
use crate::vmm_config::machine_config::HugePageConfig;
470+
use crate::vstate::memory::{GuestAddress, GuestMemoryExtension, MemoryKind};
470471

471472
#[test]
472473
fn test_new() {
@@ -758,20 +759,18 @@ mod tests {
758759
let file = TempFile::new().unwrap().into_file();
759760
let file_size = 2 * region_size;
760761
file.set_len(file_size as u64).unwrap();
761-
let regions = vec![
762-
(
763-
FileOffset::new(file.try_clone().unwrap(), 0x0),
764-
GuestAddress(0x0),
765-
region_size,
766-
),
767-
(
768-
FileOffset::new(file.try_clone().unwrap(), 0x10000),
769-
GuestAddress(0x10000),
770-
region_size,
771-
),
762+
let regions = [
763+
(GuestAddress(0x0), region_size),
764+
(GuestAddress(0x10000), region_size),
772765
];
773766

774-
let guest_memory = GuestMemoryMmap::from_raw_regions_file(regions, false, false).unwrap();
767+
let guest_memory = GuestMemoryMmap::create(
768+
regions.into_iter(),
769+
MemoryKind::FilePrivate(file),
770+
false,
771+
HugePageConfig::None,
772+
)
773+
.unwrap();
775774

776775
vuh.update_mem_table(&guest_memory).unwrap();
777776

@@ -883,13 +882,14 @@ mod tests {
883882
let region_size = 0x10000;
884883
let file = TempFile::new().unwrap().into_file();
885884
file.set_len(region_size as u64).unwrap();
886-
let regions = vec![(
887-
FileOffset::new(file.try_clone().unwrap(), 0x0),
888-
GuestAddress(0x0),
889-
region_size,
890-
)];
891885

892-
let guest_memory = GuestMemoryMmap::from_raw_regions_file(regions, false, false).unwrap();
886+
let guest_memory = GuestMemoryMmap::create(
887+
[(GuestAddress(0), region_size)].into_iter(),
888+
MemoryKind::FilePrivate(file),
889+
false,
890+
HugePageConfig::None,
891+
)
892+
.unwrap();
893893

894894
let mut queue = Queue::new(69);
895895
queue.initialize(&guest_memory).unwrap();

src/vmm/src/persist.rs

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use std::sync::{Arc, Mutex};
1414
use semver::Version;
1515
use serde::{Deserialize, Serialize};
1616
use userfaultfd::{FeatureFlags, Uffd, UffdBuilder};
17+
use vm_memory::GuestAddress;
1718
use vmm_sys_util::sock_ctrl_msg::ScmSocket;
1819

1920
#[cfg(target_arch = "aarch64")]
@@ -38,7 +39,7 @@ use crate::vmm_config::snapshot::{
3839
};
3940
use crate::vstate::kvm::KvmState;
4041
use crate::vstate::memory::{
41-
GuestMemory, GuestMemoryExtension, GuestMemoryMmap, GuestMemoryState, MemoryError,
42+
GuestMemory, GuestMemoryExtension, GuestMemoryMmap, GuestMemoryState, MemoryError, MemoryKind,
4243
};
4344
use crate::vstate::vcpu::{VcpuSendEventError, VcpuState};
4445
use crate::vstate::vm::VmState;
@@ -515,15 +516,23 @@ pub enum GuestMemoryFromFileError {
515516
Restore(#[from] MemoryError),
516517
}
517518

518-
fn guest_memory_from_file(
519+
/// Creates a [`GuestMemoryMmap`] from a snapshot file
520+
pub fn guest_memory_from_file(
519521
mem_file_path: &Path,
520522
mem_state: &GuestMemoryState,
521523
track_dirty_pages: bool,
522524
huge_pages: HugePageConfig,
523525
) -> Result<GuestMemoryMmap, GuestMemoryFromFileError> {
524526
let mem_file = File::open(mem_file_path)?;
525-
let guest_mem =
526-
GuestMemoryMmap::from_state(Some(&mem_file), mem_state, track_dirty_pages, huge_pages)?;
527+
let guest_mem = GuestMemoryMmap::create(
528+
mem_state
529+
.regions
530+
.iter()
531+
.map(|region| (GuestAddress(region.base_address), region.size)),
532+
MemoryKind::FilePrivate(mem_file),
533+
track_dirty_pages,
534+
huge_pages,
535+
)?;
527536
Ok(guest_mem)
528537
}
529538

@@ -582,7 +591,15 @@ fn create_guest_memory(
582591
track_dirty_pages: bool,
583592
huge_pages: HugePageConfig,
584593
) -> Result<(GuestMemoryMmap, Vec<GuestRegionUffdMapping>), GuestMemoryFromUffdError> {
585-
let guest_memory = GuestMemoryMmap::from_state(None, mem_state, track_dirty_pages, huge_pages)?;
594+
let guest_memory = GuestMemoryMmap::create(
595+
mem_state
596+
.regions
597+
.iter()
598+
.map(|region| (GuestAddress(region.base_address), region.size)),
599+
MemoryKind::MapAnonymous,
600+
track_dirty_pages,
601+
huge_pages,
602+
)?;
586603
let mut backend_mappings = Vec::with_capacity(guest_memory.num_regions());
587604
for (mem_region, state_region) in guest_memory.iter().zip(mem_state.regions.iter()) {
588605
backend_mappings.push(GuestRegionUffdMapping {

src/vmm/src/resources.rs

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ use crate::vmm_config::metrics::{init_metrics, MetricsConfig, MetricsConfigError
2828
use crate::vmm_config::mmds::{MmdsConfig, MmdsConfigError};
2929
use crate::vmm_config::net::*;
3030
use crate::vmm_config::vsock::*;
31-
use crate::vstate::memory::{GuestMemoryExtension, GuestMemoryMmap, MemoryError};
31+
use crate::vstate::memory::{GuestMemoryExtension, GuestMemoryMmap, MemoryError, MemoryKind};
3232

3333
/// Errors encountered when configuring microVM resources.
3434
#[derive(Debug, thiserror::Error, displaydoc::Display)]
@@ -464,20 +464,22 @@ impl VmResources {
464464
// because that would require running a backend process. If in the future we converge to
465465
// a single way of backing guest memory for vhost-user and non-vhost-user cases,
466466
// that would not be worth the effort.
467-
if vhost_user_device_used {
468-
GuestMemoryMmap::memfd_backed(
467+
468+
let memory_kind = if vhost_user_device_used {
469+
MemoryKind::memfd(
469470
self.machine_config.mem_size_mib,
470-
self.machine_config.track_dirty_pages,
471471
self.machine_config.huge_pages,
472-
)
472+
)?
473473
} else {
474-
let regions = crate::arch::arch_memory_regions(self.machine_config.mem_size_mib << 20);
475-
GuestMemoryMmap::from_raw_regions(
476-
&regions,
477-
self.machine_config.track_dirty_pages,
478-
self.machine_config.huge_pages,
479-
)
480-
}
474+
MemoryKind::MapAnonymous
475+
};
476+
477+
GuestMemoryMmap::create(
478+
crate::arch::arch_memory_regions(self.machine_config.mem_size_mib << 20).into_iter(),
479+
memory_kind,
480+
self.machine_config.track_dirty_pages,
481+
self.machine_config.huge_pages,
482+
)
481483
}
482484
}
483485

src/vmm/src/test_utils/mod.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use crate::test_utils::mock_resources::{MockBootSourceConfig, MockVmConfig, Mock
1515
use crate::vmm_config::boot_source::BootSourceConfig;
1616
use crate::vmm_config::instance_info::InstanceInfo;
1717
use crate::vmm_config::machine_config::HugePageConfig;
18-
use crate::vstate::memory::{GuestMemoryExtension, GuestMemoryMmap};
18+
use crate::vstate::memory::{GuestMemoryExtension, GuestMemoryMmap, MemoryKind};
1919
use crate::{EventManager, Vmm};
2020

2121
pub mod mock_resources;
@@ -34,8 +34,13 @@ pub fn single_region_mem_at(at: u64, size: usize) -> GuestMemoryMmap {
3434

3535
/// Creates a [`GuestMemoryMmap`] with multiple regions and without dirty page tracking.
3636
pub fn multi_region_mem(regions: &[(GuestAddress, usize)]) -> GuestMemoryMmap {
37-
GuestMemoryMmap::from_raw_regions(regions, false, HugePageConfig::None)
38-
.expect("Cannot initialize memory")
37+
GuestMemoryMmap::create(
38+
regions.iter().copied(),
39+
MemoryKind::MapAnonymous,
40+
false,
41+
HugePageConfig::None,
42+
)
43+
.expect("Cannot initialize memory")
3944
}
4045

4146
/// Creates a [`GuestMemoryMmap`] of the given size with the contained regions laid out in

0 commit comments

Comments
 (0)