pub fn map_mmio_regions<F>(
        &mut self,
        vm: &Arc<dyn hypervisor::Vm>,
        mem_slot: F,
    ) -> Result<(), VfioPciError>
    where
        F: Fn() -> u32,
    {
        let fd = self.device.as_raw_fd();

        for region in self.common.mmio_regions.iter_mut() {
            let region_flags = self.device.get_region_flags(region.index);
            if region_flags & VFIO_REGION_INFO_FLAG_MMAP != 0 {
                let mut prot = 0;
                if region_flags & VFIO_REGION_INFO_FLAG_READ != 0 {
                    prot |= libc::PROT_READ;
                }
                if region_flags & VFIO_REGION_INFO_FLAG_WRITE != 0 {
                    prot |= libc::PROT_WRITE;
                }

                // Retrieve the list of capabilities found on the region
                let caps = if region_flags & VFIO_REGION_INFO_FLAG_CAPS != 0 {
                    self.device.get_region_caps(region.index)
                } else {
                    Vec::new()
                };

                // Don't try to mmap the region if it contains MSI-X table or
                // MSI-X PBA subregion, and if we couldn't find MSIX_MAPPABLE
                // in the list of supported capabilities.
                if let Some(msix) = self.common.interrupt.msix.as_ref() {
                    if (region.index == msix.cap.table_bir() || region.index == msix.cap.pba_bir())
                        && !caps.contains(&VfioRegionInfoCap::MsixMappable)
                    {
                        continue;
                    }
                }

                let mmap_size = self.device.get_region_size(region.index);
                let offset = self.device.get_region_offset(region.index);

                let host_addr = unsafe {
                    libc::mmap(
                        null_mut(),
                        mmap_size as usize,
                        prot,
                        libc::MAP_SHARED,
                        fd,
                        offset as libc::off_t,
                    )
                };

                if host_addr == libc::MAP_FAILED {
                    error!(
                        "Could not mmap region index {}: {}",
                        region.index,
                        io::Error::last_os_error()
                    );
                    continue;
                }

                // In case the region that is being mapped contains the MSI-X
                // vectors table or the MSI-X PBA table, we must adjust what
                // is being declared through the hypervisor. We want to make
                // sure we will still trap MMIO accesses to these MSI-X
                // specific ranges.
                let user_memory_regions = Self::generate_user_memory_regions(
                    region.index,
                    region.start.raw_value(),
                    mmap_size,
                    host_addr as u64,
                    &mem_slot,
                    self.common.interrupt.msix.as_ref(),
                );
                for user_memory_region in user_memory_regions.iter() {
                    let mem_region = vm.make_user_memory_region(
                        user_memory_region.slot,
                        user_memory_region.start,
                        user_memory_region.size,
                        user_memory_region.host_addr,
                        false,
                        false,
                    );

                    vm.create_user_memory_region(mem_region)
                        .map_err(VfioPciError::MapRegionGuest)?;
                }

                // Update the region with memory mapped info.
                region.host_addr = Some(host_addr as u64);
                region.mmap_size = Some(mmap_size as usize);
                region.user_memory_regions = user_memory_regions;
            }
        }

        Ok(())
    }
/// Map MMIO regions into the guest, and avoid VM exits when the guest tries
/// to reach those regions.
///
/// # Arguments
///
/// * `vm` - The VM object. It is used to set the VFIO MMIO regions
///          as user memory regions.
/// * `mem_slot` - The closure to return a memory slot.
Map MMIO regions into the guest, and avoid VM exits when the guest tries
to reach those regions.
Map MMIO regions into the guest and avoid VM exits when the guest tries to reach those regions .
pub fn map_mmio_regions<F>(
        &mut self,
        vm: &Arc<dyn hypervisor::Vm>,
        mem_slot: F,
    ) -> Result<(), VfioPciError>
    where
        F: Fn() -> u32,
    {
        let fd = self.device.as_raw_fd();
        for region in self.common.mmio_regions.iter_mut() {
            let region_flags = self.device.get_region_flags(region.index);
            if region_flags & VFIO_REGION_INFO_FLAG_MMAP != 0 {
                let mut prot = 0;
                if region_flags & VFIO_REGION_INFO_FLAG_READ != 0 {
                    prot |= libc::PROT_READ;
                }
                if region_flags & VFIO_REGION_INFO_FLAG_WRITE != 0 {
                    prot |= libc::PROT_WRITE;
                }
                // Retrieve the list of capabilities found on the region
                let caps = if region_flags & VFIO_REGION_INFO_FLAG_CAPS != 0 {
                    self.device.get_region_caps(region.index)
                } else {
                    Vec::new()
                };
                // Don't try to mmap the region if it contains MSI-X table or
                // MSI-X PBA subregion, and if we couldn't find MSIX_MAPPABLE
                // in the list of supported capabilities.
                if let Some(msix) = self.common.interrupt.msix.as_ref() {
                    if (region.index == msix.cap.table_bir() || region.index == msix.cap.pba_bir())
                        && !caps.contains(&VfioRegionInfoCap::MsixMappable)
                    {
                        continue;
                    }
                }
                let mmap_size = self.device.get_region_size(region.index);
                let offset = self.device.get_region_offset(region.index);
                let host_addr = unsafe {
                    libc::mmap(
                        null_mut(),
                        mmap_size as usize,
                        prot,
                        libc::MAP_SHARED,
                        fd,
                        offset as libc::off_t,
                    )
                };
                if host_addr == libc::MAP_FAILED {
                    error!(
                        "Could not mmap region index {}: {}",
                        region.index,
                        io::Error::last_os_error()
                    );
                    continue;
                }
                // In case the region that is being mapped contains the MSI-X
                // vectors table or the MSI-X PBA table, we must adjust what
                // is being declared through the hypervisor. We want to make
                // sure we will still trap MMIO accesses to these MSI-X
                // specific ranges.
                let user_memory_regions = Self::generate_user_memory_regions(
                    region.index,
                    region.start.raw_value(),
                    mmap_size,
                    host_addr as u64,
                    &mem_slot,
                    self.common.interrupt.msix.as_ref(),
                );
                for user_memory_region in user_memory_regions.iter() {
                    let mem_region = vm.make_user_memory_region(
                        user_memory_region.slot,
                        user_memory_region.start,
                        user_memory_region.size,
                        user_memory_region.host_addr,
                        false,
                        false,
                    );
                    vm.create_user_memory_region(mem_region)
                        .map_err(VfioPciError::MapRegionGuest)?;
                }
                // Update the region with memory mapped info.
                region.host_addr = Some(host_addr as u64);
                region.mmap_size = Some(mmap_size as usize);
                region.user_memory_regions = user_memory_regions;
            }
        }
        Ok(())
    }
