mirror of
https://chromium.googlesource.com/crosvm/crosvm
synced 2025-02-09 20:04:20 +00:00
devices: Added suspendable.rs with the Suspendable trait.
Suspendable trait will be implemented for structs that will snapshot/restore/sleep/wake, related to suspend/resume with snapshotting. Added test generation for suspendable trait. Bug=b:232437513 Test=cargo test Change-Id: I071bad026c15ce346b6657871e7578528768bfc2 Reviewed-on: https://chromium-review.googlesource.com/c/crosvm/crosvm/+/3842812 Reviewed-by: Daniel Verkamp <dverkamp@chromium.org> Reviewed-by: Frederick Mayle <fmayle@google.com> Reviewed-by: Noah Gold <nkgold@google.com> Commit-Queue: Elie Kheirallah <khei@google.com> Reviewed-by: Steven Moreland <smoreland@google.com>
This commit is contained in:
parent
21c739216e
commit
7a11fa44d1
2 changed files with 171 additions and 0 deletions
|
@ -30,6 +30,7 @@ mod serial;
|
||||||
pub mod serial_device;
|
pub mod serial_device;
|
||||||
#[cfg(feature = "tpm")]
|
#[cfg(feature = "tpm")]
|
||||||
mod software_tpm;
|
mod software_tpm;
|
||||||
|
mod suspendable;
|
||||||
mod sys;
|
mod sys;
|
||||||
pub mod virtio;
|
pub mod virtio;
|
||||||
#[cfg(all(feature = "vtpm", target_arch = "x86_64"))]
|
#[cfg(all(feature = "vtpm", target_arch = "x86_64"))]
|
||||||
|
@ -101,6 +102,8 @@ pub use self::serial_device::SerialParameters;
|
||||||
pub use self::serial_device::SerialType;
|
pub use self::serial_device::SerialType;
|
||||||
#[cfg(feature = "tpm")]
|
#[cfg(feature = "tpm")]
|
||||||
pub use self::software_tpm::SoftwareTpm;
|
pub use self::software_tpm::SoftwareTpm;
|
||||||
|
pub use self::suspendable::DeviceState;
|
||||||
|
pub use self::suspendable::Suspendable;
|
||||||
pub use self::virtio::VirtioMmioDevice;
|
pub use self::virtio::VirtioMmioDevice;
|
||||||
pub use self::virtio::VirtioPciDevice;
|
pub use self::virtio::VirtioPciDevice;
|
||||||
#[cfg(all(feature = "vtpm", target_arch = "x86_64"))]
|
#[cfg(all(feature = "vtpm", target_arch = "x86_64"))]
|
||||||
|
|
168
devices/src/suspendable.rs
Normal file
168
devices/src/suspendable.rs
Normal file
|
@ -0,0 +1,168 @@
|
||||||
|
// Copyright 2022 The ChromiumOS Authors
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
//! Trait to suspend virtual hardware.
|
||||||
|
|
||||||
|
use anyhow::anyhow;
|
||||||
|
use anyhow::Result as AnyhowResult;
|
||||||
|
use serde::Deserialize;
|
||||||
|
use serde::Serialize;
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Serialize, Deserialize)]
|
||||||
|
pub enum DeviceState {
|
||||||
|
Awake,
|
||||||
|
Sleep,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This trait provides the functions required for a device to implement to successfully
|
||||||
|
/// suspend/resume in crosvm.
|
||||||
|
pub trait Suspendable {
|
||||||
|
/// Save the device state in an image that can be restored.
|
||||||
|
fn snapshot(&self) -> AnyhowResult<String> {
|
||||||
|
Ok(format!(
|
||||||
|
"Suspendable::snapshot not implemented for {}",
|
||||||
|
std::any::type_name::<Self>()
|
||||||
|
))
|
||||||
|
}
|
||||||
|
/// Load a saved snapshot of an image.
|
||||||
|
fn restore(&mut self, _data: &str) -> AnyhowResult<()> {
|
||||||
|
Err(anyhow!(
|
||||||
|
"Suspendable::restore not implemented for {}",
|
||||||
|
std::any::type_name::<Self>()
|
||||||
|
))
|
||||||
|
}
|
||||||
|
/// Stop all threads related to the device.
|
||||||
|
/// Sleep should be idempotent.
|
||||||
|
fn sleep(&mut self) -> AnyhowResult<()> {
|
||||||
|
Err(anyhow!(
|
||||||
|
"Suspendable::sleep not implemented for {}",
|
||||||
|
std::any::type_name::<Self>()
|
||||||
|
))
|
||||||
|
}
|
||||||
|
/// Create/Resume all threads related to the device.
|
||||||
|
/// Wake should be idempotent.
|
||||||
|
fn wake(&mut self) -> AnyhowResult<()> {
|
||||||
|
Err(anyhow!(
|
||||||
|
"Suspendable::wake not implemented for {}",
|
||||||
|
std::any::type_name::<Self>()
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// General tests that should pass on all suspendables.
|
||||||
|
// Do implement device-specific tests to validate the functionality of the device.
|
||||||
|
// Those tests are not a replacement for regular tests. Only an extension specific to the trait's
|
||||||
|
// basic functionality.
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! suspendable_tests {
|
||||||
|
($($name:ident: $expr:expr,)*) => {
|
||||||
|
$(
|
||||||
|
mod $name {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_sleep_idempotent() {
|
||||||
|
let unit = &mut $expr;
|
||||||
|
let res = unit.sleep();
|
||||||
|
let res2 = unit.sleep();
|
||||||
|
match res {
|
||||||
|
Ok(()) => (),
|
||||||
|
Err(e) => println!("{}", e),
|
||||||
|
}
|
||||||
|
match res2 {
|
||||||
|
Ok(()) => (),
|
||||||
|
Err(e) => println!("idempotent: {}", e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_snapshot_restore() {
|
||||||
|
let unit = &mut $expr;
|
||||||
|
let snap = unit.snapshot();
|
||||||
|
match snap {
|
||||||
|
Ok(snap_res) => {
|
||||||
|
let res = unit.restore(&snap_res);
|
||||||
|
match res {
|
||||||
|
Ok(()) => (),
|
||||||
|
Err(e) => println!("{}", e),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(e) => println!("{}", e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_sleep_snapshot() {
|
||||||
|
let unit = &mut $expr;
|
||||||
|
let sleep_result = unit.sleep();
|
||||||
|
let snap_result = unit.snapshot();
|
||||||
|
match sleep_result {
|
||||||
|
Ok(()) => (),
|
||||||
|
Err(e) => println!("{}", e),
|
||||||
|
}
|
||||||
|
match snap_result {
|
||||||
|
Ok(_res) => (),
|
||||||
|
Err(e) => println!("{}", e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_sleep_snapshot_restore_wake() {
|
||||||
|
let unit = &mut $expr;
|
||||||
|
let sleep_result = unit.sleep();
|
||||||
|
let snap_result = unit.snapshot();
|
||||||
|
match sleep_result {
|
||||||
|
Ok(()) => (),
|
||||||
|
Err(e) => println!("{}", e),
|
||||||
|
}
|
||||||
|
match snap_result {
|
||||||
|
Ok(snap_res) => {
|
||||||
|
let res = unit.restore(&snap_res);
|
||||||
|
match res {
|
||||||
|
Ok(()) => (),
|
||||||
|
Err(e) => println!("{}", e),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(e) => println!("{}", e),
|
||||||
|
}
|
||||||
|
let wake_res = unit.wake();
|
||||||
|
match wake_res {
|
||||||
|
Ok(()) => (),
|
||||||
|
Err(e) => println!("{}", e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_sleep_snapshot_wake() {
|
||||||
|
let unit = &mut $expr;
|
||||||
|
let sleep_result = unit.sleep();
|
||||||
|
let snap_result = unit.snapshot();
|
||||||
|
match sleep_result {
|
||||||
|
Ok(()) => (),
|
||||||
|
Err(e) => println!("{}", e),
|
||||||
|
}
|
||||||
|
match snap_result {
|
||||||
|
Ok(_snap_res) => (),
|
||||||
|
Err(e) => println!("{}", e),
|
||||||
|
}
|
||||||
|
let wake_res = unit.wake();
|
||||||
|
match wake_res {
|
||||||
|
Ok(()) => (),
|
||||||
|
Err(e) => println!("{}", e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_snapshot() {
|
||||||
|
let unit = &mut $expr;
|
||||||
|
let snap_result = unit.snapshot();
|
||||||
|
match snap_result {
|
||||||
|
Ok(_snap_res) => (),
|
||||||
|
Err(e) => println!("{}", e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)*
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue