diff --git a/src/guest_memory.rs b/src/guest_memory.rs index d2ccf714..278f229d 100644 --- a/src/guest_memory.rs +++ b/src/guest_memory.rs @@ -289,6 +289,26 @@ pub trait GuestMemoryRegion: Bytes { fn as_volatile_slice(&self) -> Result { self.get_slice(MemoryRegionAddress(0), self.len() as usize) } + + /// Show if the region is based on the `HugeTLBFS`. + /// Returns Some(true) if the region is backed by hugetlbfs. + /// None represents that no information is available. + /// + /// # Examples (uses the `backend-mmap` feature) + /// + /// ``` + /// # #[cfg(feature = "backend-mmap")] + /// # { + /// # use vm_memory::{GuestAddress, GuestMemory, GuestMemoryMmap, GuestRegionMmap}; + /// let addr = GuestAddress(0x1000); + /// let mem = GuestMemoryMmap::from_ranges(&[(addr, 0x1000)]).unwrap(); + /// let r = mem.find_region(addr).unwrap(); + /// assert_eq!(r.is_hugetlbfs(), None); + /// # } + /// ``` + fn is_hugetlbfs(&self) -> Option { + None + } } /// `GuestAddressSpace` provides a way to retrieve a `GuestMemory` object. @@ -1199,4 +1219,13 @@ mod tests { crate::bytes::tests::check_atomic_accesses(mem, addr, bad_addr); } + + #[cfg(feature = "backend-mmap")] + #[test] + fn test_guest_memory_mmap_is_hugetlbfs() { + let addr = GuestAddress(0x1000); + let mem = GuestMemoryMmap::from_ranges(&[(addr, 0x1000)]).unwrap(); + let r = mem.find_region(addr).unwrap(); + assert_eq!(r.is_hugetlbfs(), None); + } } diff --git a/src/mmap.rs b/src/mmap.rs index 936dcb46..f8386b45 100644 --- a/src/mmap.rs +++ b/src/mmap.rs @@ -456,6 +456,10 @@ impl GuestMemoryRegion for GuestRegionMmap { let slice = self.mapping.get_slice(offset.raw_value() as usize, count)?; Ok(slice) } + + fn is_hugetlbfs(&self) -> Option { + self.mapping.is_hugetlbfs() + } } /// [`GuestMemory`](trait.GuestMemory.html) implementation that mmaps the guest's memory diff --git a/src/mmap_unix.rs b/src/mmap_unix.rs index 0f91c8e2..803fb686 100644 --- a/src/mmap_unix.rs +++ b/src/mmap_unix.rs @@ -90,6 +90,7 @@ pub struct MmapRegion { prot: i32, flags: i32, owned: bool, + hugetlbfs: Option, } // Send and Sync aren't automatically inherited for the raw address pointer. @@ -172,6 +173,7 @@ impl MmapRegion { prot, flags, owned: true, + hugetlbfs: None, }) } @@ -213,6 +215,7 @@ impl MmapRegion { prot, flags, owned: false, + hugetlbfs: None, }) } @@ -272,6 +275,16 @@ impl MmapRegion { } false } + + /// Set the hugetlbfs of the region + pub fn set_hugetlbfs(&mut self, hugetlbfs: bool) { + self.hugetlbfs = Some(hugetlbfs) + } + + /// Returns `true` if the region is hugetlbfs + pub fn is_hugetlbfs(&self) -> Option { + self.hugetlbfs + } } impl AsSlice for MmapRegion { @@ -354,6 +367,45 @@ mod tests { ); } + #[test] + fn test_mmap_region_set_hugetlbfs() { + assert!(MmapRegion::new(0).is_err()); + + let size = 4096; + + let r = MmapRegion::new(size).unwrap(); + assert_eq!(r.size(), size); + assert!(r.file_offset().is_none()); + assert_eq!(r.prot(), libc::PROT_READ | libc::PROT_WRITE); + assert_eq!( + r.flags(), + libc::MAP_ANONYMOUS | libc::MAP_NORESERVE | libc::MAP_PRIVATE + ); + assert_eq!(r.is_hugetlbfs(), None); + + let mut r = MmapRegion::new(size).unwrap(); + r.set_hugetlbfs(false); + assert_eq!(r.size(), size); + assert!(r.file_offset().is_none()); + assert_eq!(r.prot(), libc::PROT_READ | libc::PROT_WRITE); + assert_eq!( + r.flags(), + libc::MAP_ANONYMOUS | libc::MAP_NORESERVE | libc::MAP_PRIVATE + ); + assert_eq!(r.is_hugetlbfs(), Some(false)); + + let mut r = MmapRegion::new(size).unwrap(); + r.set_hugetlbfs(true); + assert_eq!(r.size(), size); + assert!(r.file_offset().is_none()); + assert_eq!(r.prot(), libc::PROT_READ | libc::PROT_WRITE); + assert_eq!( + r.flags(), + libc::MAP_ANONYMOUS | libc::MAP_NORESERVE | libc::MAP_PRIVATE + ); + assert_eq!(r.is_hugetlbfs(), Some(true)); + } + #[test] fn test_mmap_region_from_file() { let mut f = TempFile::new().unwrap().into_file(); diff --git a/src/mmap_windows.rs b/src/mmap_windows.rs index ce58999a..b7155c4e 100644 --- a/src/mmap_windows.rs +++ b/src/mmap_windows.rs @@ -175,6 +175,11 @@ impl MmapRegion { pub fn file_offset(&self) -> Option<&FileOffset> { self.file_offset.as_ref() } + + /// This information is not available on Windows platforms. + pub fn is_hugetlbfs(&self) -> Option { + None + } } impl AsSlice for MmapRegion {