Skip to content

Commit 196c465

Browse files
alexandruagacatangiu
authored andcommitted
vmm: changes to the Vmm interface
Added the pub modifier to some struct Vmm methods, the possibility to specify a GuestMemory object directly (also to get a handle to the current GuestMemory object), and a function which returns a reference to the inner Vm object of the Vmm. Signed-off-by: Alexandru Agache <[email protected]>
1 parent fc75ec7 commit 196c465

File tree

1 file changed

+80
-32
lines changed

1 file changed

+80
-32
lines changed

vmm/src/lib.rs

Lines changed: 80 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,7 @@ type Result<T> = std::result::Result<T, Error>;
459459

460460
/// Describes all possible reasons which may cause the event loop to return to the caller in
461461
/// the absence of errors.
462+
#[derive(Debug)]
462463
pub enum EventLoopExitReason {
463464
/// A break statement interrupted the event loop during normal execution. This is the
464465
/// default exit reason.
@@ -779,7 +780,8 @@ pub struct VmmConfig {
779780
vsock_device: Option<VsockDeviceConfig>,
780781
}
781782

782-
struct Vmm {
783+
/// Contains the state and associated methods required for the Firecracker VMM.
784+
pub struct Vmm {
783785
kvm: KvmContext,
784786

785787
vm_config: VmConfig,
@@ -813,7 +815,8 @@ struct Vmm {
813815
}
814816

815817
impl Vmm {
816-
fn new(
818+
/// Creates a new VMM object.
819+
pub fn new(
817820
api_shared_info: Arc<RwLock<InstanceInfo>>,
818821
control_fd: &AsRawFd,
819822
from_api: Receiver<Box<VmmAction>>,
@@ -1096,16 +1099,20 @@ impl Vmm {
10961099
}
10971100

10981101
fn init_guest_memory(&mut self) -> std::result::Result<(), StartMicrovmError> {
1099-
let mem_size = self
1100-
.vm_config
1101-
.mem_size_mib
1102-
.ok_or(StartMicrovmError::GuestMemory(
1103-
memory_model::GuestMemoryError::MemoryNotInitialized,
1104-
))?
1105-
<< 20;
1106-
let arch_mem_regions = arch::arch_memory_regions(mem_size);
1107-
self.guest_memory =
1108-
Some(GuestMemory::new(&arch_mem_regions).map_err(StartMicrovmError::GuestMemory)?);
1102+
if self.guest_memory().is_none() {
1103+
let mem_size = self
1104+
.vm_config
1105+
.mem_size_mib
1106+
.ok_or(StartMicrovmError::GuestMemory(
1107+
memory_model::GuestMemoryError::MemoryNotInitialized,
1108+
))?
1109+
<< 20;
1110+
let arch_mem_regions = arch::arch_memory_regions(mem_size);
1111+
self.set_guest_memory(
1112+
GuestMemory::new(&arch_mem_regions).map_err(StartMicrovmError::GuestMemory)?,
1113+
);
1114+
}
1115+
11091116
self.vm
11101117
.memory_init(
11111118
self.guest_memory
@@ -1443,7 +1450,18 @@ impl Vmm {
14431450
Ok(())
14441451
}
14451452

1446-
fn start_microvm(&mut self) -> std::result::Result<VmmData, VmmActionError> {
1453+
/// Set the guest memory based on a pre-constructed `GuestMemory` object.
1454+
pub fn set_guest_memory(&mut self, guest_memory: GuestMemory) {
1455+
self.guest_memory = Some(guest_memory);
1456+
}
1457+
1458+
/// Returns a reference to the inner `GuestMemory` object if present, or `None` otherwise.
1459+
pub fn guest_memory(&self) -> Option<&GuestMemory> {
1460+
self.guest_memory.as_ref()
1461+
}
1462+
1463+
/// Set up the initial microVM state and start the vCPU threads.
1464+
pub fn start_microvm(&mut self) -> std::result::Result<VmmData, VmmActionError> {
14471465
info!("VMM received instance start command");
14481466
if self.is_instance_initialized() {
14491467
Err(StartMicrovmError::MicroVMAlreadyRunning)?;
@@ -1568,6 +1586,8 @@ impl Vmm {
15681586
Ok(())
15691587
}
15701588

1589+
/// Wait on VMM events and dispatch them to the appropriate handler. Returns to the caller
1590+
/// when a control action occurs.
15711591
fn run_event_loop(&mut self) -> Result<EventLoopExitReason> {
15721592
// TODO: try handling of errors/failures without breaking this main loop.
15731593
loop {
@@ -1660,13 +1680,13 @@ impl Vmm {
16601680
.unwrap_or(0 as usize)
16611681
};
16621682

1663-
self.guest_memory
1664-
.as_ref()
1683+
self.guest_memory()
16651684
.map(|ref mem| mem.map_and_fold(0, dirty_pages_in_region, std::ops::Add::add))
16661685
.unwrap_or(0)
16671686
}
16681687

1669-
fn configure_boot_source(
1688+
/// Set the guest boot source configuration.
1689+
pub fn configure_boot_source(
16701690
&mut self,
16711691
kernel_image_path: String,
16721692
kernel_cmdline: Option<String>,
@@ -1700,7 +1720,8 @@ impl Vmm {
17001720
Ok(VmmData::Empty)
17011721
}
17021722

1703-
fn set_vm_configuration(
1723+
/// Set the machine configuration of the microVM.
1724+
pub fn set_vm_configuration(
17041725
&mut self,
17051726
machine_config: VmConfig,
17061727
) -> std::result::Result<VmmData, VmmActionError> {
@@ -1745,7 +1766,8 @@ impl Vmm {
17451766
Ok(VmmData::Empty)
17461767
}
17471768

1748-
fn insert_net_device(
1769+
/// Inserts a network device to be attached when the VM starts.
1770+
pub fn insert_net_device(
17491771
&mut self,
17501772
body: NetworkInterfaceConfig,
17511773
) -> std::result::Result<VmmData, VmmActionError> {
@@ -1823,7 +1845,8 @@ impl Vmm {
18231845
Ok(VmmData::Empty)
18241846
}
18251847

1826-
fn set_vsock_device(
1848+
/// Sets a vsock device to be attached when the VM starts.
1849+
pub fn set_vsock_device(
18271850
&mut self,
18281851
config: VsockDeviceConfig,
18291852
) -> std::result::Result<VmmData, VmmActionError> {
@@ -1904,9 +1927,10 @@ impl Vmm {
19041927
Err(VmmActionError::from(DriveError::InvalidBlockDeviceID))
19051928
}
19061929

1930+
/// Inserts a block to be attached when the VM starts.
19071931
// Only call this function as part of the API.
19081932
// If the drive_id does not exist, a new Block Device Config is added to the list.
1909-
fn insert_block_device(
1933+
pub fn insert_block_device(
19101934
&mut self,
19111935
block_device_config: BlockDeviceConfig,
19121936
) -> std::result::Result<VmmData, VmmActionError> {
@@ -2093,6 +2117,11 @@ impl Vmm {
20932117
}
20942118
Ok(())
20952119
}
2120+
2121+
/// Returns a reference to the inner KVM Vm object.
2122+
pub fn kvm_vm(&self) -> &Vm {
2123+
&self.vm
2124+
}
20962125
}
20972126

20982127
// Can't derive PartialEq directly because the sender members can't be compared.
@@ -2647,7 +2676,7 @@ mod tests {
26472676
assert!(mmio_device
26482677
.device_mut()
26492678
.activate(
2650-
vmm.guest_memory.as_ref().unwrap().clone(),
2679+
vmm.guest_memory().unwrap().clone(),
26512680
EventFd::new().unwrap(),
26522681
Arc::new(AtomicUsize::new(0)),
26532682
vec![Queue::new(0), Queue::new(0)],
@@ -2886,7 +2915,7 @@ mod tests {
28862915
// Test that creating a new block device returns the correct output.
28872916
assert!(vmm.insert_block_device(root_block_device.clone()).is_ok());
28882917
assert!(vmm.init_guest_memory().is_ok());
2889-
assert!(vmm.guest_memory.is_some());
2918+
assert!(vmm.guest_memory().is_some());
28902919
assert!(vmm.setup_interrupt_controller().is_ok());
28912920

28922921
vmm.default_kernel_config(None);
@@ -2910,7 +2939,7 @@ mod tests {
29102939
// Test that creating a new block device returns the correct output.
29112940
assert!(vmm.insert_block_device(root_block_device.clone()).is_ok());
29122941
assert!(vmm.init_guest_memory().is_ok());
2913-
assert!(vmm.guest_memory.is_some());
2942+
assert!(vmm.guest_memory().is_some());
29142943
assert!(vmm.setup_interrupt_controller().is_ok());
29152944

29162945
vmm.default_kernel_config(None);
@@ -2938,7 +2967,7 @@ mod tests {
29382967
.insert_block_device(non_root_block_device.clone())
29392968
.is_ok());
29402969
assert!(vmm.init_guest_memory().is_ok());
2941-
assert!(vmm.guest_memory.is_some());
2970+
assert!(vmm.guest_memory().is_some());
29422971
assert!(vmm.setup_interrupt_controller().is_ok());
29432972

29442973
vmm.default_kernel_config(None);
@@ -2991,7 +3020,7 @@ mod tests {
29913020
fn test_attach_net_devices() {
29923021
let mut vmm = create_vmm_object(InstanceState::Uninitialized);
29933022
assert!(vmm.init_guest_memory().is_ok());
2994-
assert!(vmm.guest_memory.is_some());
3023+
assert!(vmm.guest_memory().is_some());
29953024

29963025
vmm.default_kernel_config(None);
29973026
vmm.setup_interrupt_controller()
@@ -3096,7 +3125,7 @@ mod tests {
30963125
.is_ok());
30973126

30983127
assert!(vmm.init_guest_memory().is_ok());
3099-
assert!(vmm.guest_memory.is_some());
3128+
assert!(vmm.guest_memory().is_some());
31003129
assert!(vmm.setup_interrupt_controller().is_ok());
31013130

31023131
vmm.init_mmio_device_manager()
@@ -3418,11 +3447,11 @@ mod tests {
34183447
fn test_attach_legacy_devices_without_uart() {
34193448
let mut vmm = create_vmm_object(InstanceState::Uninitialized);
34203449
assert!(vmm.init_guest_memory().is_ok());
3421-
assert!(vmm.guest_memory.is_some());
3450+
assert!(vmm.guest_memory().is_some());
34223451

3423-
let guest_mem = vmm.guest_memory.clone().unwrap();
3452+
let guest_mem = vmm.guest_memory().unwrap().clone();
34243453
let device_manager = MMIODeviceManager::new(
3425-
guest_mem.clone(),
3454+
guest_mem,
34263455
&mut (arch::get_reserved_mem_addr() as u64),
34273456
(arch::IRQ_BASE, arch::IRQ_MAX),
34283457
);
@@ -3456,11 +3485,11 @@ mod tests {
34563485
fn test_attach_legacy_devices_with_uart() {
34573486
let mut vmm = create_vmm_object(InstanceState::Uninitialized);
34583487
assert!(vmm.init_guest_memory().is_ok());
3459-
assert!(vmm.guest_memory.is_some());
3488+
assert!(vmm.guest_memory().is_some());
34603489

3461-
let guest_mem = vmm.guest_memory.clone().unwrap();
3490+
let guest_mem = vmm.guest_memory().unwrap().clone();
34623491
let device_manager = MMIODeviceManager::new(
3463-
guest_mem.clone(),
3492+
guest_mem,
34643493
&mut (arch::get_reserved_mem_addr() as u64),
34653494
(arch::IRQ_BASE, arch::IRQ_MAX),
34663495
);
@@ -4167,4 +4196,23 @@ mod tests {
41674196
"VsockConfig(User, UpdateNotAllowedPostBoot)"
41684197
);
41694198
}
4199+
4200+
#[test]
4201+
fn test_misc() {
4202+
let mut vmm = create_vmm_object(InstanceState::Uninitialized);
4203+
4204+
assert!(vmm.guest_memory().is_none());
4205+
4206+
let mem = GuestMemory::new(&[(GuestAddress(0x1000), 0x100)]).unwrap();
4207+
vmm.set_guest_memory(mem);
4208+
4209+
let mem_ref = vmm.guest_memory().unwrap();
4210+
assert_eq!(mem_ref.num_regions(), 1);
4211+
assert_eq!(mem_ref.end_addr(), GuestAddress(0x1100));
4212+
4213+
assert_eq!(
4214+
vmm.kvm_vm().get_fd().as_raw_fd(),
4215+
vmm.vm.get_fd().as_raw_fd()
4216+
);
4217+
}
41704218
}

0 commit comments

Comments
 (0)