22// SPDX-License-Identifier: Apache-2.0
33
44use std:: convert:: From ;
5+ use std:: fs:: File ;
56use std:: path:: PathBuf ;
67use std:: sync:: { Arc , Mutex , MutexGuard } ;
78
@@ -30,7 +31,7 @@ use crate::vmm_config::mmds::{MmdsConfig, MmdsConfigError};
3031use crate :: vmm_config:: net:: * ;
3132use crate :: vmm_config:: vsock:: * ;
3233use crate :: vstate:: memory;
33- use crate :: vstate:: memory:: { GuestRegionMmap , MemoryError } ;
34+ use crate :: vstate:: memory:: { GuestRegionMmap , MemoryError , create_memfd } ;
3435
3536/// Errors encountered when configuring microVM resources.
3637#[ derive( Debug , thiserror:: Error , displaydoc:: Display ) ]
@@ -476,6 +477,12 @@ impl VmResources {
476477 0
477478 }
478479
480+ /// Gets the size of the "traditional" memory region, e.g. total memory excluding the swiotlb
481+ /// region.
482+ pub fn memory_size ( & self ) -> usize {
483+ self . machine_config . mem_size_mib - self . swiotlb_size_mib ( )
484+ }
485+
479486 /// Whether the use of swiotlb was requested
480487 pub fn swiotlb_used ( & self ) -> bool {
481488 self . swiotlb_size_mib ( ) > 0
@@ -486,28 +493,45 @@ impl VmResources {
486493 offset : usize ,
487494 size : usize ,
488495 vhost_accessible : bool ,
496+ file : Option < File > ,
489497 ) -> Result < Vec < GuestRegionMmap > , MemoryError > {
490- let regions = crate :: arch:: arch_memory_regions ( offset, size) ;
491- if vhost_accessible {
492- memory:: memfd_backed (
493- regions. as_ref ( ) ,
494- self . machine_config . track_dirty_pages ,
495- self . machine_config . huge_pages ,
496- )
497- } else {
498- memory:: anonymous (
499- regions. into_iter ( ) ,
498+ let regions = crate :: arch:: arch_memory_regions ( offset, size) . into_iter ( ) ;
499+ match file {
500+ Some ( file) => memory:: file_shared (
501+ file,
502+ regions,
500503 self . machine_config . track_dirty_pages ,
501504 self . machine_config . huge_pages ,
502- )
505+ ) ,
506+ None => {
507+ if vhost_accessible {
508+ let memfd = create_memfd ( size as u64 , self . machine_config . huge_pages . into ( ) ) ?
509+ . into_file ( ) ;
510+ memory:: file_shared (
511+ memfd,
512+ regions,
513+ self . machine_config . track_dirty_pages ,
514+ self . machine_config . huge_pages ,
515+ )
516+ } else {
517+ memory:: anonymous (
518+ regions. into_iter ( ) ,
519+ self . machine_config . track_dirty_pages ,
520+ self . machine_config . huge_pages ,
521+ )
522+ }
523+ }
503524 }
504525 }
505526
506527 /// Allocates guest memory in a configuration most appropriate for these [`VmResources`].
507528 ///
508529 /// If vhost-user-blk devices are in use, allocates memfd-backed shared memory, otherwise
509530 /// prefers anonymous memory for performance reasons.
510- pub fn allocate_guest_memory ( & self ) -> Result < Vec < GuestRegionMmap > , MemoryError > {
531+ pub fn allocate_guest_memory (
532+ & self ,
533+ guest_memfd : Option < File > ,
534+ ) -> Result < Vec < GuestRegionMmap > , MemoryError > {
511535 // Page faults are more expensive for shared memory mapping, including memfd.
512536 // For this reason, we only back guest memory with a memfd
513537 // if a vhost-user-blk device is configured in the VM, otherwise we fall back to
@@ -522,8 +546,9 @@ impl VmResources {
522546 // that would not be worth the effort.
523547 self . allocate_memory (
524548 0 ,
525- mib_to_bytes ( self . machine_config . mem_size_mib - self . swiotlb_size_mib ( ) ) ,
549+ mib_to_bytes ( self . memory_size ( ) ) ,
526550 self . vhost_user_devices_used ( ) && !self . swiotlb_used ( ) ,
551+ guest_memfd,
527552 )
528553 }
529554
@@ -537,7 +562,8 @@ impl VmResources {
537562 let start = mib_to_bytes ( self . machine_config . mem_size_mib ) - swiotlb_size;
538563 let start = start. max ( crate :: arch:: bytes_before_last_gap ( ) ) ;
539564
540- let mut mem = self . allocate_memory ( start, swiotlb_size, self . vhost_user_devices_used ( ) ) ?;
565+ let mut mem =
566+ self . allocate_memory ( start, swiotlb_size, self . vhost_user_devices_used ( ) , None ) ?;
541567
542568 assert_eq ! ( mem. len( ) , 1 ) ;
543569
0 commit comments