summary refs log tree commit diff
path: root/sys_util/src
diff options
context:
space:
mode:
authorAlyssa Ross <hi@alyssa.is>2020-02-09 17:46:45 +0000
committerAlyssa Ross <hi@alyssa.is>2020-06-15 09:36:02 +0000
commitb8f316251bc594cb7d12e4bf0e383362944b5da3 (patch)
treec674ee5594da5aa34555f0d4721cf88165618918 /sys_util/src
parent1a522613c469cbab90f7fa615cf359c7b55676ca (diff)
downloadcrosvm-b8f316251bc594cb7d12e4bf0e383362944b5da3.tar
crosvm-b8f316251bc594cb7d12e4bf0e383362944b5da3.tar.gz
crosvm-b8f316251bc594cb7d12e4bf0e383362944b5da3.tar.bz2
crosvm-b8f316251bc594cb7d12e4bf0e383362944b5da3.tar.lz
crosvm-b8f316251bc594cb7d12e4bf0e383362944b5da3.tar.xz
crosvm-b8f316251bc594cb7d12e4bf0e383362944b5da3.tar.zst
crosvm-b8f316251bc594cb7d12e4bf0e383362944b5da3.zip
guest_memory: allow creating with an existing memfd
This will allow creating GuestMemory structs representing memory of
VMs being managed by other processes.
Diffstat (limited to 'sys_util/src')
-rw-r--r--sys_util/src/guest_memory.rs28
1 files changed, 23 insertions, 5 deletions
diff --git a/sys_util/src/guest_memory.rs b/sys_util/src/guest_memory.rs
index b13b8cc..0728b77 100644
--- a/sys_util/src/guest_memory.rs
+++ b/sys_util/src/guest_memory.rs
@@ -28,6 +28,7 @@ pub enum Error {
     MemoryRegionOverlap,
     MemoryRegionTooLarge(u64),
     MemoryNotAligned,
+    MemoryBadSize,
     MemoryCreationFailed(errno::Error),
     MemorySetSizeFailed(errno::Error),
     MemoryAddSealsFailed(errno::Error),
@@ -57,6 +58,7 @@ impl Display for Error {
             MemoryRegionOverlap => write!(f, "memory regions overlap"),
             MemoryRegionTooLarge(size) => write!(f, "memory region size {} is too large", size),
             MemoryNotAligned => write!(f, "memfd regions must be page aligned"),
+            MemoryBadSize => write!(f, "memfd is wrong size for guest memory regions"),
             MemoryCreationFailed(_) => write!(f, "failed to create memfd region"),
             MemorySetSizeFailed(e) => write!(f, "failed to set memfd region size: {}", e),
             MemoryAddSealsFailed(e) => write!(f, "failed to set seals on memfd region: {}", e),
@@ -124,8 +126,9 @@ impl AsRef<SharedMemory> for GuestMemory {
 }
 
 impl GuestMemory {
-    /// Creates backing memfd for GuestMemory regions
-    fn create_memfd(ranges: &[(GuestAddress, u64)]) -> Result<SharedMemory> {
+    /// Calculates the page-aligned size for guest memory ranges.
+    /// This will be the size of the host memory allocated for the guest memory.
+    fn aligned_size(ranges: &[(GuestAddress, u64)]) -> Result<u64> {
         let mut aligned_size = 0;
         let pg_size = pagesize();
         for range in ranges {
@@ -135,7 +138,11 @@ impl GuestMemory {
 
             aligned_size += range.1;
         }
+        Ok(aligned_size)
+    }
 
+    /// Creates backing memfd for GuestMemory regions
+    fn create_memfd(ranges: &[(GuestAddress, u64)]) -> Result<SharedMemory> {
         let mut seals = MemfdSeals::new();
 
         seals.set_shrink_seal();
@@ -144,7 +151,7 @@ impl GuestMemory {
 
         let mut memfd = SharedMemory::named("crosvm_guest").map_err(Error::MemoryCreationFailed)?;
         memfd
-            .set_size(aligned_size)
+            .set_size(GuestMemory::aligned_size(ranges)?)
             .map_err(Error::MemorySetSizeFailed)?;
         memfd
             .add_seals(seals)
@@ -153,12 +160,23 @@ impl GuestMemory {
         Ok(memfd)
     }
 
-    /// Creates a container for guest memory regions.
+    /// Allocates guest memory regions, and creates a container for them.
     /// Valid memory regions are specified as a Vec of (Address, Size) tuples sorted by Address.
     pub fn new(ranges: &[(GuestAddress, u64)]) -> Result<GuestMemory> {
         // Create memfd
-
         let memfd = GuestMemory::create_memfd(ranges)?;
+        GuestMemory::with_memfd(ranges, memfd)
+    }
+
+    /// Creates a container for guest memory regions.
+    /// Valid memory regions are specified as a Vec of (Address, Size) tuples sorted by Address.
+    /// The memfd must be the correct size for the ranges.
+    pub fn with_memfd(ranges: &[(GuestAddress, u64)], memfd: SharedMemory) -> Result<GuestMemory> {
+        // Check the given memfd is the correct size for the given ranges.
+        if memfd.size() != GuestMemory::aligned_size(ranges)? {
+            return Err(Error::MemoryBadSize);
+        }
+
         // Create memory regions
         let mut regions = Vec::<MemoryRegion>::new();
         let mut offset = 0;