Skip to content

Commit e7f9bb0

Browse files
committed
refactor: have memory.rs hand out Vec<GuestRegionMmap>
This way, we can accumulate different memory regions into one `GuestMemoryMmap` over this inside `struct Vm`. Sadly, vm-memory does not offer APIs for merging `GuestMemoryMmap`s, so there can only be one of these. Signed-off-by: Patrick Roy <[email protected]>
1 parent de7804d commit e7f9bb0

File tree

12 files changed

+272
-226
lines changed

12 files changed

+272
-226
lines changed

src/vmm/benches/memory_access.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
// SPDX-License-Identifier: Apache-2.0
33

44
use criterion::{BatchSize, Criterion, criterion_group, criterion_main};
5-
use vm_memory::GuestMemory;
65
use vmm::resources::VmResources;
76
use vmm::vmm_config::machine_config::{HugePageConfig, MachineConfig};
87

@@ -14,7 +13,7 @@ fn bench_single_page_fault(c: &mut Criterion, configuration: VmResources) {
1413
// Get a pointer to the first memory region (cannot do `.get_slice(GuestAddress(0),
1514
// 1)`, because on ARM64 guest memory does not start at physical
1615
// address 0).
17-
let ptr = memory.iter().next().unwrap().as_ptr();
16+
let ptr = memory.first().unwrap().as_ptr();
1817

1918
// fine to return both here, because ptr is not a reference into `memory` (e.g. no
2019
// self-referential structs are happening here)

src/vmm/src/acpi/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ mod tests {
188188
use crate::acpi::{AcpiError, AcpiTableWriter};
189189
use crate::arch::x86_64::layout::{SYSTEM_MEM_SIZE, SYSTEM_MEM_START};
190190
use crate::builder::tests::default_vmm;
191-
use crate::test_utils::arch_mem;
191+
use crate::test_utils::arch_mem_raw;
192192

193193
struct MockSdt(Vec<u8>);
194194

@@ -265,7 +265,7 @@ mod tests {
265265
fn test_write_acpi_table_small_memory() {
266266
let mut vmm = default_vmm();
267267
vmm.vm
268-
.memory_init(arch_mem(
268+
.register_memory_regions(arch_mem_raw(
269269
(SYSTEM_MEM_START + SYSTEM_MEM_SIZE - 4096)
270270
.try_into()
271271
.unwrap(),

src/vmm/src/builder.rs

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ use crate::vmm_config::boot_source::BootConfig;
7272
use crate::vmm_config::instance_info::InstanceInfo;
7373
use crate::vmm_config::machine_config::{MachineConfig, MachineConfigError};
7474
use crate::vstate::kvm::Kvm;
75-
use crate::vstate::memory::{GuestAddress, GuestMemory, GuestMemoryMmap};
75+
use crate::vstate::memory::{GuestAddress, GuestMemory, GuestMemoryMmap, GuestRegionMmap};
7676
use crate::vstate::vcpu::{Vcpu, VcpuConfig, VcpuError};
7777
use crate::vstate::vm::Vm;
7878
use crate::{EventManager, Vmm, VmmError, device_manager};
@@ -154,7 +154,6 @@ impl std::convert::From<linux_loader::cmdline::Error> for StartMicrovmError {
154154
fn create_vmm_and_vcpus(
155155
instance_info: &InstanceInfo,
156156
event_manager: &mut EventManager,
157-
guest_memory: GuestMemoryMmap,
158157
uffd: Option<Uffd>,
159158
vcpu_count: u8,
160159
kvm_capabilities: Vec<KvmCapability>,
@@ -163,7 +162,6 @@ fn create_vmm_and_vcpus(
163162
// Set up Kvm Vm and register memory regions.
164163
// Build custom CPU config if a custom template is provided.
165164
let mut vm = Vm::new(&kvm)?;
166-
vm.memory_init(guest_memory)?;
167165

168166
let resource_allocator = ResourceAllocator::new()?;
169167

@@ -250,12 +248,18 @@ pub fn build_microvm_for_boot(
250248
let (mut vmm, mut vcpus) = create_vmm_and_vcpus(
251249
instance_info,
252250
event_manager,
253-
guest_memory,
254251
None,
255252
vm_resources.machine_config.vcpu_count,
256253
cpu_template.kvm_capabilities.clone(),
257254
)?;
258255

256+
for region in guest_memory {
257+
vmm.vm
258+
.register_memory_region(region)
259+
.map_err(VmmError::Vm)
260+
.map_err(StartMicrovmError::Internal)?;
261+
}
262+
259263
let entry_point = load_kernel(boot_config, vmm.guest_memory())?;
260264
let initrd = load_initrd_from_config(boot_config, vmm.guest_memory())?;
261265

@@ -433,7 +437,7 @@ pub fn build_microvm_from_snapshot(
433437
instance_info: &InstanceInfo,
434438
event_manager: &mut EventManager,
435439
microvm_state: MicrovmState,
436-
guest_memory: GuestMemoryMmap,
440+
guest_memory: Vec<GuestRegionMmap>,
437441
uffd: Option<Uffd>,
438442
seccomp_filters: &BpfThreadMap,
439443
vm_resources: &mut VmResources,
@@ -443,13 +447,17 @@ pub fn build_microvm_from_snapshot(
443447
let (mut vmm, mut vcpus) = create_vmm_and_vcpus(
444448
instance_info,
445449
event_manager,
446-
guest_memory,
447450
uffd,
448451
vm_resources.machine_config.vcpu_count,
449452
microvm_state.kvm_state.kvm_cap_modifiers.clone(),
450453
)
451454
.map_err(Internal)?;
452455

456+
vmm.vm
457+
.register_memory_regions(guest_memory)
458+
.map_err(VmmError::Vm)
459+
.map_err(StartMicrovmError::Internal)?;
460+
453461
#[cfg(target_arch = "x86_64")]
454462
{
455463
// Scale TSC to match, extract the TSC freq from the state if specified

src/vmm/src/device_manager/mmio.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -532,7 +532,7 @@ mod tests {
532532
use crate::devices::virtio::ActivateError;
533533
use crate::devices::virtio::device::{IrqTrigger, VirtioDevice};
534534
use crate::devices::virtio::queue::Queue;
535-
use crate::test_utils::multi_region_mem;
535+
use crate::test_utils::multi_region_mem_raw;
536536
use crate::vstate::kvm::Kvm;
537537
use crate::vstate::memory::{GuestAddress, GuestMemoryMmap};
538538

@@ -649,10 +649,10 @@ mod tests {
649649
fn test_register_virtio_device() {
650650
let start_addr1 = GuestAddress(0x0);
651651
let start_addr2 = GuestAddress(0x1000);
652-
let guest_mem = multi_region_mem(&[(start_addr1, 0x1000), (start_addr2, 0x1000)]);
652+
let guest_mem = multi_region_mem_raw(&[(start_addr1, 0x1000), (start_addr2, 0x1000)]);
653653
let kvm = Kvm::new(vec![]).expect("Cannot create Kvm");
654654
let mut vm = Vm::new(&kvm).unwrap();
655-
vm.memory_init(guest_mem).unwrap();
655+
vm.register_memory_regions(guest_mem).unwrap();
656656
let mut device_manager = MMIODeviceManager::new();
657657
let mut resource_allocator = ResourceAllocator::new().unwrap();
658658

@@ -680,10 +680,10 @@ mod tests {
680680
fn test_register_too_many_devices() {
681681
let start_addr1 = GuestAddress(0x0);
682682
let start_addr2 = GuestAddress(0x1000);
683-
let guest_mem = multi_region_mem(&[(start_addr1, 0x1000), (start_addr2, 0x1000)]);
683+
let guest_mem = multi_region_mem_raw(&[(start_addr1, 0x1000), (start_addr2, 0x1000)]);
684684
let kvm = Kvm::new(vec![]).expect("Cannot create Kvm");
685685
let mut vm = Vm::new(&kvm).unwrap();
686-
vm.memory_init(guest_mem).unwrap();
686+
vm.register_memory_regions(guest_mem).unwrap();
687687
let mut device_manager = MMIODeviceManager::new();
688688
let mut resource_allocator = ResourceAllocator::new().unwrap();
689689

@@ -736,10 +736,10 @@ mod tests {
736736
fn test_device_info() {
737737
let start_addr1 = GuestAddress(0x0);
738738
let start_addr2 = GuestAddress(0x1000);
739-
let guest_mem = multi_region_mem(&[(start_addr1, 0x1000), (start_addr2, 0x1000)]);
739+
let guest_mem = multi_region_mem_raw(&[(start_addr1, 0x1000), (start_addr2, 0x1000)]);
740740
let kvm = Kvm::new(vec![]).expect("Cannot create Kvm");
741741
let mut vm = Vm::new(&kvm).unwrap();
742-
vm.memory_init(guest_mem).unwrap();
742+
vm.register_memory_regions(guest_mem).unwrap();
743743

744744
#[cfg(target_arch = "x86_64")]
745745
vm.setup_irqchip().unwrap();

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

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,8 @@ mod tests {
378378
use crate::devices::virtio::block::virtio::device::FileEngineType;
379379
use crate::devices::virtio::mmio::VIRTIO_MMIO_INT_CONFIG;
380380
use crate::test_utils::create_tmp_socket;
381-
use crate::vstate::memory::{GuestAddress, GuestMemoryExtension};
381+
use crate::vstate::memory;
382+
use crate::vstate::memory::GuestAddress;
382383

383384
#[test]
384385
fn test_from_config() {
@@ -779,9 +780,10 @@ mod tests {
779780
let file = TempFile::new().unwrap().into_file();
780781
file.set_len(region_size as u64).unwrap();
781782
let regions = vec![(GuestAddress(0x0), region_size)];
782-
let guest_memory =
783-
GuestMemoryMmap::create(regions.into_iter(), libc::MAP_PRIVATE, Some(file), false)
784-
.unwrap();
783+
let guest_memory = GuestMemoryMmap::from_regions(
784+
memory::create(regions.into_iter(), libc::MAP_PRIVATE, Some(file), false).unwrap(),
785+
)
786+
.unwrap();
785787

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

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

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,8 @@ 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;
198+
use crate::vstate::memory::{Bitmap, Bytes, GuestMemory};
198199

199200
const FILE_LEN: u32 = 1024;
200201
// 2 pages of memory should be enough to test read/write ops and also dirty tracking.
@@ -230,10 +231,13 @@ pub mod tests {
230231
}
231232

232233
fn create_mem() -> GuestMemoryMmap {
233-
GuestMemoryMmap::anonymous(
234-
[(GuestAddress(0), MEM_LEN)].into_iter(),
235-
true,
236-
HugePageConfig::None,
234+
GuestMemoryMmap::from_regions(
235+
memory::anonymous(
236+
[(GuestAddress(0), MEM_LEN)].into_iter(),
237+
true,
238+
HugePageConfig::None,
239+
)
240+
.unwrap(),
237241
)
238242
.unwrap()
239243
}

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

Lines changed: 10 additions & 7 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::{GuestAddress, GuestMemoryExtension};
469+
use crate::vstate::memory;
470+
use crate::vstate::memory::GuestAddress;
470471

471472
#[test]
472473
fn test_new() {
@@ -763,9 +764,10 @@ mod tests {
763764
(GuestAddress(0x10000), region_size),
764765
];
765766

766-
let guest_memory =
767-
GuestMemoryMmap::create(regions.into_iter(), libc::MAP_PRIVATE, Some(file), false)
768-
.unwrap();
767+
let guest_memory = GuestMemoryMmap::from_regions(
768+
memory::create(regions.into_iter(), libc::MAP_PRIVATE, Some(file), false).unwrap(),
769+
)
770+
.unwrap();
769771

770772
vuh.update_mem_table(&guest_memory).unwrap();
771773

@@ -879,9 +881,10 @@ mod tests {
879881
file.set_len(region_size as u64).unwrap();
880882
let regions = vec![(GuestAddress(0x0), region_size)];
881883

882-
let guest_memory =
883-
GuestMemoryMmap::create(regions.into_iter(), libc::MAP_PRIVATE, Some(file), false)
884-
.unwrap();
884+
let guest_memory = GuestMemoryMmap::from_regions(
885+
memory::create(regions.into_iter(), libc::MAP_PRIVATE, Some(file), false).unwrap(),
886+
)
887+
.unwrap();
885888

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

src/vmm/src/persist.rs

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,8 @@ use crate::vmm_config::snapshot::{
3737
CreateSnapshotParams, LoadSnapshotParams, MemBackendType, SnapshotType,
3838
};
3939
use crate::vstate::kvm::KvmState;
40-
use crate::vstate::memory::{
41-
GuestMemory, GuestMemoryExtension, GuestMemoryMmap, GuestMemoryState, MemoryError,
42-
};
40+
use crate::vstate::memory;
41+
use crate::vstate::memory::{GuestMemoryExtension, GuestMemoryState, GuestRegionMmap, MemoryError};
4342
use crate::vstate::vcpu::{VcpuSendEventError, VcpuState};
4443
use crate::vstate::vm::VmState;
4544
use crate::{EventManager, Vmm, VmmError, mem_size_mib, vstate};
@@ -532,10 +531,9 @@ fn guest_memory_from_file(
532531
mem_file_path: &Path,
533532
mem_state: &GuestMemoryState,
534533
track_dirty_pages: bool,
535-
) -> Result<GuestMemoryMmap, GuestMemoryFromFileError> {
534+
) -> Result<Vec<GuestRegionMmap>, GuestMemoryFromFileError> {
536535
let mem_file = File::open(mem_file_path)?;
537-
let guest_mem =
538-
GuestMemoryMmap::snapshot_file(mem_file, mem_state.regions(), track_dirty_pages)?;
536+
let guest_mem = memory::snapshot_file(mem_file, mem_state.regions(), track_dirty_pages)?;
539537
Ok(guest_mem)
540538
}
541539

@@ -560,7 +558,7 @@ fn guest_memory_from_uffd(
560558
track_dirty_pages: bool,
561559
enable_balloon: bool,
562560
huge_pages: HugePageConfig,
563-
) -> Result<(GuestMemoryMmap, Option<Uffd>), GuestMemoryFromUffdError> {
561+
) -> Result<(Vec<GuestRegionMmap>, Option<Uffd>), GuestMemoryFromUffdError> {
564562
let (guest_memory, backend_mappings) =
565563
create_guest_memory(mem_state, track_dirty_pages, huge_pages)?;
566564

@@ -593,10 +591,9 @@ fn create_guest_memory(
593591
mem_state: &GuestMemoryState,
594592
track_dirty_pages: bool,
595593
huge_pages: HugePageConfig,
596-
) -> Result<(GuestMemoryMmap, Vec<GuestRegionUffdMapping>), GuestMemoryFromUffdError> {
597-
let guest_memory =
598-
GuestMemoryMmap::anonymous(mem_state.regions(), track_dirty_pages, huge_pages)?;
599-
let mut backend_mappings = Vec::with_capacity(guest_memory.num_regions());
594+
) -> Result<(Vec<GuestRegionMmap>, Vec<GuestRegionUffdMapping>), GuestMemoryFromUffdError> {
595+
let guest_memory = memory::anonymous(mem_state.regions(), track_dirty_pages, huge_pages)?;
596+
let mut backend_mappings = Vec::with_capacity(guest_memory.len());
600597
let mut offset = 0;
601598
for mem_region in guest_memory.iter() {
602599
#[allow(deprecated)]

src/vmm/src/resources.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ use crate::vmm_config::metrics::{MetricsConfig, MetricsConfigError, init_metrics
2929
use crate::vmm_config::mmds::{MmdsConfig, MmdsConfigError};
3030
use crate::vmm_config::net::*;
3131
use crate::vmm_config::vsock::*;
32-
use crate::vstate::memory::{GuestMemoryExtension, GuestMemoryMmap, MemoryError};
32+
use crate::vstate::memory;
33+
use crate::vstate::memory::{GuestRegionMmap, MemoryError};
3334

3435
/// Errors encountered when configuring microVM resources.
3536
#[derive(Debug, thiserror::Error, displaydoc::Display)]
@@ -440,7 +441,7 @@ impl VmResources {
440441
///
441442
/// If vhost-user-blk devices are in use, allocates memfd-backed shared memory, otherwise
442443
/// prefers anonymous memory for performance reasons.
443-
pub fn allocate_guest_memory(&self) -> Result<GuestMemoryMmap, MemoryError> {
444+
pub fn allocate_guest_memory(&self) -> Result<Vec<GuestRegionMmap>, MemoryError> {
444445
let vhost_user_device_used = self
445446
.block
446447
.devices
@@ -460,13 +461,13 @@ impl VmResources {
460461
self.machine_config.mem_size_mib << MIB_TO_BYTES_SHIFT,
461462
);
462463
if vhost_user_device_used {
463-
GuestMemoryMmap::memfd_backed(
464+
memory::memfd_backed(
464465
regions.as_ref(),
465466
self.machine_config.track_dirty_pages,
466467
self.machine_config.huge_pages,
467468
)
468469
} else {
469-
GuestMemoryMmap::anonymous(
470+
memory::anonymous(
470471
regions.into_iter(),
471472
self.machine_config.track_dirty_pages,
472473
self.machine_config.huge_pages,

src/vmm/src/test_utils/mod.rs

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ 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;
19+
use crate::vstate::memory::{GuestMemoryMmap, GuestRegionMmap};
1920
use crate::{EventManager, Vmm};
2021

2122
pub mod mock_resources;
@@ -26,15 +27,31 @@ pub fn single_region_mem(region_size: usize) -> GuestMemoryMmap {
2627
single_region_mem_at(0, region_size)
2728
}
2829

30+
pub fn single_region_mem_raw(region_size: usize) -> Vec<GuestRegionMmap> {
31+
single_region_mem_at_raw(0, region_size)
32+
}
33+
2934
/// Creates a [`GuestMemoryMmap`] with a single region of the given size starting at the given
3035
/// guest physical address `at` and without dirty tracking.
3136
pub fn single_region_mem_at(at: u64, size: usize) -> GuestMemoryMmap {
3237
multi_region_mem(&[(GuestAddress(at), size)])
3338
}
3439

40+
pub fn single_region_mem_at_raw(at: u64, size: usize) -> Vec<GuestRegionMmap> {
41+
multi_region_mem_raw(&[(GuestAddress(at), size)])
42+
}
43+
3544
/// Creates a [`GuestMemoryMmap`] with multiple regions and without dirty page tracking.
3645
pub fn multi_region_mem(regions: &[(GuestAddress, usize)]) -> GuestMemoryMmap {
37-
GuestMemoryMmap::anonymous(regions.iter().copied(), false, HugePageConfig::None)
46+
GuestMemoryMmap::from_regions(
47+
memory::anonymous(regions.iter().copied(), false, HugePageConfig::None)
48+
.expect("Cannot initialize memory"),
49+
)
50+
.unwrap()
51+
}
52+
53+
pub fn multi_region_mem_raw(regions: &[(GuestAddress, usize)]) -> Vec<GuestRegionMmap> {
54+
memory::anonymous(regions.iter().copied(), false, HugePageConfig::None)
3855
.expect("Cannot initialize memory")
3956
}
4057

@@ -44,6 +61,10 @@ pub fn arch_mem(mem_size_bytes: usize) -> GuestMemoryMmap {
4461
multi_region_mem(&crate::arch::arch_memory_regions(mem_size_bytes))
4562
}
4663

64+
pub fn arch_mem_raw(mem_size_bytes: usize) -> Vec<GuestRegionMmap> {
65+
multi_region_mem_raw(&crate::arch::arch_memory_regions(mem_size_bytes))
66+
}
67+
4768
pub fn create_vmm(
4869
_kernel_image: Option<&str>,
4970
is_diff: bool,

0 commit comments

Comments
 (0)