mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2025-02-22 11:22:26 +00:00
vmm: vm: Implement the Pausable trait
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
This commit is contained in:
parent
9756fc2dd0
commit
37557c8b35
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -1111,6 +1111,7 @@ name = "vmm"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"acpi_tables 0.1.0",
|
"acpi_tables 0.1.0",
|
||||||
|
"anyhow 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"arch 0.1.0",
|
"arch 0.1.0",
|
||||||
"devices 0.1.0",
|
"devices 0.1.0",
|
||||||
"epoll 4.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"epoll 4.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -13,6 +13,7 @@ cmos = ["devices/cmos"]
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
acpi_tables = { path = "../acpi_tables", optional = true }
|
acpi_tables = { path = "../acpi_tables", optional = true }
|
||||||
|
anyhow = "1.0"
|
||||||
arch = { path = "../arch" }
|
arch = { path = "../arch" }
|
||||||
devices = { path = "../devices" }
|
devices = { path = "../devices" }
|
||||||
epoll = ">=4.0.1"
|
epoll = ">=4.0.1"
|
||||||
|
@ -23,6 +23,7 @@ use std::os::unix::io::{AsRawFd, RawFd};
|
|||||||
use std::sync::mpsc::{Receiver, RecvError, SendError, Sender};
|
use std::sync::mpsc::{Receiver, RecvError, SendError, Sender};
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use std::{result, thread};
|
use std::{result, thread};
|
||||||
|
use vm_device::Pausable;
|
||||||
use vmm_sys_util::eventfd::EventFd;
|
use vmm_sys_util::eventfd::EventFd;
|
||||||
|
|
||||||
pub mod api;
|
pub mod api;
|
||||||
@ -236,7 +237,7 @@ impl Vmm {
|
|||||||
|
|
||||||
fn vm_pause(&mut self) -> result::Result<(), VmError> {
|
fn vm_pause(&mut self) -> result::Result<(), VmError> {
|
||||||
if let Some(ref mut vm) = self.vm {
|
if let Some(ref mut vm) = self.vm {
|
||||||
vm.pause()
|
vm.pause().map_err(VmError::Pause)
|
||||||
} else {
|
} else {
|
||||||
Err(VmError::VmNotRunning)
|
Err(VmError::VmNotRunning)
|
||||||
}
|
}
|
||||||
@ -244,7 +245,7 @@ impl Vmm {
|
|||||||
|
|
||||||
fn vm_resume(&mut self) -> result::Result<(), VmError> {
|
fn vm_resume(&mut self) -> result::Result<(), VmError> {
|
||||||
if let Some(ref mut vm) = self.vm {
|
if let Some(ref mut vm) = self.vm {
|
||||||
vm.resume()
|
vm.resume().map_err(VmError::Resume)
|
||||||
} else {
|
} else {
|
||||||
Err(VmError::VmNotRunning)
|
Err(VmError::VmNotRunning)
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
|
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
|
||||||
//
|
//
|
||||||
|
|
||||||
|
extern crate anyhow;
|
||||||
extern crate arch;
|
extern crate arch;
|
||||||
extern crate devices;
|
extern crate devices;
|
||||||
extern crate epoll;
|
extern crate epoll;
|
||||||
@ -26,6 +27,7 @@ extern crate vm_virtio;
|
|||||||
use crate::config::VmConfig;
|
use crate::config::VmConfig;
|
||||||
use crate::cpu;
|
use crate::cpu;
|
||||||
use crate::device_manager::{get_win_size, Console, DeviceManager, DeviceManagerError};
|
use crate::device_manager::{get_win_size, Console, DeviceManager, DeviceManagerError};
|
||||||
|
use anyhow::anyhow;
|
||||||
use arch::RegionType;
|
use arch::RegionType;
|
||||||
use devices::{ioapic, HotPlugNotificationType};
|
use devices::{ioapic, HotPlugNotificationType};
|
||||||
use kvm_bindings::{kvm_enable_cap, kvm_userspace_memory_region, KVM_CAP_SPLIT_IRQCHIP};
|
use kvm_bindings::{kvm_enable_cap, kvm_userspace_memory_region, KVM_CAP_SPLIT_IRQCHIP};
|
||||||
@ -43,7 +45,7 @@ use std::os::unix::io::FromRawFd;
|
|||||||
use std::sync::{Arc, Mutex, RwLock};
|
use std::sync::{Arc, Mutex, RwLock};
|
||||||
use std::{result, str, thread};
|
use std::{result, str, thread};
|
||||||
use vm_allocator::{GsiApic, SystemAllocator};
|
use vm_allocator::{GsiApic, SystemAllocator};
|
||||||
use vm_device::{MigratableError, Pausable};
|
use vm_device::{Migratable, MigratableError, Pausable, Snapshotable};
|
||||||
use vm_memory::guest_memory::FileOffset;
|
use vm_memory::guest_memory::FileOffset;
|
||||||
use vm_memory::{
|
use vm_memory::{
|
||||||
Address, Bytes, Error as MmapError, GuestAddress, GuestMemory, GuestMemoryMmap,
|
Address, Bytes, Error as MmapError, GuestAddress, GuestMemory, GuestMemoryMmap,
|
||||||
@ -158,6 +160,12 @@ pub enum Error {
|
|||||||
|
|
||||||
/// Cannot resume cpus
|
/// Cannot resume cpus
|
||||||
ResumeCpus(MigratableError),
|
ResumeCpus(MigratableError),
|
||||||
|
|
||||||
|
/// Cannot pause VM
|
||||||
|
Pause(MigratableError),
|
||||||
|
|
||||||
|
/// Cannot resume VM
|
||||||
|
Resume(MigratableError),
|
||||||
}
|
}
|
||||||
pub type Result<T> = result::Result<T, Error>;
|
pub type Result<T> = result::Result<T, Error>;
|
||||||
|
|
||||||
@ -629,43 +637,6 @@ impl Vm {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pause(&mut self) -> Result<()> {
|
|
||||||
let mut state = self.state.try_write().map_err(|_| Error::PoisonedState)?;
|
|
||||||
let new_state = VmState::Paused;
|
|
||||||
|
|
||||||
state.valid_transition(new_state)?;
|
|
||||||
|
|
||||||
self.cpu_manager
|
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.pause()
|
|
||||||
.map_err(Error::PauseCpus)?;
|
|
||||||
self.devices.pause().map_err(Error::PauseDevices)?;
|
|
||||||
|
|
||||||
*state = new_state;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn resume(&mut self) -> Result<()> {
|
|
||||||
let mut state = self.state.try_write().map_err(|_| Error::PoisonedState)?;
|
|
||||||
let new_state = VmState::Running;
|
|
||||||
|
|
||||||
state.valid_transition(new_state)?;
|
|
||||||
|
|
||||||
self.devices.resume().map_err(Error::ResumeDevices)?;
|
|
||||||
self.cpu_manager
|
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.resume()
|
|
||||||
.map_err(Error::ResumeCpus)?;
|
|
||||||
|
|
||||||
// And we're back to the Running state.
|
|
||||||
*state = new_state;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn resize(&mut self, desired_vcpus: u8) -> Result<()> {
|
pub fn resize(&mut self, desired_vcpus: u8) -> Result<()> {
|
||||||
self.cpu_manager
|
self.cpu_manager
|
||||||
.lock()
|
.lock()
|
||||||
@ -703,7 +674,7 @@ impl Vm {
|
|||||||
pub fn boot(&mut self) -> Result<()> {
|
pub fn boot(&mut self) -> Result<()> {
|
||||||
let current_state = self.get_state()?;
|
let current_state = self.get_state()?;
|
||||||
if current_state == VmState::Paused {
|
if current_state == VmState::Paused {
|
||||||
return self.resume();
|
return self.resume().map_err(Error::Resume);
|
||||||
}
|
}
|
||||||
|
|
||||||
let new_state = VmState::Running;
|
let new_state = VmState::Running;
|
||||||
@ -785,6 +756,50 @@ impl Vm {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Pausable for Vm {
|
||||||
|
fn pause(&mut self) -> std::result::Result<(), MigratableError> {
|
||||||
|
let mut state = self
|
||||||
|
.state
|
||||||
|
.try_write()
|
||||||
|
.map_err(|e| MigratableError::Pause(anyhow!("Could not get VM state: {}", e)))?;
|
||||||
|
let new_state = VmState::Paused;
|
||||||
|
|
||||||
|
state
|
||||||
|
.valid_transition(new_state)
|
||||||
|
.map_err(|e| MigratableError::Pause(anyhow!("Invalid transition: {:?}", e)))?;
|
||||||
|
|
||||||
|
self.cpu_manager.lock().unwrap().pause()?;
|
||||||
|
self.devices.pause()?;
|
||||||
|
|
||||||
|
*state = new_state;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn resume(&mut self) -> std::result::Result<(), MigratableError> {
|
||||||
|
let mut state = self
|
||||||
|
.state
|
||||||
|
.try_write()
|
||||||
|
.map_err(|e| MigratableError::Resume(anyhow!("Could not get VM state: {}", e)))?;
|
||||||
|
let new_state = VmState::Running;
|
||||||
|
|
||||||
|
state
|
||||||
|
.valid_transition(new_state)
|
||||||
|
.map_err(|e| MigratableError::Pause(anyhow!("Invalid transition: {:?}", e)))?;
|
||||||
|
|
||||||
|
self.devices.resume()?;
|
||||||
|
self.cpu_manager.lock().unwrap().resume()?;
|
||||||
|
|
||||||
|
// And we're back to the Running state.
|
||||||
|
*state = new_state;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Snapshotable for Vm {}
|
||||||
|
impl Migratable for Vm {}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user