diff options
author | Alyssa Ross <hi@alyssa.is> | 2020-02-09 17:46:45 +0000 |
---|---|---|
committer | Alyssa Ross <hi@alyssa.is> | 2020-06-15 09:36:02 +0000 |
commit | b8f316251bc594cb7d12e4bf0e383362944b5da3 (patch) | |
tree | c674ee5594da5aa34555f0d4721cf88165618918 /sys_util/src | |
parent | 1a522613c469cbab90f7fa615cf359c7b55676ca (diff) | |
download | crosvm-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.rs | 28 |
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; |