diff --git a/Cargo.lock b/Cargo.lock index 17d95e838..01185dadb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1130,6 +1130,7 @@ dependencies = [ "signal-hook 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "vfio 0.0.1", "vm-allocator 0.1.0", + "vm-device 0.1.0", "vm-memory 0.1.0 (git+https://github.com/rust-vmm/vm-memory)", "vm-virtio 0.1.0", "vmm-sys-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/vmm/Cargo.toml b/vmm/Cargo.toml index 6a0698715..83f54ecc1 100644 --- a/vmm/Cargo.toml +++ b/vmm/Cargo.toml @@ -30,6 +30,7 @@ serde_derive = ">=1.0.27" serde_json = ">=1.0.9" vfio = { path = "../vfio", optional = true } vm-allocator = { path = "../vm-allocator" } +vm-device = { path = "../vm-device" } vm-virtio = { path = "../vm-virtio" } vmm-sys-util = ">=0.3.1" signal-hook = "0.1.10" diff --git a/vmm/src/device_manager.rs b/vmm/src/device_manager.rs index 431030e41..a2ca39324 100644 --- a/vmm/src/device_manager.rs +++ b/vmm/src/device_manager.rs @@ -9,6 +9,8 @@ // SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause // +extern crate vm_device; + use crate::config::{ConsoleOutputMode, VmConfig}; use crate::vm::VmInfo; #[cfg(feature = "acpi")] @@ -43,6 +45,7 @@ use std::sync::{Arc, Mutex, RwLock}; #[cfg(feature = "pci_support")] use vfio::{VfioDevice, VfioDmaMapping, VfioPciDevice, VfioPciError}; use vm_allocator::SystemAllocator; +use vm_device::{Migratable, MigratableError, Pausable, Snapshotable}; use vm_memory::GuestAddress; use vm_memory::{Address, GuestMemoryMmap, GuestUsize}; #[cfg(feature = "pci_support")] @@ -404,6 +407,9 @@ pub struct DeviceManager { // VM configuration config: Arc>, + + // Migratable devices + migratable_devices: Vec>>, } impl DeviceManager { @@ -418,6 +424,7 @@ impl DeviceManager { let mmio_bus = devices::Bus::new(); let mut virtio_devices: Vec<(Arc>, bool)> = Vec::new(); + let mut migratable_devices: Vec>> = Vec::new(); let mut mmap_regions = Vec::new(); #[allow(unused_mut)] @@ -501,6 +508,7 @@ impl DeviceManager { start_of_device_area, end_of_device_area, config, + migratable_devices, }) } @@ -1710,3 +1718,24 @@ impl Aml for DeviceManager { bytes } } + +impl Pausable for DeviceManager { + fn pause(&mut self) -> result::Result<(), MigratableError> { + for dev in &self.migratable_devices { + dev.lock().unwrap().pause()?; + } + + Ok(()) + } + + fn resume(&mut self) -> result::Result<(), MigratableError> { + for dev in &self.migratable_devices { + dev.lock().unwrap().resume()?; + } + + Ok(()) + } +} + +impl Snapshotable for DeviceManager {} +impl Migratable for DeviceManager {} diff --git a/vmm/src/vm.rs b/vmm/src/vm.rs index ed2f4ef5f..e97aedc02 100755 --- a/vmm/src/vm.rs +++ b/vmm/src/vm.rs @@ -43,6 +43,7 @@ use std::os::unix::io::FromRawFd; use std::sync::{Arc, Mutex, RwLock}; use std::{result, str, thread}; use vm_allocator::{GsiApic, SystemAllocator}; +use vm_device::{MigratableError, Pausable}; use vm_memory::guest_memory::FileOffset; use vm_memory::{ Address, Bytes, Error as MmapError, GuestAddress, GuestMemory, GuestMemoryMmap, @@ -145,6 +146,12 @@ pub enum Error { /// Capability missing CapabilityMissing(Cap), + + /// Cannot pause devices + PauseDevices(MigratableError), + + /// Cannot resume devices + ResumeDevices(MigratableError), } pub type Result = result::Result; @@ -627,6 +634,7 @@ impl Vm { .unwrap() .pause() .map_err(Error::CpuManager)?; + self.devices.pause().map_err(Error::PauseDevices)?; *state = new_state; @@ -639,6 +647,7 @@ impl Vm { state.valid_transition(new_state)?; + self.devices.resume().map_err(Error::ResumeDevices)?; self.cpu_manager .lock() .unwrap()