From 35dd1523c923111bc5255b9cc9982462c5c11e8b Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Tue, 19 Nov 2019 00:24:31 +0100 Subject: [PATCH] vmm: device_manager: Implement the Pausable trait Since the Snapshotable placeholder and Migratable traits are provided as well, the DeviceManager object and all its objects are now Migratable. All Migratable devices are tracked as Arc> references. Keeping track of all migratable devices allows for implementing the Migratable trait for the DeviceManager structure, making the whole device model potentially migratable. Signed-off-by: Samuel Ortiz --- Cargo.lock | 1 + vmm/Cargo.toml | 1 + vmm/src/device_manager.rs | 29 +++++++++++++++++++++++++++++ vmm/src/vm.rs | 9 +++++++++ 4 files changed, 40 insertions(+) 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()