Compare commits

...

3 Commits

Author SHA1 Message Date
Muminul Islam 0461c3080e vmm: pause/resume VM during the VM events
For MSHV we always create frozen partition, so we
resume the VM during boot. Also during pause and resume
VM events we call hypervisor specific API.

Signed-off-by: Muminul Islam <muislam@microsoft.com>
2024-05-09 15:03:14 -07:00
Muminul Islam c973524a88 hypervisor: always create a frozen partition
Create a partition frozen always, then unfreeze the partition
during boot phase or resume phase. We also freeze the
partition during pause event. Time is freeze during the
time between freeze and unfreeze.

Signed-off-by: Muminul Islam <muislam@microsoft.com>
2024-05-09 15:03:14 -07:00
Muminul Islam d8b0145184 hypervisor: implement pause/resume API for MSHV
Implementing pause/Resume API for MSHV.
Here we set/reset the partition property(TIME_FREEZE)

Signed-off-by: Muminul Islam <muislam@microsoft.com>
2024-05-09 15:03:12 -07:00
3 changed files with 63 additions and 0 deletions

View File

@ -310,6 +310,13 @@ impl hypervisor::Hypervisor for MshvHypervisor {
)
.map_err(|e| hypervisor::HypervisorError::SetPartitionProperty(e.into()))?;
// Always create a frozen partition
fd.set_partition_property(
hv_partition_property_code_HV_PARTITION_PROPERTY_TIME_FREEZE,
1u64,
)
.map_err(|e| hypervisor::HypervisorError::SetPartitionProperty(e.into()))?;
let vm_fd = Arc::new(fd);
#[cfg(target_arch = "x86_64")]
@ -2076,4 +2083,36 @@ impl vm::Vm for MshvVm {
fn get_preferred_target(&self, kvi: &mut VcpuInit) -> vm::Result<()> {
unimplemented!()
}
/// Pause the VM
fn pause(&self) -> vm::Result<()> {
// Freeze the partition
self.fd
.set_partition_property(
hv_partition_property_code_HV_PARTITION_PROPERTY_TIME_FREEZE,
1u64,
)
.map_err(|e| {
vm::HypervisorVmError::SetVmProperty(anyhow!(
"Failed to set partition property: {}",
e
))
})
}
/// Resume the VM
fn resume(&self) -> vm::Result<()> {
// Resuming the partition using TIME_FREEZE property
self.fd
.set_partition_property(
hv_partition_property_code_HV_PARTITION_PROPERTY_TIME_FREEZE,
0u64,
)
.map_err(|e| {
vm::HypervisorVmError::SetVmProperty(anyhow!(
"Failed to set partition property: {}",
e
))
})
}
}

View File

@ -231,6 +231,10 @@ pub enum HypervisorVmError {
///
#[error("Failed to complete isolated import: {0}")]
CompleteIsolatedImport(#[source] anyhow::Error),
/// Failed to set VM property
///
#[error("Failed to set VM property: {0}")]
SetVmProperty(#[source] anyhow::Error),
}
///
/// Result type for returning from a function

View File

@ -319,6 +319,9 @@ pub enum Error {
#[error("Error injecting NMI")]
ErrorNmi,
#[error("Error resuming the VM: {0}")]
ResumeVm(#[source] hypervisor::HypervisorVmError),
}
pub type Result<T> = result::Result<T, Error>;
@ -2173,6 +2176,11 @@ impl Vm {
self.vm.tdx_finalize().map_err(Error::FinalizeTdx)?;
}
// Resume the vm for MSHV
if current_state == VmState::Created {
self.vm.resume().map_err(Error::ResumeVm)?;
}
self.cpu_manager
.lock()
.unwrap()
@ -2487,6 +2495,10 @@ impl Pausable for Vm {
self.cpu_manager.lock().unwrap().pause()?;
self.device_manager.lock().unwrap().pause()?;
self.vm
.pause()
.map_err(|e| MigratableError::Pause(anyhow!("Could not pause the VM: {}", e)))?;
*state = new_state;
event!("vm", "paused");
@ -2495,6 +2507,7 @@ impl Pausable for Vm {
fn resume(&mut self) -> std::result::Result<(), MigratableError> {
event!("vm", "resuming");
let current_state = self.get_state().unwrap();
let mut state = self
.state
.try_write()
@ -2514,6 +2527,13 @@ impl Pausable for Vm {
})?;
}
}
if current_state == VmState::Paused {
self.vm
.resume()
.map_err(|e| MigratableError::Resume(anyhow!("Could not resume the VM: {}", e)))?;
}
self.device_manager.lock().unwrap().resume()?;
// And we're back to the Running state.