devices: adding Suspendable trait to BusDevice and PciDevice

Add supertrait Suspednable to BusDevice and PciDevice

Bug=b:232437513
Test=WIP

Change-Id: I74162399091fc4bc5fdef4bbeefb2639148bd283
Reviewed-on: https://chromium-review.googlesource.com/c/crosvm/crosvm/+/3924745
Commit-Queue: Elie Kheirallah <khei@google.com>
Reviewed-by: Noah Gold <nkgold@google.com>
Auto-Submit: Elie Kheirallah <khei@google.com>
This commit is contained in:
Elie Kheirallah 2022-09-29 01:17:37 +00:00 committed by crosvm LUCI
parent 2cfd0293af
commit eb27c46876
29 changed files with 116 additions and 4 deletions

View file

@ -36,6 +36,7 @@ use crate::BusDevice;
use crate::BusResumeDevice;
use crate::DeviceId;
use crate::IrqLevelEvent;
use crate::Suspendable;
#[derive(Error, Debug)]
pub enum ACPIPMError {
@ -217,6 +218,8 @@ impl ACPIPMResource {
}
}
impl Suspendable for ACPIPMResource {}
fn run_worker(
sci_evt: IrqLevelEvent,
kill_evt: Event,

View file

@ -28,6 +28,7 @@ use crate::BusAccessInfo;
use crate::BusDevice;
use crate::DeviceId;
use crate::IrqLevelEvent;
use crate::Suspendable;
/// Errors for battery devices.
#[sorted]
@ -472,3 +473,5 @@ impl Aml for GoldfishBattery {
.to_aml_bytes(bytes);
}
}
impl Suspendable for GoldfishBattery {}

View file

@ -26,6 +26,7 @@ use crate::BusStatistics;
use crate::DeviceId;
use crate::PciAddress;
use crate::PciDevice;
use crate::Suspendable;
#[cfg(unix)]
use crate::VfioPlatformDevice;
use crate::VirtioMmioDevice;
@ -80,7 +81,7 @@ pub enum BusType {
/// The device does not care where it exists in address space as each method is only given an offset
/// into its allocated portion of address space.
#[allow(unused_variables)]
pub trait BusDevice: Send {
pub trait BusDevice: Send + Suspendable {
/// Returns a label suitable for debug output.
fn debug_label(&self) -> String;
/// Returns a unique id per device type suitable for metrics gathering.

View file

@ -13,6 +13,7 @@ use crate::pci::CrosvmDeviceId;
use crate::BusAccessInfo;
use crate::BusDevice;
use crate::DeviceId;
use crate::Suspendable;
const INDEX_MASK: u8 = 0x7f;
const INDEX_OFFSET: u64 = 0x0;
@ -122,6 +123,8 @@ impl BusDevice for Cmos {
}
}
impl Suspendable for Cmos {}
#[cfg(test)]
mod tests {
use chrono::NaiveDateTime;

View file

@ -20,6 +20,7 @@ use crate::BusAccessInfo;
use crate::BusDevice;
use crate::DeviceId;
use crate::SerialDevice;
use crate::Suspendable;
const BOCHS_DEBUGCON_READBACK: u8 = 0xe9;
@ -88,6 +89,8 @@ impl Debugcon {
}
}
impl Suspendable for Debugcon {}
#[cfg(test)]
mod tests {
use std::io;

View file

@ -23,6 +23,7 @@ use crate::BusDevice;
use crate::BusDeviceSync;
use crate::BusRange;
use crate::DeviceId;
use crate::Suspendable;
pub struct DirectIo {
dev: Mutex<File>,
@ -86,6 +87,8 @@ impl BusDeviceSync for DirectIo {
}
}
impl Suspendable for DirectIo {}
pub struct DirectMmio {
dev: Mutex<Vec<(BusRange, MemoryMapping)>>,
read_only: bool,
@ -216,3 +219,5 @@ impl BusDeviceSync for DirectMmio {
self.iowr(ai, data);
}
}
impl Suspendable for DirectMmio {}

View file

@ -10,6 +10,7 @@ use crate::pci::CrosvmDeviceId;
use crate::BusAccessInfo;
use crate::BusDevice;
use crate::DeviceId;
use crate::Suspendable;
/// A i8042 PS/2 controller that emulates just enough to shutdown the machine.
pub struct I8042Device {
@ -55,3 +56,5 @@ impl BusDevice for I8042Device {
}
}
}
impl Suspendable for I8042Device {}

View file

@ -31,6 +31,7 @@ use crate::pci::CrosvmDeviceId;
use crate::BusDevice;
use crate::DeviceId;
use crate::IrqEventSource;
use crate::Suspendable;
// ICH10 I/O APIC version: 0x20
const IOAPIC_VERSION_ID: u32 = 0x00000020;
@ -498,6 +499,8 @@ impl Ioapic {
}
}
impl Suspendable for Ioapic {}
#[sorted]
#[derive(Error, Debug)]
enum IoapicError {

View file

@ -23,6 +23,7 @@ use crate::bus::BusAccessInfo;
use crate::pci::CrosvmDeviceId;
use crate::BusDevice;
use crate::DeviceId;
use crate::Suspendable;
pub struct Pic {
// Indicates a pending INTR signal to LINT0 of vCPU, checked by vCPU thread.
@ -538,6 +539,8 @@ impl Pic {
}
}
impl Suspendable for Pic {}
#[cfg(test)]
mod tests {
// ICW4: Special fully nested mode with no auto EOI.

View file

@ -76,6 +76,7 @@ use crate::IrqEventSource;
use crate::IrqLevelEvent;
use crate::Pit;
use crate::PitError;
use crate::Suspendable;
/// PIT channel 0 timer is connected to IRQ 0
const PIT_CHANNEL0_IRQ: u32 = 0;
@ -860,6 +861,8 @@ impl<V: VcpuX86_64 + 'static> BusDevice for UserspaceIrqChip<V> {
}
}
impl<V: VcpuX86_64 + 'static> Suspendable for UserspaceIrqChip<V> {}
impl<V: VcpuX86_64 + 'static> BusDeviceSync for UserspaceIrqChip<V> {
fn read(&self, info: BusAccessInfo, data: &mut [u8]) {
self.apics[info.id].lock().read(info.offset, data)

View file

@ -46,6 +46,7 @@ use crate::pci::PciDeviceError;
use crate::pci::PciInterruptPin;
use crate::pci::PCI_VENDOR_ID_INTEL;
use crate::IrqLevelEvent;
use crate::Suspendable;
// Use 82801AA because it's what qemu does.
const PCI_DEVICE_ID_INTEL_82801AA_5: u16 = 0x2415;
@ -405,6 +406,8 @@ impl PciDevice for Ac97Dev {
}
}
impl Suspendable for Ac97Dev {}
#[cfg(test)]
mod tests {
use resources::AddressRange;

View file

@ -80,6 +80,7 @@ use crate::pci::pci_device::Result as PciResult;
use crate::pci::PciAddress;
use crate::pci::PciDeviceError;
use crate::vfio::VfioContainer;
use crate::Suspendable;
use crate::UnpinRequest;
use crate::UnpinResponse;
@ -1675,3 +1676,5 @@ impl Drop for CoIommuDev {
}
}
}
impl Suspendable for CoIommuDev {}

