mirror of
https://chromium.googlesource.com/crosvm/crosvm
synced 2025-02-09 03:57:24 +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;
|
||||
#[cfg(feature = "tpm")]
|
||||
mod software_tpm;
|
||||
mod suspendable;
|
||||
mod sys;
|
||||
pub mod virtio;
|
||||
#[cfg(all(feature = "vtpm", target_arch = "x86_64"))]
|
||||
|
@ -101,6 +102,8 @@ pub use self::serial_device::SerialParameters;
|
|||
pub use self::serial_device::SerialType;
|
||||
#[cfg(feature = "tpm")]
|
||||
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::VirtioPciDevice;
|
||||
#[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