@@ -437,28 +437,39 @@ impl VmResources {
437437 Ok ( ( ) )
438438 }
439439
440- /// Allocates guest memory in a configuration most appropriate for these [`VmResources`].
441- ///
442- /// If vhost-user-blk devices are in use, allocates memfd-backed shared memory, otherwise
443- /// prefers anonymous memory for performance reasons.
444- pub fn allocate_guest_memory ( & self ) -> Result < Vec < GuestRegionMmap > , MemoryError > {
445- let vhost_user_device_used = self
446- . block
440+ /// Returns true if any vhost user devices are configured int his [`VmResources`] object
441+ pub fn vhost_user_devices_used ( & self ) -> bool {
442+ self . block
447443 . devices
448444 . iter ( )
449- . any ( |b| b. lock ( ) . expect ( "Poisoned lock" ) . is_vhost_user ( ) ) ;
445+ . any ( |b| b. lock ( ) . expect ( "Poisoned lock" ) . is_vhost_user ( ) )
446+ }
450447
451- // Page faults are more expensive for shared memory mapping, including memfd.
452- // For this reason, we only back guest memory with a memfd
453- // if a vhost-user-blk device is configured in the VM, otherwise we fall back to
454- // an anonymous private memory.
455- //
456- // The vhost-user-blk branch is not currently covered by integration tests in Rust,
457- // because that would require running a backend process. If in the future we converge to
458- // a single way of backing guest memory for vhost-user and non-vhost-user cases,
459- // that would not be worth the effort.
460- let regions = crate :: arch:: arch_memory_regions ( 0 , self . machine_config . mem_size_mib << MIB_TO_BYTES_SHIFT ) ;
461- if vhost_user_device_used {
448+ /// The size of the swiotlb region requested, in MiB
449+ #[ cfg( target_arch = "aarch64" ) ]
450+ pub fn swiotlb_size_mib ( & self ) -> usize {
451+ self . machine_config . mem_config . initial_swiotlb_size
452+ }
453+
454+ /// The size of the swiotlb region requested, in MiB
455+ #[ cfg( target_arch = "x86_64" ) ]
456+ pub fn swiotlb_size_mib ( & self ) -> usize {
457+ 0
458+ }
459+
460+ /// Whether the use of swiotlb was requested
461+ pub fn swiotlb_used ( & self ) -> bool {
462+ self . swiotlb_size_mib ( ) > 0
463+ }
464+
465+ fn allocate_memory (
466+ & self ,
467+ offset : usize ,
468+ size : usize ,
469+ vhost_accessible : bool ,
470+ ) -> Result < Vec < GuestRegionMmap > , MemoryError > {
471+ let regions = crate :: arch:: arch_memory_regions ( offset, size) ;
472+ if vhost_accessible {
462473 memory:: memfd_backed (
463474 regions. as_ref ( ) ,
464475 self . machine_config . track_dirty_pages ,
@@ -472,6 +483,47 @@ impl VmResources {
472483 )
473484 }
474485 }
486+
487+ /// Allocates guest memory in a configuration most appropriate for these [`VmResources`].
488+ ///
489+ /// If vhost-user-blk devices are in use, allocates memfd-backed shared memory, otherwise
490+ /// prefers anonymous memory for performance reasons.
491+ pub fn allocate_guest_memory ( & self ) -> Result < Vec < GuestRegionMmap > , MemoryError > {
492+ // Page faults are more expensive for shared memory mapping, including memfd.
493+ // For this reason, we only back guest memory with a memfd
494+ // if a vhost-user-blk device is configured in the VM, otherwise we fall back to
495+ // an anonymous private memory.
496+ //
497+ // Note that if a swiotlb region is used, no I/O will go through the "regular"
498+ // memory regions, and we can back them with anon memory regardless.
499+ //
500+ // The vhost-user-blk branch is not currently covered by integration tests in Rust,
501+ // because that would require running a backend process. If in the future we converge to
502+ // a single way of backing guest memory for vhost-user and non-vhost-user cases,
503+ // that would not be worth the effort.
504+ self . allocate_memory (
505+ 0 ,
506+ ( self . machine_config . mem_size_mib - self . swiotlb_size_mib ( ) ) << MIB_TO_BYTES_SHIFT ,
507+ self . vhost_user_devices_used ( ) && !self . swiotlb_used ( ) ,
508+ )
509+ }
510+
511+ /// Allocates the dedicated I/O region for swiotlb use, if one was requested.
512+ pub fn allocate_io_memory ( & self ) -> Result < Option < GuestRegionMmap > , MemoryError > {
513+ if !self . swiotlb_used ( ) {
514+ return Ok ( None ) ;
515+ }
516+
517+ let swiotlb_size = self . swiotlb_size_mib ( ) << MIB_TO_BYTES_SHIFT ;
518+ let start = ( self . machine_config . mem_size_mib << MIB_TO_BYTES_SHIFT ) - swiotlb_size;
519+ let start = start. max ( crate :: arch:: bytes_before_last_gap ( ) ) ;
520+
521+ let mut mem = self . allocate_memory ( start, swiotlb_size, self . vhost_user_devices_used ( ) ) ?;
522+
523+ assert_eq ! ( mem. len( ) , 1 ) ;
524+
525+ Ok ( Some ( mem. remove ( 0 ) ) )
526+ }
475527}
476528
477529impl From < & VmResources > for VmmConfig {
0 commit comments