@@ -437,43 +437,92 @@ impl VmResources {
437437 Ok ( ( ) )
438438 }
439439
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
443+ . devices
444+ . iter ( )
445+ . any ( |b| b. lock ( ) . expect ( "Poisoned lock" ) . is_vhost_user ( ) )
446+ }
447+
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 {
473+ memory:: memfd_backed (
474+ regions. as_ref ( ) ,
475+ self . machine_config . track_dirty_pages ,
476+ self . machine_config . huge_pages ,
477+ )
478+ } else {
479+ memory:: anonymous (
480+ regions. into_iter ( ) ,
481+ self . machine_config . track_dirty_pages ,
482+ self . machine_config . huge_pages ,
483+ )
484+ }
485+ }
486+
440487 /// Allocates guest memory in a configuration most appropriate for these [`VmResources`].
441488 ///
442489 /// If vhost-user-blk devices are in use, allocates memfd-backed shared memory, otherwise
443490 /// prefers anonymous memory for performance reasons.
444491 pub fn allocate_guest_memory ( & self ) -> Result < Vec < GuestRegionMmap > , MemoryError > {
445- let vhost_user_device_used = self
446- . block
447- . devices
448- . iter ( )
449- . any ( |b| b. lock ( ) . expect ( "Poisoned lock" ) . is_vhost_user ( ) ) ;
450-
451492 // Page faults are more expensive for shared memory mapping, including memfd.
452493 // For this reason, we only back guest memory with a memfd
453494 // if a vhost-user-blk device is configured in the VM, otherwise we fall back to
454495 // an anonymous private memory.
455496 //
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+ //
456500 // The vhost-user-blk branch is not currently covered by integration tests in Rust,
457501 // because that would require running a backend process. If in the future we converge to
458502 // a single way of backing guest memory for vhost-user and non-vhost-user cases,
459503 // that would not be worth the effort.
460- let regions = crate :: arch :: arch_memory_regions (
504+ self . allocate_memory (
461505 0 ,
462- self . machine_config . mem_size_mib << MIB_TO_BYTES_SHIFT ,
463- ) ;
464- if vhost_user_device_used {
465- memory:: memfd_backed (
466- regions. as_ref ( ) ,
467- self . machine_config . track_dirty_pages ,
468- self . machine_config . huge_pages ,
469- )
470- } else {
471- memory:: anonymous (
472- regions. into_iter ( ) ,
473- self . machine_config . track_dirty_pages ,
474- self . machine_config . huge_pages ,
475- )
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 ) ;
476515 }
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 ) ) )
477526 }
478527}
479528
0 commit comments