Skip to content

Commit 2b182c6

Browse files
committed
refactor: store GuestMemoryMmap inside struct Vm
Semantically, this is where it belong - the memory is associated with the virtual machine, not the virtual machine manager. But independently of this, it is needed for borrowchk reasons: In the future, each Vm will have two guest memory regions associated with it. One for traditional guest memory, and another that is dedicated to I/O (swiotlb region). Storing these two GuestMemoryMmap in `struct Vm` allows for a function as follows: fn io_memory(&self) -> &GuestMemoryMmap { self.io_memory.as_ref() .unwrap_or(&self.normal_memory) } Such a function cannot live in `struct Vmm`, as that would mean borrowing the guest memory implies borrowing the entire `Vmm` object (because rustc is not intelligent enough to project split borrows past function calls - e.g. it doesn't know the references returned by io_memory() really only borrows the io_memory and normal_memory fields, not everything else.). However, this means it cannot be used in callsites where such splitting of borrows is required (e.g. everywhere where both a guest memory reference _and_ another Vmm field are passed by reference to a function). The `Option`-ness of the the guest_memory field is transitory. Signed-off-by: Patrick Roy <[email protected]>
1 parent acab782 commit 2b182c6

File tree

10 files changed

+106
-98
lines changed

10 files changed

+106
-98
lines changed

src/vmm/src/acpi/mod.rs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ mod tests {
215215
// A mocke Vmm object with 128MBs of memory
216216
let mut vmm = default_vmm();
217217
let mut writer = AcpiTableWriter {
218-
mem: &vmm.guest_memory,
218+
mem: vmm.vm.guest_memory(),
219219
resource_allocator: &mut vmm.resource_allocator,
220220
};
221221

@@ -264,13 +264,15 @@ mod tests {
264264
#[test]
265265
fn test_write_acpi_table_small_memory() {
266266
let mut vmm = default_vmm();
267-
vmm.guest_memory = arch_mem(
268-
(SYSTEM_MEM_START + SYSTEM_MEM_SIZE - 4096)
269-
.try_into()
270-
.unwrap(),
271-
);
267+
vmm.vm
268+
.memory_init(arch_mem(
269+
(SYSTEM_MEM_START + SYSTEM_MEM_SIZE - 4096)
270+
.try_into()
271+
.unwrap(),
272+
))
273+
.unwrap();
272274
let mut writer = AcpiTableWriter {
273-
mem: &vmm.guest_memory,
275+
mem: vmm.vm.guest_memory(),
274276
resource_allocator: &mut vmm.resource_allocator,
275277
};
276278

src/vmm/src/builder.rs

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ fn create_vmm_and_vcpus(
163163
// Set up Kvm Vm and register memory regions.
164164
// Build custom CPU config if a custom template is provided.
165165
let mut vm = Vm::new(&kvm)?;
166-
vm.memory_init(&guest_memory)?;
166+
vm.memory_init(guest_memory)?;
167167

168168
let resource_allocator = ResourceAllocator::new()?;
169169

@@ -199,7 +199,6 @@ fn create_vmm_and_vcpus(
199199
shutdown_exit_code: None,
200200
kvm,
201201
vm,
202-
guest_memory,
203202
uffd,
204203
vcpus_handles: Vec::new(),
205204
vcpus_exit_evt,
@@ -488,7 +487,7 @@ pub fn build_microvm_from_snapshot(
488487

489488
// Restore devices states.
490489
let mmio_ctor_args = MMIODevManagerConstructorArgs {
491-
mem: &vmm.guest_memory,
490+
mem: vmm.vm.guest_memory(),
492491
vm: vmm.vm.fd(),
493492
event_manager,
494493
resource_allocator: &mut vmm.resource_allocator,
@@ -504,7 +503,7 @@ pub fn build_microvm_from_snapshot(
504503

505504
{
506505
let acpi_ctor_args = ACPIDeviceManagerConstructorArgs {
507-
mem: &vmm.guest_memory,
506+
mem: vmm.vm.guest_memory(),
508507
resource_allocator: &mut vmm.resource_allocator,
509508
vm: vmm.vm.fd(),
510509
};
@@ -795,7 +794,7 @@ pub fn configure_system_for_boot(
795794
)
796795
.map_err(LoadCommandline)?;
797796
crate::arch::x86_64::configure_system(
798-
&vmm.guest_memory,
797+
vmm.vm.guest_memory(),
799798
&mut vmm.resource_allocator,
800799
crate::vstate::memory::GuestAddress(crate::arch::x86_64::layout::CMDLINE_START),
801800
cmdline_size,
@@ -808,7 +807,7 @@ pub fn configure_system_for_boot(
808807
// Create ACPI tables and write them in guest memory
809808
// For the time being we only support ACPI in x86_64
810809
acpi::create_acpi_tables(
811-
&vmm.guest_memory,
810+
vmm.vm.guest_memory(),
812811
&mut vmm.resource_allocator,
813812
&vmm.mmio_device_manager,
814813
&vmm.acpi_device_manager,
@@ -835,7 +834,7 @@ pub fn configure_system_for_boot(
835834
.collect();
836835
let cmdline = boot_cmdline.as_cstring()?;
837836
crate::arch::aarch64::configure_system(
838-
&vmm.guest_memory,
837+
&vmm.vm.guest_memory(),
839838
cmdline,
840839
vcpu_mpidr,
841840
vmm.mmio_device_manager.get_device_info(),
@@ -891,7 +890,7 @@ pub(crate) fn attach_boot_timer_device(
891890
}
892891

893892
fn attach_vmgenid_device(vmm: &mut Vmm) -> Result<(), StartMicrovmError> {
894-
let vmgenid = VmGenId::new(&vmm.guest_memory, &mut vmm.resource_allocator)
893+
let vmgenid = VmGenId::new(vmm.vm.guest_memory(), &mut vmm.resource_allocator)
895894
.map_err(StartMicrovmError::CreateVMGenID)?;
896895

897896
vmm.acpi_device_manager
@@ -1088,7 +1087,7 @@ pub(crate) mod tests {
10881087
}
10891088

10901089
pub(crate) fn default_vmm() -> Vmm {
1091-
let (kvm, mut vm, guest_memory) = setup_vm_with_memory(128 << MIB_TO_BYTES_SHIFT);
1090+
let (kvm, mut vm) = setup_vm_with_memory(128 << MIB_TO_BYTES_SHIFT);
10921091

10931092
let mmio_device_manager = MMIODeviceManager::new();
10941093
let acpi_device_manager = ACPIDeviceManager::new();
@@ -1116,7 +1115,6 @@ pub(crate) mod tests {
11161115
shutdown_exit_code: None,
11171116
kvm,
11181117
vm,
1119-
guest_memory,
11201118
uffd: None,
11211119
vcpus_handles: Vec::new(),
11221120
vcpus_exit_evt,

src/vmm/src/device_manager/legacy.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ mod tests {
248248

249249
#[test]
250250
fn test_register_legacy_devices() {
251-
let (_, vm, _) = setup_vm_with_memory(0x1000);
251+
let (_, vm) = setup_vm_with_memory(0x1000);
252252
vm.setup_irqchip().unwrap();
253253
let mut ldm = PortIODeviceManager::new(
254254
Arc::new(Mutex::new(BusDevice::Serial(SerialDevice {

src/vmm/src/device_manager/mmio.rs

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -652,7 +652,7 @@ mod tests {
652652
let guest_mem = multi_region_mem(&[(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.memory_init(guest_mem).unwrap();
656656
let mut device_manager = MMIODeviceManager::new();
657657
let mut resource_allocator = ResourceAllocator::new().unwrap();
658658

@@ -666,7 +666,7 @@ mod tests {
666666
device_manager
667667
.register_virtio_test_device(
668668
vm.fd(),
669-
guest_mem,
669+
vm.guest_memory().clone(),
670670
&mut resource_allocator,
671671
dummy,
672672
&mut cmdline,
@@ -683,7 +683,7 @@ mod tests {
683683
let guest_mem = multi_region_mem(&[(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.memory_init(guest_mem).unwrap();
687687
let mut device_manager = MMIODeviceManager::new();
688688
let mut resource_allocator = ResourceAllocator::new().unwrap();
689689

@@ -697,7 +697,7 @@ mod tests {
697697
device_manager
698698
.register_virtio_test_device(
699699
vm.fd(),
700-
guest_mem.clone(),
700+
vm.guest_memory().clone(),
701701
&mut resource_allocator,
702702
Arc::new(Mutex::new(DummyDevice::new())),
703703
&mut cmdline,
@@ -711,7 +711,7 @@ mod tests {
711711
device_manager
712712
.register_virtio_test_device(
713713
vm.fd(),
714-
guest_mem,
714+
vm.guest_memory().clone(),
715715
&mut resource_allocator,
716716
Arc::new(Mutex::new(DummyDevice::new())),
717717
&mut cmdline,
@@ -739,9 +739,7 @@ mod tests {
739739
let guest_mem = multi_region_mem(&[(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();
743-
744-
let mem_clone = guest_mem.clone();
742+
vm.memory_init(guest_mem).unwrap();
745743

746744
#[cfg(target_arch = "x86_64")]
747745
vm.setup_irqchip().unwrap();
@@ -758,7 +756,7 @@ mod tests {
758756
let addr = device_manager
759757
.register_virtio_test_device(
760758
vm.fd(),
761-
guest_mem,
759+
vm.guest_memory().clone(),
762760
&mut resource_allocator,
763761
dummy,
764762
&mut cmdline,
@@ -794,7 +792,7 @@ mod tests {
794792
device_manager
795793
.register_virtio_test_device(
796794
vm.fd(),
797-
mem_clone,
795+
vm.guest_memory().clone(),
798796
&mut resource_allocator,
799797
dummy2,
800798
&mut cmdline,

src/vmm/src/lib.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,6 @@ pub struct Vmm {
314314
// Guest VM core resources.
315315
kvm: Kvm,
316316
vm: Vm,
317-
guest_memory: GuestMemoryMmap,
318317
// Save UFFD in order to keep it open in the Firecracker process, as well.
319318
uffd: Option<Uffd>,
320319
vcpus_handles: Vec<VcpuHandle>,
@@ -450,7 +449,7 @@ impl Vmm {
450449

451450
/// Returns a reference to the inner `GuestMemoryMmap` object.
452451
pub fn guest_memory(&self) -> &GuestMemoryMmap {
453-
&self.guest_memory
452+
self.vm.guest_memory()
454453
}
455454

456455
/// Sets RDA bit in serial console
@@ -602,7 +601,7 @@ impl Vmm {
602601

603602
/// Retrieves the KVM dirty bitmap for each of the guest's memory regions.
604603
pub fn reset_dirty_bitmap(&self) {
605-
self.guest_memory
604+
self.guest_memory()
606605
.iter()
607606
.enumerate()
608607
.for_each(|(slot, region)| {
@@ -616,7 +615,7 @@ impl Vmm {
616615
/// Retrieves the KVM dirty bitmap for each of the guest's memory regions.
617616
pub fn get_dirty_bitmap(&self) -> Result<DirtyBitmap, VmmError> {
618617
let mut bitmap: DirtyBitmap = HashMap::new();
619-
self.guest_memory
618+
self.guest_memory()
620619
.iter()
621620
.enumerate()
622621
.try_for_each(|(slot, region)| {

src/vmm/src/vstate/vcpu/aarch64.rs

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -313,22 +313,21 @@ mod tests {
313313
use crate::cpu_config::templates::RegisterValueFilter;
314314
use crate::vcpu::VcpuConfig;
315315
use crate::vstate::kvm::Kvm;
316-
use crate::vstate::memory::GuestMemoryMmap;
317316
use crate::vstate::vm::Vm;
318317
use crate::vstate::vm::tests::setup_vm_with_memory;
319318

320-
fn setup_vcpu(mem_size: usize) -> (Kvm, Vm, KvmVcpu, GuestMemoryMmap) {
321-
let (kvm, mut vm, vm_mem) = setup_vm_with_memory(mem_size);
319+
fn setup_vcpu(mem_size: usize) -> (Kvm, Vm, KvmVcpu) {
320+
let (kvm, mut vm) = setup_vm_with_memory(mem_size);
322321
let mut vcpu = KvmVcpu::new(0, &vm).unwrap();
323322
vcpu.init(&[]).unwrap();
324323
vm.setup_irqchip(1).unwrap();
325324

326-
(kvm, vm, vcpu, vm_mem)
325+
(kvm, vm, vcpu)
327326
}
328327

329328
#[test]
330329
fn test_create_vcpu() {
331-
let (_, vm, _) = setup_vm_with_memory(0x1000);
330+
let (_, vm) = setup_vm_with_memory(0x1000);
332331

333332
unsafe { libc::close(vm.fd().as_raw_fd()) };
334333

@@ -344,7 +343,7 @@ mod tests {
344343

345344
#[test]
346345
fn test_configure_vcpu() {
347-
let (kvm, _, mut vcpu, vm_mem) = setup_vcpu(0x10000);
346+
let (kvm, vm, mut vcpu) = setup_vcpu(0x10000);
348347
let optional_capabilities = kvm.optional_capabilities();
349348

350349
let vcpu_config = VcpuConfig {
@@ -354,7 +353,7 @@ mod tests {
354353
};
355354

356355
vcpu.configure(
357-
&vm_mem,
356+
vm.guest_memory(),
358357
EntryPoint {
359358
entry_addr: GuestAddress(crate::arch::get_kernel_start()),
360359
protocol: BootProtocol::LinuxBoot,
@@ -367,7 +366,7 @@ mod tests {
367366
unsafe { libc::close(vcpu.fd.as_raw_fd()) };
368367

369368
let err = vcpu.configure(
370-
&vm_mem,
369+
vm.guest_memory(),
371370
EntryPoint {
372371
entry_addr: GuestAddress(crate::arch::get_kernel_start()),
373372
protocol: BootProtocol::LinuxBoot,
@@ -389,7 +388,7 @@ mod tests {
389388

390389
#[test]
391390
fn test_init_vcpu() {
392-
let (_, mut vm, _) = setup_vm_with_memory(0x1000);
391+
let (_, mut vm) = setup_vm_with_memory(0x1000);
393392
let mut vcpu = KvmVcpu::new(0, &vm).unwrap();
394393
vm.setup_irqchip(1).unwrap();
395394

@@ -408,7 +407,7 @@ mod tests {
408407

409408
#[test]
410409
fn test_vcpu_save_restore_state() {
411-
let (_, mut vm, _) = setup_vm_with_memory(0x1000);
410+
let (_, mut vm) = setup_vm_with_memory(0x1000);
412411
let mut vcpu = KvmVcpu::new(0, &vm).unwrap();
413412
vm.setup_irqchip(1).unwrap();
414413

@@ -452,7 +451,7 @@ mod tests {
452451
//
453452
// This should fail with ENOEXEC.
454453
// https://elixir.bootlin.com/linux/v5.10.176/source/arch/arm64/kvm/arm.c#L1165
455-
let (_, mut vm, _) = setup_vm_with_memory(0x1000);
454+
let (_, mut vm) = setup_vm_with_memory(0x1000);
456455
let vcpu = KvmVcpu::new(0, &vm).unwrap();
457456
vm.setup_irqchip(1).unwrap();
458457

@@ -462,7 +461,7 @@ mod tests {
462461
#[test]
463462
fn test_dump_cpu_config_after_init() {
464463
// Test `dump_cpu_config()` after `KVM_VCPU_INIT`.
465-
let (_, mut vm, _) = setup_vm_with_memory(0x1000);
464+
let (_, mut vm) = setup_vm_with_memory(0x1000);
466465
let mut vcpu = KvmVcpu::new(0, &vm).unwrap();
467466
vm.setup_irqchip(1).unwrap();
468467
vcpu.init(&[]).unwrap();
@@ -472,7 +471,7 @@ mod tests {
472471

473472
#[test]
474473
fn test_setup_non_boot_vcpu() {
475-
let (_, vm, _) = setup_vm_with_memory(0x1000);
474+
let (_, vm) = setup_vm_with_memory(0x1000);
476475
let mut vcpu1 = KvmVcpu::new(0, &vm).unwrap();
477476
vcpu1.init(&[]).unwrap();
478477
let mut vcpu2 = KvmVcpu::new(1, &vm).unwrap();
@@ -484,15 +483,15 @@ mod tests {
484483
// Test `get_regs()` with valid register IDs.
485484
// - X0: 0x6030 0000 0010 0000
486485
// - X1: 0x6030 0000 0010 0002
487-
let (_, _, vcpu, _) = setup_vcpu(0x10000);
486+
let (_, _, vcpu) = setup_vcpu(0x10000);
488487
let reg_list = Vec::<u64>::from([0x6030000000100000, 0x6030000000100002]);
489488
get_registers(&vcpu.fd, &reg_list, &mut Aarch64RegisterVec::default()).unwrap();
490489
}
491490

492491
#[test]
493492
fn test_get_invalid_regs() {
494493
// Test `get_regs()` with invalid register IDs.
495-
let (_, _, vcpu, _) = setup_vcpu(0x10000);
494+
let (_, _, vcpu) = setup_vcpu(0x10000);
496495
let reg_list = Vec::<u64>::from([0x6030000000100001, 0x6030000000100003]);
497496
get_registers(&vcpu.fd, &reg_list, &mut Aarch64RegisterVec::default()).unwrap_err();
498497
}

0 commit comments

Comments
 (0)