vmm/devices/virtio/rng/
persist.rs1use std::sync::Arc;
7
8use serde::{Deserialize, Serialize};
9
10use crate::devices::virtio::generated::virtio_ids::VIRTIO_ID_RNG;
11use crate::devices::virtio::persist::{PersistError as VirtioStateError, VirtioDeviceState};
12use crate::devices::virtio::queue::FIRECRACKER_MAX_QUEUE_SIZE;
13use crate::devices::virtio::rng::{Entropy, EntropyError, RNG_NUM_QUEUES};
14use crate::devices::virtio::transport::VirtioInterrupt;
15use crate::rate_limiter::RateLimiter;
16use crate::rate_limiter::persist::RateLimiterState;
17use crate::snapshot::Persist;
18use crate::vstate::memory::GuestMemoryMmap;
19
20#[derive(Debug, Clone, Serialize, Deserialize)]
21pub struct EntropyState {
22 pub virtio_state: VirtioDeviceState,
23 rate_limiter_state: RateLimiterState,
24}
25
26#[derive(Debug)]
27pub struct EntropyConstructorArgs {
28 pub mem: GuestMemoryMmap,
29}
30
31#[derive(Debug, thiserror::Error, displaydoc::Display)]
32pub enum EntropyPersistError {
33 CreateEntropy(#[from] EntropyError),
35 VirtioState(#[from] VirtioStateError),
37 RestoreRateLimiter(#[from] std::io::Error),
39}
40
41impl Persist<'_> for Entropy {
42 type State = EntropyState;
43 type ConstructorArgs = EntropyConstructorArgs;
44 type Error = EntropyPersistError;
45
46 fn save(&self) -> Self::State {
47 EntropyState {
48 virtio_state: VirtioDeviceState::from_device(self),
49 rate_limiter_state: self.rate_limiter().save(),
50 }
51 }
52
53 fn restore(
54 constructor_args: Self::ConstructorArgs,
55 state: &Self::State,
56 ) -> Result<Self, Self::Error> {
57 let queues = state.virtio_state.build_queues_checked(
58 &constructor_args.mem,
59 VIRTIO_ID_RNG,
60 RNG_NUM_QUEUES,
61 FIRECRACKER_MAX_QUEUE_SIZE,
62 )?;
63
64 let rate_limiter = RateLimiter::restore((), &state.rate_limiter_state)?;
65 let mut entropy = Entropy::new_with_queues(queues, rate_limiter)?;
66 entropy.set_avail_features(state.virtio_state.avail_features);
67 entropy.set_acked_features(state.virtio_state.acked_features);
68
69 Ok(entropy)
70 }
71}
72
73#[cfg(test)]
74mod tests {
75
76 use super::*;
77 use crate::devices::virtio::device::VirtioDevice;
78 use crate::devices::virtio::rng::device::ENTROPY_DEV_ID;
79 use crate::devices::virtio::test_utils::default_interrupt;
80 use crate::devices::virtio::test_utils::test::create_virtio_mem;
81 use crate::snapshot::Snapshot;
82
83 #[test]
84 fn test_persistence() {
85 let mut mem = vec![0u8; 4096];
86 let entropy = Entropy::new(RateLimiter::default()).unwrap();
87
88 Snapshot::new(entropy.save())
89 .save(&mut mem.as_mut_slice())
90 .unwrap();
91
92 let guest_mem = create_virtio_mem();
93 let restored = Entropy::restore(
94 EntropyConstructorArgs { mem: guest_mem },
95 &Snapshot::load_without_crc_check(mem.as_slice())
96 .unwrap()
97 .data,
98 )
99 .unwrap();
100
101 assert_eq!(restored.device_type(), VIRTIO_ID_RNG);
102 assert_eq!(restored.id(), ENTROPY_DEV_ID);
103 assert!(!restored.is_activated());
104 assert!(!entropy.is_activated());
105 assert_eq!(restored.avail_features(), entropy.avail_features());
106 assert_eq!(restored.acked_features(), entropy.acked_features());
107 }
108}