hyperlight_host/mem/
shared_mem_snapshot.rs1use tracing::{Span, instrument};
18
19use super::memory_region::MemoryRegion;
20use super::shared_mem::SharedMemory;
21use crate::Result;
22
23#[derive(Clone)]
26pub(crate) struct SharedMemorySnapshot {
27 sandbox_id: u64,
29 snapshot: Vec<u8>,
31 regions: Vec<MemoryRegion>,
33}
34
35impl SharedMemorySnapshot {
36 #[instrument(err(Debug), skip_all, parent = Span::current(), level= "Trace")]
39 pub(super) fn new<S: SharedMemory>(
40 shared_mem: &mut S,
41 sandbox_id: u64,
42 regions: Vec<MemoryRegion>,
43 ) -> Result<Self> {
44 let snapshot = shared_mem.with_exclusivity(|e| e.copy_all_to_vec())??;
46 Ok(Self {
47 sandbox_id,
48 snapshot,
49 regions,
50 })
51 }
52
53 #[instrument(err(Debug), skip_all, parent = Span::current(), level= "Trace")]
56 pub(super) fn restore_from_snapshot<S: SharedMemory>(&self, shared_mem: &mut S) -> Result<()> {
57 shared_mem.with_exclusivity(|e| e.copy_from_slice(self.snapshot.as_slice(), 0))??;
58 Ok(())
59 }
60
61 pub(crate) fn sandbox_id(&self) -> u64 {
63 self.sandbox_id
64 }
65
66 pub(crate) fn regions(&self) -> &[MemoryRegion] {
68 &self.regions
69 }
70
71 #[instrument(skip_all, parent = Span::current(), level= "Trace")]
73 pub(super) fn mem_size(&self) -> usize {
74 self.snapshot.len()
75 }
76}
77
78#[cfg(test)]
79mod tests {
80 use hyperlight_common::mem::PAGE_SIZE_USIZE;
81
82 use crate::mem::shared_mem::ExclusiveSharedMemory;
83
84 #[test]
85 fn restore() {
86 let data1 = vec![b'a'; PAGE_SIZE_USIZE];
88 let data2 = vec![b'b'; PAGE_SIZE_USIZE];
89
90 let mut gm = ExclusiveSharedMemory::new(PAGE_SIZE_USIZE).unwrap();
91 gm.copy_from_slice(&data1, 0).unwrap();
92
93 let snapshot = super::SharedMemorySnapshot::new(&mut gm, 0, Vec::new()).unwrap();
95
96 gm.copy_from_slice(&data2, 0).unwrap();
98 assert_eq!(gm.as_slice(), &data2[..]);
99
100 snapshot.restore_from_snapshot(&mut gm).unwrap();
102 assert_eq!(gm.as_slice(), &data1[..]);
103 }
104
105 #[test]
106 fn snapshot_mem_size() {
107 let size = PAGE_SIZE_USIZE * 2;
108 let mut gm = ExclusiveSharedMemory::new(size).unwrap();
109
110 let snapshot = super::SharedMemorySnapshot::new(&mut gm, 0, Vec::new()).unwrap();
111 assert_eq!(snapshot.mem_size(), size);
112 }
113
114 #[test]
115 fn multiple_snapshots_independent() {
116 let mut gm = ExclusiveSharedMemory::new(PAGE_SIZE_USIZE).unwrap();
117
118 let pattern_a = vec![0xAA; PAGE_SIZE_USIZE];
120 gm.copy_from_slice(&pattern_a, 0).unwrap();
121 let snapshot_a = super::SharedMemorySnapshot::new(&mut gm, 1, Vec::new()).unwrap();
122
123 let pattern_b = vec![0xBB; PAGE_SIZE_USIZE];
125 gm.copy_from_slice(&pattern_b, 0).unwrap();
126 let snapshot_b = super::SharedMemorySnapshot::new(&mut gm, 2, Vec::new()).unwrap();
127
128 gm.copy_from_slice(&[0; PAGE_SIZE_USIZE], 0).unwrap();
130
131 snapshot_a.restore_from_snapshot(&mut gm).unwrap();
133 assert_eq!(gm.as_slice(), &pattern_a[..]);
134
135 snapshot_b.restore_from_snapshot(&mut gm).unwrap();
137 assert_eq!(gm.as_slice(), &pattern_b[..]);
138 }
139}