pub fn map_mmio_regions < F > ( & mut self , vm : & Arc < dyn hypervisor :: Vm > , mem_slot : F , ) -> Result < ( ) , VfioPciError > where F : Fn ( ) -> u32 , { let fd = self . device . as_raw_fd ( ) ; for region in self . common . mmio_regions . iter_mut ( ) { let region_flags = self . device . get_region_flags ( region . index ) ; if region_flags & VFIO_REGION_INFO_FLAG_MMAP != 0 { let mut prot = 0 ; if region_flags & VFIO_REGION_INFO_FLAG_READ != 0 { prot |= libc :: PROT_READ ; } if region_flags & VFIO_REGION_INFO_FLAG_WRITE != 0 { prot |= libc :: PROT_WRITE ; } // Retrieve the list of capabilities found on the region let caps = if region_flags & VFIO_REGION_INFO_FLAG_CAPS != 0 { self . device . get_region_caps ( region . index ) } else { Vec :: new ( ) } ; // Don't try to mmap the region if it contains MSI-X table or // MSI-X PBA subregion, and if we couldn't find MSIX_MAPPABLE // in the list of supported capabilities. if let Some ( msix ) = self . common . interrupt . msix . as_ref ( ) { if ( region . index == msix . cap . table_bir ( ) || region . index == msix . cap . pba_bir ( ) ) && ! caps . contains ( & VfioRegionInfoCap :: MsixMappable ) { continue ; } } let mmap_size = self . device . get_region_size ( region . index ) ; let offset = self . device . get_region_offset ( region . index ) ; let host_addr = unsafe { libc :: mmap ( null_mut ( ) , mmap_size as usize , prot , libc :: MAP_SHARED , fd , offset as libc :: off_t , ) } ; if host_addr == libc :: MAP_FAILED { error ! ( " " region index io Error last_os_error ( ) ) ; continue ; } // In case the region that is being mapped contains the MSI-X // vectors table or the MSI-X PBA table, we must adjust what // is being declared through the hypervisor. We want to make // sure we will still trap MMIO accesses to these MSI-X // specific ranges. let user_memory_regions = Self :: generate_user_memory_regions ( region . index , region . start . raw_value ( ) , mmap_size , host_addr as u64 , & mem_slot , self . common . interrupt . msix . as_ref ( ) , ) ; for user_memory_region in user_memory_regions . iter ( ) { let mem_region = vm . make_user_memory_region ( user_memory_region . slot , user_memory_region . start , user_memory_region . size , user_memory_region . host_addr , false , false , ) ; vm . create_user_memory_region ( mem_region ) . map_err ( VfioPciError :: MapRegionGuest ) ? ; } // Update the region with memory mapped info. region . host_addr = Some ( host_addr as u64 ) ; region . mmap_size = Some ( mmap_size as usize ) ; region . user_memory_regions = user_memory_regions ; } } Ok ( ( ) ) }
Map MMIO regions into the guest, and avoid VM exits when the guest tries
to reach those regions.
Map MMIO regions into the guest and avoid VM exits when the guest tries to reach those regions .
&mut self
vm
&Arc<dyn hypervisor::Vm>
mem_slot
F
&mut self
vm
&Arc<dyn hypervisor::Vm>
mem_slot
F