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

        for region in self.mmio_regions.iter_mut() {
            // We want to skip the mapping of the BAR containing the MSI-X
            // table even if it is mappable. The reason is we need to trap
            // any access to the MSI-X table and update the GSI routing
            // accordingly.
            if let Some(msix) = &self.interrupt.msix {
                if region.index == msix.cap.table_bir() || region.index == msix.cap.pba_bir() {
                    continue;
                }
            }

            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;
                }
                let (mmap_offset, mmap_size) = self.device.get_region_mmap(region.index);
                let offset = self.device.get_region_offset(region.index) + mmap_offset;

                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 regions, error:{}",
                        io::Error::last_os_error()
                    );
                    continue;
                }

                let slot = mem_slot();
                let mem_region = vm.make_user_memory_region(
                    slot,
                    region.start.raw_value() + mmap_offset,
                    mmap_size as u64,
                    host_addr as u64,
                    false,
                    false,
                );

                vm.set_user_memory_region(mem_region)
                    .map_err(|e| VfioPciError::MapRegionGuest(e.into()))?;

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

        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<()>
    where
        F: Fn() -> u32,
    {
        let fd = self.device.as_raw_fd();
        for region in self.mmio_regions.iter_mut() {
            // We want to skip the mapping of the BAR containing the MSI-X
            // table even if it is mappable. The reason is we need to trap
            // any access to the MSI-X table and update the GSI routing
            // accordingly.
            if let Some(msix) = &self.interrupt.msix {
                if region.index == msix.cap.table_bir() || region.index == msix.cap.pba_bir() {
                    continue;
                }
            }
            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;
                }
                let (mmap_offset, mmap_size) = self.device.get_region_mmap(region.index);
                let offset = self.device.get_region_offset(region.index) + mmap_offset;
                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 regions, error:{}",
                        io::Error::last_os_error()
                    );
                    continue;
                }
                let slot = mem_slot();
                let mem_region = vm.make_user_memory_region(
                    slot,
                    region.start.raw_value() + mmap_offset,
                    mmap_size as u64,
                    host_addr as u64,
                    false,
                    false,
                );
                vm.set_user_memory_region(mem_region)
                    .map_err(|e| VfioPciError::MapRegionGuest(e.into()))?;
                // Update the region with memory mapped info.
                region.mem_slot = Some(slot);
                region.host_addr = Some(host_addr as u64);
                region.mmap_size = Some(mmap_size as usize);
            }
        }
        Ok(())
    }
pub fn map_mmio_regions < F > ( & mut self , vm : & Arc < dyn hypervisor :: Vm > , mem_slot : F ) -> Result < ( ) > where F : Fn ( ) -> u32 , { let fd = self . device . as_raw_fd ( ) ; for region in self . mmio_regions . iter_mut ( ) { // We want to skip the mapping of the BAR containing the MSI-X // table even if it is mappable. The reason is we need to trap // any access to the MSI-X table and update the GSI routing // accordingly. if let Some ( msix ) = & self . interrupt . msix { if region . index == msix . cap . table_bir ( ) || region . index == msix . cap . pba_bir ( ) { continue ; } } 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 ; } let ( mmap_offset , mmap_size ) = self . device . get_region_mmap ( region . index ) ; let offset = self . device . get_region_offset ( region . index ) + mmap_offset ; 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 ! ( " " io Error last_os_error ( ) ) ; continue ; } let slot = mem_slot ( ) ; let mem_region = vm . make_user_memory_region ( slot , region . start . raw_value ( ) + mmap_offset , mmap_size as u64 , host_addr as u64 , false , false , ) ; vm . set_user_memory_region ( mem_region ) . map_err ( | e | VfioPciError :: MapRegionGuest ( e . into ( ) ) ) ? ; // Update the region with memory mapped info. region . mem_slot = Some ( slot ) ; region . host_addr = Some ( host_addr as u64 ) ; region . mmap_size = Some ( mmap_size as usize ) ; } } 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