diff --git a/src/vmm/src/vstate/memory.rs b/src/vmm/src/vstate/memory.rs index 1b7114b4bca5..a2a03760960d 100644 --- a/src/vmm/src/vstate/memory.rs +++ b/src/vmm/src/vstate/memory.rs @@ -56,61 +56,6 @@ pub enum MemoryError { MemfdSetLen(std::io::Error), } -/// Defines the interface for snapshotting memory. -pub trait GuestMemoryExtension -where - Self: Sized, -{ - /// Creates a GuestMemoryMmap with `size` in MiB and guard pages. - fn with_file(file: &File, track_dirty_pages: bool) -> Result; - - /// Creates a GuestMemoryMmap with `size` in MiB and guard pages. - fn with_size(size: usize, track_dirty_pages: bool) -> Result; - - /// Creates a GuestMemoryMmap from raw regions with guard pages. - fn from_raw_regions( - regions: &[(GuestAddress, usize)], - track_dirty_pages: bool, - ) -> Result; - - /// Creates a GuestMemoryMmap from raw regions with no guard pages. - fn from_raw_regions_unguarded( - regions: &[(GuestAddress, usize)], - track_dirty_pages: bool, - ) -> Result; - - /// Creates a GuestMemoryMmap from raw regions with guard pages. - fn from_raw_regions_file( - regions: &[(FileOffset, GuestAddress, usize)], - track_dirty_pages: bool, - shared: bool, - ) -> Result; - - /// Creates a GuestMemoryMmap given a `file` containing the data - /// and a `state` containing mapping information. - fn from_state( - file: Option<&File>, - state: &GuestMemoryState, - track_dirty_pages: bool, - ) -> Result; - - /// Describes GuestMemoryMmap through a GuestMemoryState struct. - fn describe(&self) -> GuestMemoryState; - - /// Mark memory range as dirty - fn mark_dirty(&self, addr: GuestAddress, len: usize); - - /// Dumps all contents of GuestMemoryMmap to a writer. - fn dump(&self, writer: &mut T) -> Result<(), MemoryError>; - - /// Dumps all pages of GuestMemoryMmap present in `dirty_bitmap` to a writer. - fn dump_dirty( - &self, - writer: &mut T, - dirty_bitmap: &DirtyBitmap, - ) -> Result<(), MemoryError>; -} - /// State of a guest memory region saved to file/buffer. #[derive(Debug, PartialEq, Eq, Versionize)] // NOTICE: Any changes to this structure require a snapshot version bump. @@ -133,236 +78,240 @@ pub struct GuestMemoryState { pub regions: Vec, } -impl GuestMemoryExtension for GuestMemoryMmap { - /// Creates a GuestMemoryMmap with `size` in MiB and guard pages backed by memfd. - fn with_file(file: &File, track_dirty_pages: bool) -> Result { - let mem_size = file.metadata().map_err(MemoryError::FileError)?.len() as usize; - - let mut offset: u64 = 0; - let regions = crate::arch::arch_memory_regions(mem_size) - .iter() - .map(|(guest_address, region_size)| { - let file_clone = file.try_clone().map_err(MemoryError::FileError)?; - let file_offset = FileOffset::new(file_clone, offset); - offset += *region_size as u64; - Ok((file_offset, *guest_address, *region_size)) - }) - .collect::, MemoryError>>()?; - - Self::from_raw_regions_file(®ions, track_dirty_pages, true) - } - - /// Creates a GuestMemoryMmap with `size` in MiB and guard pages backed by anonymous memory. - fn with_size(size: usize, track_dirty_pages: bool) -> Result { - let mem_size = size << 20; - let regions = crate::arch::arch_memory_regions(mem_size); +/// Creates a GuestMemoryMmap with `size` in MiB and guard pages backed by memfd. +pub fn guest_mem_with_file( + file: &File, + track_dirty_pages: bool, +) -> Result { + let mem_size = file.metadata().map_err(MemoryError::FileError)?.len() as usize; + + let mut offset: u64 = 0; + let regions = crate::arch::arch_memory_regions(mem_size) + .iter() + .map(|(guest_address, region_size)| { + let file_clone = file.try_clone().map_err(MemoryError::FileError)?; + let file_offset = FileOffset::new(file_clone, offset); + offset += *region_size as u64; + Ok((file_offset, *guest_address, *region_size)) + }) + .collect::, MemoryError>>()?; + + guest_mem_from_raw_regions_file(®ions, track_dirty_pages, true) +} - Self::from_raw_regions(®ions, track_dirty_pages) - } +/// Creates a GuestMemoryMmap with `size` in MiB and guard pages backed by anonymous memory. +pub fn guest_mem_with_size( + size: usize, + track_dirty_pages: bool, +) -> Result { + let mem_size = size << 20; + let regions = crate::arch::arch_memory_regions(mem_size); - /// Creates a GuestMemoryMmap from raw regions with guard pages backed by anonymous memory. - fn from_raw_regions( - regions: &[(GuestAddress, usize)], - track_dirty_pages: bool, - ) -> Result { - let prot = libc::PROT_READ | libc::PROT_WRITE; - let flags = libc::MAP_NORESERVE | libc::MAP_PRIVATE | libc::MAP_ANONYMOUS; - - let regions = regions - .iter() - .map(|(guest_address, region_size)| { - let region = - build_guarded_region(None, *region_size, prot, flags, track_dirty_pages)?; - GuestRegionMmap::new(region, *guest_address).map_err(MemoryError::VmMemoryError) - }) - .collect::, MemoryError>>()?; - - GuestMemoryMmap::from_regions(regions).map_err(MemoryError::VmMemoryError) - } + guest_mem_from_raw_regions(®ions, track_dirty_pages) +} - /// Creates a GuestMemoryMmap from raw regions with no guard pages backed by anonymous memory. - fn from_raw_regions_unguarded( - regions: &[(GuestAddress, usize)], - track_dirty_pages: bool, - ) -> Result { - let prot = libc::PROT_READ | libc::PROT_WRITE; - let flags = libc::MAP_NORESERVE | libc::MAP_PRIVATE | libc::MAP_ANONYMOUS; - - let regions = regions - .iter() - .map(|(guest_address, region_size)| { - let bitmap = match track_dirty_pages { - true => Some(AtomicBitmap::with_len(*region_size)), - false => None, - }; - let region = MmapRegionBuilder::new_with_bitmap(*region_size, bitmap) - .with_mmap_prot(prot) - .with_mmap_flags(flags) - .build() - .map_err(MemoryError::MmapRegionError)?; - GuestRegionMmap::new(region, *guest_address).map_err(MemoryError::VmMemoryError) - }) - .collect::, MemoryError>>()?; - - GuestMemoryMmap::from_regions(regions).map_err(MemoryError::VmMemoryError) - } +/// Creates a GuestMemoryMmap from raw regions with guard pages backed by anonymous memory. +pub fn guest_mem_from_raw_regions( + regions: &[(GuestAddress, usize)], + track_dirty_pages: bool, +) -> Result { + let prot = libc::PROT_READ | libc::PROT_WRITE; + let flags = libc::MAP_NORESERVE | libc::MAP_PRIVATE | libc::MAP_ANONYMOUS; + + let regions = regions + .iter() + .map(|(guest_address, region_size)| { + let region = build_guarded_region(None, *region_size, prot, flags, track_dirty_pages)?; + GuestRegionMmap::new(region, *guest_address).map_err(MemoryError::VmMemoryError) + }) + .collect::, MemoryError>>()?; + + GuestMemoryMmap::from_regions(regions).map_err(MemoryError::VmMemoryError) +} - /// Creates a GuestMemoryMmap from raw regions with guard pages backed by file. - fn from_raw_regions_file( - regions: &[(FileOffset, GuestAddress, usize)], - track_dirty_pages: bool, - shared: bool, - ) -> Result { - let prot = libc::PROT_READ | libc::PROT_WRITE; - let flags = if shared { - libc::MAP_NORESERVE | libc::MAP_SHARED - } else { - libc::MAP_NORESERVE | libc::MAP_PRIVATE - }; - let regions = regions - .iter() - .map(|(file_offset, guest_address, region_size)| { - let region = build_guarded_region( - Some(file_offset), - *region_size, - prot, - flags, - track_dirty_pages, - )?; - GuestRegionMmap::new(region, *guest_address).map_err(MemoryError::VmMemoryError) - }) - .collect::, MemoryError>>()?; +/// Creates a GuestMemoryMmap from raw regions with no guard pages backed by anonymous memory. +pub fn guest_mem_from_raw_regions_unguarded( + regions: &[(GuestAddress, usize)], + track_dirty_pages: bool, +) -> Result { + let prot = libc::PROT_READ | libc::PROT_WRITE; + let flags = libc::MAP_NORESERVE | libc::MAP_PRIVATE | libc::MAP_ANONYMOUS; + + let regions = regions + .iter() + .map(|(guest_address, region_size)| { + let bitmap = match track_dirty_pages { + true => Some(AtomicBitmap::with_len(*region_size)), + false => None, + }; + let region = MmapRegionBuilder::new_with_bitmap(*region_size, bitmap) + .with_mmap_prot(prot) + .with_mmap_flags(flags) + .build() + .map_err(MemoryError::MmapRegionError)?; + GuestRegionMmap::new(region, *guest_address).map_err(MemoryError::VmMemoryError) + }) + .collect::, MemoryError>>()?; + + GuestMemoryMmap::from_regions(regions).map_err(MemoryError::VmMemoryError) +} - GuestMemoryMmap::from_regions(regions).map_err(MemoryError::VmMemoryError) - } +/// Creates a GuestMemoryMmap from raw regions with guard pages backed by file. +pub fn guest_mem_from_raw_regions_file( + regions: &[(FileOffset, GuestAddress, usize)], + track_dirty_pages: bool, + shared: bool, +) -> Result { + let prot = libc::PROT_READ | libc::PROT_WRITE; + let flags = if shared { + libc::MAP_NORESERVE | libc::MAP_SHARED + } else { + libc::MAP_NORESERVE | libc::MAP_PRIVATE + }; + let regions = regions + .iter() + .map(|(file_offset, guest_address, region_size)| { + let region = build_guarded_region( + Some(file_offset), + *region_size, + prot, + flags, + track_dirty_pages, + )?; + GuestRegionMmap::new(region, *guest_address).map_err(MemoryError::VmMemoryError) + }) + .collect::, MemoryError>>()?; + + GuestMemoryMmap::from_regions(regions).map_err(MemoryError::VmMemoryError) +} - /// Creates a GuestMemoryMmap backed by a `file` if present, otherwise backed - /// by anonymous memory. Memory layout and ranges are described in `state` param. - fn from_state( - file: Option<&File>, - state: &GuestMemoryState, - track_dirty_pages: bool, - ) -> Result { - match file { - Some(f) => { - let regions = state - .regions - .iter() - .map(|r| { - f.try_clone().map(|file_clone| { - let offset = FileOffset::new(file_clone, r.offset); - (offset, GuestAddress(r.base_address), r.size) - }) +/// Creates a GuestMemoryMmap backed by a `file` if present, otherwise backed +/// by anonymous memory. Memory layout and ranges are described in `state` param. +pub fn guest_mem_from_state( + file: Option<&File>, + state: &GuestMemoryState, + track_dirty_pages: bool, +) -> Result { + match file { + Some(f) => { + let regions = state + .regions + .iter() + .map(|r| { + f.try_clone().map(|file_clone| { + let offset = FileOffset::new(file_clone, r.offset); + (offset, GuestAddress(r.base_address), r.size) }) - .collect::, std::io::Error>>() - .map_err(MemoryError::FileError)?; + }) + .collect::, std::io::Error>>() + .map_err(MemoryError::FileError)?; - Self::from_raw_regions_file(®ions, track_dirty_pages, false) - } - None => { - let regions = state - .regions - .iter() - .map(|r| (GuestAddress(r.base_address), r.size)) - .collect::>(); - Self::from_raw_regions(®ions, track_dirty_pages) - } + guest_mem_from_raw_regions_file(®ions, track_dirty_pages, false) + } + None => { + let regions = state + .regions + .iter() + .map(|r| (GuestAddress(r.base_address), r.size)) + .collect::>(); + guest_mem_from_raw_regions(®ions, track_dirty_pages) } } +} - /// Describes GuestMemoryMmap through a GuestMemoryState struct. - fn describe(&self) -> GuestMemoryState { - let mut guest_memory_state = GuestMemoryState::default(); - let mut offset = 0; - self.iter().for_each(|region| { - guest_memory_state.regions.push(GuestMemoryRegionState { - base_address: region.start_addr().0, - size: region.len() as usize, - offset, - }); - - offset += region.len(); +/// Describes GuestMemoryMmap through a GuestMemoryState struct. +pub fn guest_mem_describe(mem: &GuestMemoryMmap) -> GuestMemoryState { + let mut guest_memory_state = GuestMemoryState::default(); + let mut offset = 0; + mem.iter().for_each(|region| { + guest_memory_state.regions.push(GuestMemoryRegionState { + base_address: region.start_addr().0, + size: region.len() as usize, + offset, }); - guest_memory_state - } - /// Mark memory range as dirty - fn mark_dirty(&self, addr: GuestAddress, len: usize) { - let _ = self.try_access(len, addr, |_total, count, caddr, region| { - if let Some(bitmap) = region.bitmap() { - bitmap.mark_dirty(caddr.0 as usize, count); - } - Ok(count) - }); - } + offset += region.len(); + }); + guest_memory_state +} - /// Dumps all contents of GuestMemoryMmap to a writer. - fn dump(&self, writer: &mut T) -> Result<(), MemoryError> { - self.iter() - .try_for_each(|region| Ok(writer.write_all_volatile(®ion.as_volatile_slice()?)?)) - .map_err(MemoryError::WriteMemory) - } +/// Mark memory range as dirty +pub fn guest_mem_mark_dirty(mem: &GuestMemoryMmap, addr: GuestAddress, len: usize) { + let _ = mem.try_access(len, addr, |_total, count, caddr, region| { + if let Some(bitmap) = region.bitmap() { + bitmap.mark_dirty(caddr.0 as usize, count); + } + Ok(count) + }); +} - /// Dumps all pages of GuestMemoryMmap present in `dirty_bitmap` to a writer. - fn dump_dirty( - &self, - writer: &mut T, - dirty_bitmap: &DirtyBitmap, - ) -> Result<(), MemoryError> { - let mut writer_offset = 0; - let page_size = get_page_size().map_err(MemoryError::PageSize)?; - - self.iter() - .enumerate() - .try_for_each(|(slot, region)| { - let kvm_bitmap = dirty_bitmap.get(&slot).unwrap(); - let firecracker_bitmap = region.bitmap(); - let mut write_size = 0; - let mut dirty_batch_start: u64 = 0; - - for (i, v) in kvm_bitmap.iter().enumerate() { - for j in 0..64 { - let is_kvm_page_dirty = ((v >> j) & 1u64) != 0u64; - let page_offset = ((i * 64) + j) * page_size; - let is_firecracker_page_dirty = firecracker_bitmap.dirty_at(page_offset); - if is_kvm_page_dirty || is_firecracker_page_dirty { - // We are at the start of a new batch of dirty pages. - if write_size == 0 { - // Seek forward over the unmodified pages. - writer - .seek(SeekFrom::Start(writer_offset + page_offset as u64)) - .unwrap(); - dirty_batch_start = page_offset as u64; - } - write_size += page_size; - } else if write_size > 0 { - // We are at the end of a batch of dirty pages. - writer.write_all_volatile( - ®ion.get_slice( - MemoryRegionAddress(dirty_batch_start), - write_size, - )?, - )?; - - write_size = 0; +/// Dumps all contents of GuestMemoryMmap to a writer. +pub fn guest_mem_dump( + mem: &GuestMemoryMmap, + writer: &mut T, +) -> Result<(), MemoryError> { + mem.iter() + .try_for_each(|region| Ok(writer.write_all_volatile(®ion.as_volatile_slice()?)?)) + .map_err(MemoryError::WriteMemory) +} + +/// Dumps all pages of GuestMemoryMmap present in `dirty_bitmap` to a writer. +pub fn guest_mem_dump_dirty( + mem: &GuestMemoryMmap, + writer: &mut T, + dirty_bitmap: &DirtyBitmap, +) -> Result<(), MemoryError> { + let mut writer_offset = 0; + let page_size = get_page_size().map_err(MemoryError::PageSize)?; + + mem.iter() + .enumerate() + .try_for_each(|(slot, region)| { + let kvm_bitmap = dirty_bitmap.get(&slot).unwrap(); + let firecracker_bitmap = region.bitmap(); + let mut write_size = 0; + let mut dirty_batch_start: u64 = 0; + + for (i, v) in kvm_bitmap.iter().enumerate() { + for j in 0..64 { + let is_kvm_page_dirty = ((v >> j) & 1u64) != 0u64; + let page_offset = ((i * 64) + j) * page_size; + let is_firecracker_page_dirty = firecracker_bitmap.dirty_at(page_offset); + if is_kvm_page_dirty || is_firecracker_page_dirty { + // We are at the start of a new batch of dirty pages. + if write_size == 0 { + // Seek forward over the unmodified pages. + writer + .seek(SeekFrom::Start(writer_offset + page_offset as u64)) + .unwrap(); + dirty_batch_start = page_offset as u64; } + write_size += page_size; + } else if write_size > 0 { + // We are at the end of a batch of dirty pages. + writer.write_all_volatile( + ®ion + .get_slice(MemoryRegionAddress(dirty_batch_start), write_size)?, + )?; + + write_size = 0; } } + } - if write_size > 0 { - writer.write_all_volatile( - ®ion.get_slice(MemoryRegionAddress(dirty_batch_start), write_size)?, - )?; - } - writer_offset += region.len(); - if let Some(bitmap) = firecracker_bitmap { - bitmap.reset(); - } + if write_size > 0 { + writer.write_all_volatile( + ®ion.get_slice(MemoryRegionAddress(dirty_batch_start), write_size)?, + )?; + } + writer_offset += region.len(); + if let Some(bitmap) = firecracker_bitmap { + bitmap.reset(); + } - Ok(()) - }) - .map_err(MemoryError::WriteMemory) - } + Ok(()) + }) + .map_err(MemoryError::WriteMemory) } /// Creates a memfd file with the `size` in MiB. @@ -567,7 +516,7 @@ mod tests { (GuestAddress(0x30000), region_size), ]; - let guest_memory = GuestMemoryMmap::from_raw_regions(®ions, false).unwrap(); + let guest_memory = guest_mem_from_raw_regions(®ions, false).unwrap(); guest_memory.iter().for_each(|region| { validate_guard_region(region); }); @@ -583,7 +532,7 @@ mod tests { (GuestAddress(0x30000), region_size), ]; - let guest_memory = GuestMemoryMmap::from_raw_regions(®ions, false).unwrap(); + let guest_memory = guest_mem_from_raw_regions(®ions, false).unwrap(); guest_memory.iter().for_each(|region| { assert!(region.bitmap().is_none()); }); @@ -599,7 +548,7 @@ mod tests { (GuestAddress(0x30000), region_size), ]; - let guest_memory = GuestMemoryMmap::from_raw_regions(®ions, true).unwrap(); + let guest_memory = guest_mem_from_raw_regions(®ions, true).unwrap(); guest_memory.iter().for_each(|region| { assert!(region.bitmap().is_some()); }); @@ -618,8 +567,7 @@ mod tests { (GuestAddress(0x30000), region_size), ]; - let guest_memory = - GuestMemoryMmap::from_raw_regions_unguarded(®ions, false).unwrap(); + let guest_memory = guest_mem_from_raw_regions_unguarded(®ions, false).unwrap(); guest_memory.iter().for_each(|region| { assert!(region.bitmap().is_none()); }); @@ -635,7 +583,7 @@ mod tests { (GuestAddress(0x30000), region_size), ]; - let guest_memory = GuestMemoryMmap::from_raw_regions_unguarded(®ions, true).unwrap(); + let guest_memory = guest_mem_from_raw_regions_unguarded(®ions, true).unwrap(); guest_memory.iter().for_each(|region| { assert!(region.bitmap().is_some()); }); @@ -675,8 +623,7 @@ mod tests { // Test that all regions are guarded. { - let guest_memory = - GuestMemoryMmap::from_raw_regions_file(®ions, false, false).unwrap(); + let guest_memory = guest_mem_from_raw_regions_file(®ions, false, false).unwrap(); guest_memory.iter().for_each(|region| { assert_eq!(region.size(), region_size); assert!(region.file_offset().is_none()); @@ -687,8 +634,7 @@ mod tests { // Check dirty page tracking is off. { - let guest_memory = - GuestMemoryMmap::from_raw_regions_file(®ions, false, false).unwrap(); + let guest_memory = guest_mem_from_raw_regions_file(®ions, false, false).unwrap(); guest_memory.iter().for_each(|region| { assert!(region.bitmap().is_none()); }); @@ -696,8 +642,7 @@ mod tests { // Check dirty page tracking is on. { - let guest_memory = - GuestMemoryMmap::from_raw_regions_file(®ions, true, false).unwrap(); + let guest_memory = guest_mem_from_raw_regions_file(®ions, true, false).unwrap(); guest_memory.iter().for_each(|region| { assert!(region.bitmap().is_some()); }); @@ -714,7 +659,7 @@ mod tests { (GuestAddress(region_size as u64), region_size), // pages 3-5 (GuestAddress(region_size as u64 * 2), region_size), // pages 6-8 ]; - let guest_memory = GuestMemoryMmap::from_raw_regions(®ions, true).unwrap(); + let guest_memory = guest_mem_from_raw_regions(®ions, true).unwrap(); let dirty_map = [ // page 0: not dirty @@ -732,7 +677,7 @@ mod tests { // Mark dirty memory for (addr, len, dirty) in &dirty_map { if *dirty { - guest_memory.mark_dirty(GuestAddress(*addr as u64), *len); + guest_mem_mark_dirty(&guest_memory, GuestAddress(*addr as u64), *len); } } @@ -764,7 +709,7 @@ mod tests { (GuestAddress(0), page_size), (GuestAddress(page_size as u64 * 2), page_size), ]; - let guest_memory = GuestMemoryMmap::from_raw_regions(&mem_regions[..], true).unwrap(); + let guest_memory = guest_mem_from_raw_regions(&mem_regions[..], true).unwrap(); let expected_memory_state = GuestMemoryState { regions: vec![ @@ -781,7 +726,7 @@ mod tests { ], }; - let actual_memory_state = guest_memory.describe(); + let actual_memory_state = guest_mem_describe(&guest_memory); assert_eq!(expected_memory_state, actual_memory_state); // Two regions of three pages each, with a one page gap between them. @@ -789,7 +734,7 @@ mod tests { (GuestAddress(0), page_size * 3), (GuestAddress(page_size as u64 * 4), page_size * 3), ]; - let guest_memory = GuestMemoryMmap::from_raw_regions(&mem_regions[..], true).unwrap(); + let guest_memory = guest_mem_from_raw_regions(&mem_regions[..], true).unwrap(); let expected_memory_state = GuestMemoryState { regions: vec![ @@ -806,7 +751,7 @@ mod tests { ], }; - let actual_memory_state = guest_memory.describe(); + let actual_memory_state = guest_mem_describe(&guest_memory); assert_eq!(expected_memory_state, actual_memory_state); } @@ -822,7 +767,7 @@ mod tests { (region_1_address, region_size), (region_2_address, region_size), ]; - let guest_memory = GuestMemoryMmap::from_raw_regions(&mem_regions, true).unwrap(); + let guest_memory = guest_mem_from_raw_regions(&mem_regions, true).unwrap(); // Check that Firecracker bitmap is clean. guest_memory.iter().for_each(|r| { assert!(!r.bitmap().dirty_at(0)); @@ -838,14 +783,14 @@ mod tests { .write(&second_region, region_2_address) .unwrap(); - let memory_state = guest_memory.describe(); + let memory_state = guest_mem_describe(&guest_memory); // dump the full memory. let mut memory_file = TempFile::new().unwrap().into_file(); - guest_memory.dump(&mut memory_file).unwrap(); + guest_mem_dump(&guest_memory, &mut memory_file).unwrap(); let restored_guest_memory = - GuestMemoryMmap::from_state(Some(&memory_file), &memory_state, false).unwrap(); + guest_mem_from_state(Some(&memory_file), &memory_state, false).unwrap(); // Check that the region contents are the same. let mut restored_region = vec![0u8; page_size * 2]; @@ -872,7 +817,7 @@ mod tests { (region_1_address, region_size), (region_2_address, region_size), ]; - let guest_memory = GuestMemoryMmap::from_raw_regions(&mem_regions, true).unwrap(); + let guest_memory = guest_mem_from_raw_regions(&mem_regions, true).unwrap(); // Check that Firecracker bitmap is clean. guest_memory.iter().for_each(|r| { assert!(!r.bitmap().dirty_at(0)); @@ -888,7 +833,7 @@ mod tests { .write(&second_region, region_2_address) .unwrap(); - let memory_state = guest_memory.describe(); + let memory_state = guest_mem_describe(&guest_memory); // Dump only the dirty pages. // First region pages: [dirty, clean] @@ -898,11 +843,11 @@ mod tests { dirty_bitmap.insert(1, vec![0b10]); let mut file = TempFile::new().unwrap().into_file(); - guest_memory.dump_dirty(&mut file, &dirty_bitmap).unwrap(); + guest_mem_dump_dirty(&guest_memory, &mut file, &dirty_bitmap).unwrap(); // We can restore from this because this is the first dirty dump. let restored_guest_memory = - GuestMemoryMmap::from_state(Some(&file), &memory_state, false).unwrap(); + guest_mem_from_state(Some(&file), &memory_state, false).unwrap(); // Check that the region contents are the same. let mut restored_region = vec![0u8; region_size]; @@ -930,7 +875,7 @@ mod tests { .write(&twos, GuestAddress(page_size as u64)) .unwrap(); - guest_memory.dump_dirty(&mut reader, &dirty_bitmap).unwrap(); + guest_mem_dump_dirty(&guest_memory, &mut reader, &dirty_bitmap).unwrap(); // Check that only the dirty regions are dumped. let mut diff_file_content = Vec::new();