diff --git a/src/guest_memory.rs b/src/guest_memory.rs index 08d0a530..a65ff4b8 100644 --- a/src/guest_memory.rs +++ b/src/guest_memory.rs @@ -159,6 +159,15 @@ impl FileOffset { } } +/// Configurations options usable for Guest Memory +#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, Ord, PartialOrd)] +pub struct GuestMemoryOptions { + /// Use huge pages to back guest memory + pub huge_page: bool, + /// Use transparent huge pages to back guest memory + pub transparent_huge_page: bool, +} + /// Represents a continuous region of guest physical memory. #[allow(clippy::len_without_is_empty)] pub trait GuestMemoryRegion: Bytes { diff --git a/src/mmap.rs b/src/mmap.rs index 406bc867..7505ae89 100644 --- a/src/mmap.rs +++ b/src/mmap.rs @@ -22,7 +22,7 @@ use std::sync::Arc; use crate::address::Address; use crate::guest_memory::{ - self, FileOffset, GuestAddress, GuestMemory, GuestMemoryRegion, GuestUsize, MemoryRegionAddress, + self, FileOffset, GuestAddress, GuestMemory, GuestMemoryOptions, GuestMemoryRegion, GuestUsize, MemoryRegionAddress, }; use crate::volatile_memory::{VolatileMemory, VolatileSlice}; use crate::Bytes; @@ -391,6 +391,7 @@ impl GuestMemoryRegion for GuestRegionMmap { /// virtual address space of the calling process. #[derive(Clone, Debug, Default)] pub struct GuestMemoryMmap { + options: GuestMemoryOptions, regions: Vec>, } @@ -416,6 +417,7 @@ impl GuestMemoryMmap { A: Borrow<(GuestAddress, usize, Option)>, T: IntoIterator, { + let options = GuestMemoryOptions {huge_page : false, transparent_huge_page : false}; Self::from_regions( ranges .into_iter() @@ -424,9 +426,9 @@ impl GuestMemoryMmap { let size = x.borrow().1; if let Some(ref f_off) = x.borrow().2 { - MmapRegion::from_file(f_off.clone(), size) + MmapRegion::from_file(f_off.clone(), size, options) } else { - MmapRegion::new(size) + MmapRegion::new(size, options) } .map_err(Error::MmapRegion) .and_then(|r| GuestRegionMmap::new(r, guest_base)) @@ -476,7 +478,7 @@ impl GuestMemoryMmap { } } - Ok(Self { regions }) + Ok(Self { regions, options: GuestMemoryOptions {huge_page : false, transparent_huge_page : false} }) } /// Insert a region into the `GuestMemoryMmap` object and return a new `GuestMemoryMmap`. @@ -509,7 +511,7 @@ impl GuestMemoryMmap { if self.regions.get(region_index).unwrap().size() as GuestUsize == size { let mut regions = self.regions.clone(); let region = regions.remove(region_index); - return Ok((Self { regions }, region)); + return Ok((Self { regions, options: GuestMemoryOptions {huge_page : false, transparent_huge_page : false} }, region)); } } diff --git a/src/mmap_unix.rs b/src/mmap_unix.rs index de583f73..aeb3d36a 100644 --- a/src/mmap_unix.rs +++ b/src/mmap_unix.rs @@ -20,6 +20,7 @@ use std::result; use libc; use crate::guest_memory::FileOffset; +use crate::guest_memory::GuestMemoryOptions; use crate::mmap::{check_file_offset, AsSlice}; use crate::volatile_memory::{self, compute_offset, VolatileMemory, VolatileSlice}; @@ -93,12 +94,13 @@ impl MmapRegion { /// /// # Arguments /// * `size` - The size of the memory region in bytes. - pub fn new(size: usize) -> Result { + pub fn new(size: usize, options: GuestMemoryOptions) -> Result { Self::build( None, size, libc::PROT_READ | libc::PROT_WRITE, libc::MAP_ANONYMOUS | libc::MAP_NORESERVE | libc::MAP_PRIVATE, + options ) } @@ -108,12 +110,13 @@ impl MmapRegion { /// * `file_offset` - The mapping will be created at offset `file_offset.start` in the file /// referred to by `file_offset.file`. /// * `size` - The size of the memory region in bytes. - pub fn from_file(file_offset: FileOffset, size: usize) -> Result { + pub fn from_file(file_offset: FileOffset, size: usize, options: GuestMemoryOptions) -> Result { Self::build( Some(file_offset), size, libc::PROT_READ | libc::PROT_WRITE, libc::MAP_NORESERVE | libc::MAP_SHARED, + options ) } @@ -132,6 +135,7 @@ impl MmapRegion { size: usize, prot: i32, flags: i32, + options: GuestMemoryOptions, ) -> Result { // Forbid MAP_FIXED, as it doesn't make sense in this context, and is pretty dangerous // in general. @@ -154,6 +158,14 @@ impl MmapRegion { return Err(Error::Mmap(io::Error::last_os_error())); } + if options.huge_page { + if options.transparent_huge_page { + if size > 2 * 1024 * 4096 { + let _ret = unsafe { libc::madvise(addr, size, libc::MADV_HUGEPAGE) }; + } + } + } + Ok(Self { addr: addr as *mut u8, size,