View file

@ -44,6 +44,7 @@ use crate::BusAccessInfo;
use crate::BusDevice;
use crate::DeviceId;
use crate::IrqLevelEvent;
use crate::Suspendable;
#[sorted]
#[derive(Error, Debug)]
@ -307,7 +308,7 @@ pub enum PreferredIrq {
Fixed { pin: PciInterruptPin, gsi: u32 },
}
pub trait PciDevice: Send {
pub trait PciDevice: Send + Suspendable {
/// Returns a label suitable for debug output.
fn debug_label(&self) -> String;
@ -697,6 +698,24 @@ impl<T: PciDevice + ?Sized> PciDevice for Box<T> {
}
}
impl<T: PciDevice + ?Sized> Suspendable for Box<T> {
fn snapshot(&self) -> anyhow::Result<String> {
(**self).snapshot()
}
fn restore(&mut self, data: &str) -> anyhow::Result<()> {
(**self).restore(data)
}
fn sleep(&mut self) -> anyhow::Result<()> {
(**self).sleep()
}
fn wake(&mut self) -> anyhow::Result<()> {
(**self).wake()
}
}
impl<T: 'static + PciDevice> BusDeviceObj for T {
fn as_pci_device(&self) -> Option<&dyn PciDevice> {
Some(self)
@ -759,6 +778,8 @@ mod tests {
}
}
impl Suspendable for TestDev {}
#[test]
fn config_write_result() {
let mut test_dev = TestDev {

View file

@ -33,6 +33,7 @@ use crate::BusAccessInfo;
use crate::BusDevice;
use crate::BusType;
use crate::DeviceId;
use crate::Suspendable;
// A PciDevice that holds the root hub's configuration.
struct PciRootConfiguration {
@ -71,6 +72,8 @@ impl PciDevice for PciRootConfiguration {
}
}
impl Suspendable for PciRootConfiguration {}
// Command send to pci root worker thread to add/remove device from pci root
pub enum PciRootCommand {
Add(PciAddress, Arc<Mutex<dyn BusDevice>>),
@ -428,6 +431,8 @@ impl BusDevice for PciConfigIo {
}
}
impl Suspendable for PciConfigIo {}
/// Emulates PCI memory-mapped configuration access mechanism.
pub struct PciConfigMmio {
/// PCI root bridge.
@ -493,7 +498,9 @@ impl BusDevice for PciConfigMmio {
}
}
/// Inspired by PCI configuration space, crosvm provides 2048 dword virtual registers (8KiB in
impl Suspendable for PciConfigMmio {}
/// Inspired by PCI configuration space, CrosVM provides 2048 dword virtual registers (8KiB in
/// total) for each PCI device. The guest can use these registers to exchange device-specific
/// information with crosvm. The first 4kB is trapped by crosvm and crosvm supplies these
/// register's emulation. The second 4KB is mapped into guest directly as shared memory, so
@ -567,3 +574,5 @@ impl BusDevice for PciVirtualConfigMmio {
.virtual_config_space_write(address, register, value)
}
}
impl Suspendable for PciVirtualConfigMmio {}

View file

@ -31,6 +31,7 @@ use crate::pci::PciHeaderType;
use crate::pci::PCI_VENDOR_ID_INTEL;
use crate::IrqLevelEvent;
use crate::PciInterruptPin;
use crate::Suspendable;
pub const BR_BUS_NUMBER_REG: usize = 0x6;
pub const BR_BUS_SUBORDINATE_OFFSET: usize = 0x2;
@ -504,3 +505,5 @@ impl PciDevice for PciBridge {
self.msi_config.lock().destroy()
}
}
impl Suspendable for PciBridge {}

View file

@ -36,6 +36,7 @@ use crate::pci::pci_device::Result;
use crate::pci::PciAddress;
use crate::pci::PciDeviceError;
use crate::pci::PCI_VENDOR_ID_REDHAT;
use crate::Suspendable;
const PCI_DEVICE_ID_REDHAT_PVPANIC: u16 = 0x0011;
const PCI_PVPANIC_REVISION_ID: u8 = 1;
@ -205,6 +206,8 @@ impl PciDevice for PvPanicPciDevice {
}
}
impl Suspendable for PvPanicPciDevice {}
#[cfg(test)]
mod test {
use base::Tube;

View file

@ -28,6 +28,7 @@ use crate::pci::pci_device::PciDevice;
use crate::pci::pci_device::Result;
use crate::pci::PciAddress;
use crate::pci::PciDeviceError;
use crate::Suspendable;
#[derive(Serialize, Deserialize)]
pub struct StubPciParameters {
@ -136,6 +137,8 @@ impl PciDevice for StubPciDevice {
fn write_bar(&mut self, _addr: u64, _data: &[u8]) {}
}
impl Suspendable for StubPciDevice {}
#[cfg(test)]
mod test {
use resources::AddressRange;

View file

@ -89,6 +89,7 @@ use crate::vfio::VfioError;
use crate::vfio::VfioIrqType;
use crate::vfio::VfioPciConfig;
use crate::IrqLevelEvent;
use crate::Suspendable;
const PCI_VENDOR_ID: u32 = 0x0;
const PCI_DEVICE_ID: u32 = 0x2;
@ -2192,6 +2193,8 @@ impl Drop for VfioPciDevice {
}
}
impl Suspendable for VfioPciDevice {}
#[cfg(test)]
mod tests {
use resources::AddressRange;

View file

@ -34,6 +34,7 @@ use crate::pci::CrosvmDeviceId;
use crate::BusAccessInfo;
use crate::BusDevice;
use crate::DeviceId;
use crate::Suspendable;
const COMMAND_WRITE_BYTE: u8 = 0x10;
const COMMAND_BLOCK_ERASE: u8 = 0x20;
@ -230,6 +231,8 @@ impl BusDevice for Pflash {
}
}
impl Suspendable for Pflash {}
#[cfg(test)]
mod tests {
use base::FileReadWriteAtVolatile;

View file

@ -41,6 +41,7 @@ use crate::pci::CrosvmDeviceId;
use crate::BusDevice;
use crate::DeviceId;
use crate::IrqEdgeEvent;
use crate::Suspendable;
// Bitmask for areas of standard (non-ReadBack) Control Word Format. Constant
// names are kept the same as Intel PIT data sheet.
@ -380,6 +381,8 @@ impl Pit {
}
}
impl Suspendable for Pit {}
// Each instance of this represents one of the PIT counters. They are used to
// implement one-shot and repeating timer alarms. An 8254 has three counters.
struct PitCounter {

View file

@ -13,6 +13,7 @@ use crate::BusAccessInfo;
use crate::BusDevice;
use crate::DeviceId;
use crate::IrqEdgeEvent;
use crate::Suspendable;
// Register offsets
// Data register
@ -154,6 +155,9 @@ impl BusDevice for Pl030 {
*data_array = reg_content.to_ne_bytes();
}
}
impl Suspendable for Pl030 {}
#[cfg(test)]
mod tests {
use super::*;

View file

@ -37,6 +37,7 @@ use crate::BusDeviceObj;
use crate::DeviceId;
use crate::IrqEdgeEvent;
use crate::IrqLevelEvent;
use crate::Suspendable;
struct MmioInfo {
index: u32,
@ -72,6 +73,8 @@ impl BusDevice for VfioPlatformDevice {
}
}
impl Suspendable for VfioPlatformDevice {}
impl BusDeviceObj for VfioPlatformDevice {
fn as_platform_device(&self) -> Option<&VfioPlatformDevice> {
Some(self)

View file

@ -27,6 +27,7 @@ use crate::BusDevice;
use crate::BusRange;
use crate::BusType;
use crate::DeviceId;
use crate::Suspendable;
/// Errors for proxy devices.
#[sorted]
@ -359,6 +360,8 @@ impl BusDevice for ProxyDevice {
}
}
impl Suspendable for ProxyDevice {}
impl Drop for ProxyDevice {
fn drop(&mut self) {
self.sync_send(&Command::Shutdown);
@ -420,6 +423,8 @@ mod tests {
}
}
impl Suspendable for EchoDevice {}
fn new_proxied_echo_device() -> ProxyDevice {
let device = EchoDevice::new();
let keep_fds: Vec<RawDescriptor> = Vec::new();

View file

@ -21,6 +21,7 @@ use base::Result;
use crate::bus::BusAccessInfo;
use crate::pci::CrosvmDeviceId;
use crate::serial_device::SerialInput;
use crate::suspendable::Suspendable;
use crate::BusDevice;
use crate::DeviceId;
@ -399,6 +400,8 @@ impl BusDevice for Serial {
}
}
impl Suspendable for Serial {}
#[cfg(test)]
mod tests {
use std::io;

View file

@ -20,7 +20,7 @@ pub enum DeviceState {
pub trait Suspendable {
/// Save the device state in an image that can be restored.
fn snapshot(&self) -> AnyhowResult<String> {
Ok(format!(
Err(anyhow!(
"Suspendable::snapshot not implemented for {}",
std::any::type_name::<Self>()
))

View file

@ -37,6 +37,7 @@ use crate::usb::xhci::xhci_regs::init_xhci_mmio_space_and_regs;
use crate::usb::xhci::xhci_regs::XhciRegs;
use crate::utils::FailHandle;
use crate::IrqLevelEvent;
use crate::Suspendable;
const XHCI_BAR0_SIZE: u64 = 0x10000;
@ -326,3 +327,5 @@ impl PciDevice for XhciController {
self.init_when_forked();
}
}
impl Suspendable for XhciController {}

View file

@ -38,6 +38,7 @@ use crate::BusDevice;
use crate::BusDeviceObj;
use crate::DeviceId;
use crate::IrqEdgeEvent;
use crate::Suspendable;
const VIRT_MAGIC: u32 = 0x74726976; /* 'virt' */
const VIRT_VERSION: u8 = 2;
@ -506,3 +507,5 @@ impl BusDevice for VirtioMmioDevice {
self.on_device_sandboxed();
}
}
impl Suspendable for VirtioMmioDevice {}

View file

@ -62,6 +62,7 @@ use crate::pci::PciInterruptPin;
use crate::pci::PciSubclass;
use crate::virtio::ipc_memory_mapper::IpcMemoryMapper;
use crate::IrqLevelEvent;
use crate::Suspendable;
#[repr(u8)]
#[derive(Debug, Copy, Clone, enumn::N)]
@ -933,6 +934,8 @@ impl PciDevice for VirtioPciDevice {
}
}
impl Suspendable for VirtioPciDevice {}
struct VmRequester {
tube: Tube,
alloc: Alloc,

View file

@ -35,6 +35,7 @@ use crate::pci::CrosvmDeviceId;
use crate::BusAccessInfo;
use crate::BusDevice;
use crate::DeviceId;
use crate::Suspendable;
// Registers offsets
const VMWDT_REG_STATUS: u32 = 0x00;
@ -339,6 +340,9 @@ impl BusDevice for Vmwdt {
}
}
}
impl Suspendable for Vmwdt {}
#[cfg(test)]
mod tests {
use std::thread::sleep;