mirror of
https://chromium.googlesource.com/crosvm/crosvm
synced 2024-11-28 01:16:50 +00:00
devices: pci: Add serialization/deserialization to StubPciDevice
Add simple serialization/deserialization to StubPciDevice through the traits provided by serde by adding the snapshot() and restore() implementations to this struct's Suspendable implementation. The requested_address and assigned_address fields were left out of the snapshot since they are only configurable during VM creation. Also add a test case for validation. BUG=b:266622321 TEST=cargo build && ./tools/run_tests Change-Id: I8d640452ee7db7263f1ecb185041dabb50ac46fc Reviewed-on: https://chromium-review.googlesource.com/c/crosvm/crosvm/+/4451466 Reviewed-by: Daniel Verkamp <dverkamp@chromium.org> Reviewed-by: Elie Kheirallah <khei@google.com> Commit-Queue: Jesus Sanchez-Palencia <jesussanp@google.com>
This commit is contained in:
parent
db627e80e9
commit
aebac6eff3
2 changed files with 68 additions and 1 deletions
|
@ -47,7 +47,7 @@ pub enum Error {
|
|||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
|
||||
/// PCI Device Address, AKA Bus:Device.Function
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[derive(Default, Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct PciAddress {
|
||||
/// Bus number, in the range `0..=255`.
|
||||
pub bus: u8,
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
//! scanned if function 0 is present. A stub PCI device is useful in that situation to present
|
||||
//! something to the guest on function 0.
|
||||
|
||||
use anyhow::Context;
|
||||
use base::RawDescriptor;
|
||||
use resources::Alloc;
|
||||
use resources::SystemAllocator;
|
||||
|
@ -106,8 +107,13 @@ pub struct StubPciParameters {
|
|||
pub revision: u8,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct StubPciDevice {
|
||||
#[serde(default)]
|
||||
#[serde(skip)]
|
||||
requested_address: PciAddress,
|
||||
#[serde(default)]
|
||||
#[serde(skip)]
|
||||
assigned_address: Option<PciAddress>,
|
||||
config_regs: PciConfiguration,
|
||||
}
|
||||
|
@ -210,6 +216,17 @@ impl Suspendable for StubPciDevice {
|
|||
// There are no workers to sleep/wake.
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn snapshot(&self) -> anyhow::Result<serde_json::Value> {
|
||||
serde_json::to_value(self).context("failed to snapshot")
|
||||
}
|
||||
|
||||
fn restore(&mut self, data: serde_json::Value) -> anyhow::Result<()> {
|
||||
let restored_device: StubPciDevice =
|
||||
serde_json::from_value(data).context("failed to restore snapshot")?;
|
||||
*self = restored_device;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -365,4 +382,54 @@ mod test {
|
|||
assert_eq!(params.class.programming_interface, 0x45);
|
||||
assert_eq!(params.revision, 52);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn stub_pci_device_snapshot_restore() -> anyhow::Result<()> {
|
||||
let mut device = StubPciDevice::new(&CONFIG);
|
||||
let init_reg_value = device.read_config_register(1);
|
||||
let snapshot_init = device.snapshot().unwrap();
|
||||
|
||||
// Modify config reg 1 and make sure it went through.
|
||||
let new_reg_value: u32 = 0xCAFE;
|
||||
device.write_config_register(1, 0, &new_reg_value.to_le_bytes());
|
||||
assert_eq!(device.read_config_register(1), new_reg_value);
|
||||
|
||||
// Capture a snapshot after the modification.
|
||||
let mut snapshot_modified = device.snapshot().unwrap();
|
||||
assert_ne!(snapshot_init, snapshot_modified);
|
||||
|
||||
// Modify the same register and verify that it's restored correctly.
|
||||
device.write_config_register(1, 0, &[0xBA, 0xBA]);
|
||||
assert_ne!(device.read_config_register(1), new_reg_value);
|
||||
assert_ne!(device.read_config_register(1), init_reg_value);
|
||||
device.restore(snapshot_init.clone())?;
|
||||
assert_eq!(device.read_config_register(1), init_reg_value);
|
||||
|
||||
// Capture a snapshot after restoring the initial snapshot.
|
||||
let mut snapshot_restored = device.snapshot().unwrap();
|
||||
assert_eq!(snapshot_init, snapshot_restored);
|
||||
|
||||
// Restore to the first modification and verify the values.
|
||||
device.restore(snapshot_modified.clone())?;
|
||||
assert_eq!(device.read_config_register(1), new_reg_value);
|
||||
snapshot_restored = device.snapshot().unwrap();
|
||||
assert_eq!(snapshot_modified, snapshot_restored);
|
||||
|
||||
/*
|
||||
Restore the initial snapshot and verify that addresses are not encoded.
|
||||
The addresses are only configurable during VM creation so they never
|
||||
change afterwards and are not part of the snapshot. Force a change
|
||||
to requested_address to confirm that.
|
||||
*/
|
||||
device.restore(snapshot_init.clone())?;
|
||||
device.requested_address = PciAddress {
|
||||
bus: 0x0d,
|
||||
dev: 0x0e,
|
||||
func: 0x4,
|
||||
};
|
||||
snapshot_modified = device.snapshot().unwrap();
|
||||
assert_eq!(snapshot_init, snapshot_modified);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue