fn write_config(&mut self, offset: usize, data: &[u8]) {
        let size = data.len();
        let end = offset + size;
        if end > (self.config_size as usize) || size > 4 {
            error!(
                "Failed to write pci config space at offset {} with data size {}",
                offset, size
            );
            return;
        }

        // Let vfio device filter data to write.
        if let Err(e) = self
            .vfio_device
            .write_region(data, self.config_offset, offset as u64)
        {
            error!("Failed to write device pci config, error is {}", e);
            return;
        }

        let mut cap_offset = 0;
        if let Some(msix) = &self.pci_config.msix {
            cap_offset = msix.lock().unwrap().msix_cap_offset as usize;
        }

        if ranges_overlap(offset, end, COMMAND as usize, COMMAND as usize + REG_SIZE) {
            self.pci_config
                .write(offset, data, self.dev_id.load(Ordering::Acquire));

            if le_read_u32(&self.pci_config.config, offset).unwrap() & COMMAND_MEMORY_SPACE as u32
                != 0
            {
                let parent_bus = self.parent_bus.upgrade().unwrap();
                let locked_parent_bus = parent_bus.lock().unwrap();
                if let Err(e) = self.pci_config.update_bar_mapping(
                    #[cfg(target_arch = "x86_64")]
                    &locked_parent_bus.io_region,
                    &locked_parent_bus.mem_region,
                ) {
                    error!("Failed to update bar, error is {}", e.display_chain());
                    return;
                }
                drop(locked_parent_bus);

                if let Err(e) = self.setup_bars_mmap() {
                    error!("Failed to map bar regions, error is {}", e.display_chain());
                    return;
                }
            }
        } else if ranges_overlap(offset, end, BAR_0 as usize, (BAR_5 as usize) + REG_SIZE) {
            self.pci_config
                .write(offset, data, self.dev_id.load(Ordering::Acquire));

            if size == 4 && LittleEndian::read_u32(data) != 0xffff_ffff {
                let parent_bus = self.parent_bus.upgrade().unwrap();
                let locked_parent_bus = parent_bus.lock().unwrap();
                if let Err(e) = self.pci_config.update_bar_mapping(
                    #[cfg(target_arch = "x86_64")]
                    &locked_parent_bus.io_region,
                    &locked_parent_bus.mem_region,
                ) {
                    error!("Failed to update bar, error is {}", e.display_chain());
                    return;
                }
            }
        } else if ranges_overlap(offset, end, cap_offset, cap_offset + MSIX_CAP_SIZE as usize) {
            let was_enable = is_msix_enabled(cap_offset, &self.pci_config.config);
            self.pci_config
                .write(offset, data, self.dev_id.load(Ordering::Acquire));
            let is_enable = is_msix_enabled(cap_offset, &self.pci_config.config);

            if !was_enable && is_enable {
                if let Err(e) = self.vfio_enable_msix() {
                    error!("Failed to enable MSI-X, error is {}", e.display_chain());
                    return;
                }
            } else if was_enable && !is_enable {
                if let Err(e) = self.vfio_disable_msix() {
                    error!("Failed to disable MSI-X, error is {}", e.display_chain());
                    return;
                }
            }
        } else {
            self.pci_config
                .write(offset, data, self.dev_id.load(Ordering::Acquire));
        }
    }
/// Write data to pci config and vfio device at the same time
Write data to pci config and vfio device at the same time
Write data to pci config and vfio device at the same time
fn write_config(&mut self, offset: usize, data: &[u8]) {
        let size = data.len();
        let end = offset + size;
        if end > (self.config_size as usize) || size > 4 {
            error!(
                "Failed to write pci config space at offset {} with data size {}",
                offset, size
            );
            return;
        }
        // Let vfio device filter data to write.
        if let Err(e) = self
            .vfio_device
            .write_region(data, self.config_offset, offset as u64)
        {
            error!("Failed to write device pci config, error is {}", e);
            return;
        }
        let mut cap_offset = 0;
        if let Some(msix) = &self.pci_config.msix {
            cap_offset = msix.lock().unwrap().msix_cap_offset as usize;
        }
        if ranges_overlap(offset, end, COMMAND as usize, COMMAND as usize + REG_SIZE) {
            self.pci_config
                .write(offset, data, self.dev_id.load(Ordering::Acquire));
            if le_read_u32(&self.pci_config.config, offset).unwrap() & COMMAND_MEMORY_SPACE as u32
                != 0
            {
                let parent_bus = self.parent_bus.upgrade().unwrap();
                let locked_parent_bus = parent_bus.lock().unwrap();
                if let Err(e) = self.pci_config.update_bar_mapping(
                    #[cfg(target_arch = "x86_64")]
                    &locked_parent_bus.io_region,
                    &locked_parent_bus.mem_region,
                ) {
                    error!("Failed to update bar, error is {}", e.display_chain());
                    return;
                }
                drop(locked_parent_bus);
                if let Err(e) = self.setup_bars_mmap() {
                    error!("Failed to map bar regions, error is {}", e.display_chain());
                    return;
                }
            }
        } else if ranges_overlap(offset, end, BAR_0 as usize, (BAR_5 as usize) + REG_SIZE) {
            self.pci_config
                .write(offset, data, self.dev_id.load(Ordering::Acquire));
            if size == 4 && LittleEndian::read_u32(data) != 0xffff_ffff {
                let parent_bus = self.parent_bus.upgrade().unwrap();
                let locked_parent_bus = parent_bus.lock().unwrap();
                if let Err(e) = self.pci_config.update_bar_mapping(
                    #[cfg(target_arch = "x86_64")]
                    &locked_parent_bus.io_region,
                    &locked_parent_bus.mem_region,
                ) {
                    error!("Failed to update bar, error is {}", e.display_chain());
                    return;
                }
            }
        } else if ranges_overlap(offset, end, cap_offset, cap_offset + MSIX_CAP_SIZE as usize) {
            let was_enable = is_msix_enabled(cap_offset, &self.pci_config.config);
            self.pci_config
                .write(offset, data, self.dev_id.load(Ordering::Acquire));
            let is_enable = is_msix_enabled(cap_offset, &self.pci_config.config);
            if !was_enable && is_enable {
                if let Err(e) = self.vfio_enable_msix() {
                    error!("Failed to enable MSI-X, error is {}", e.display_chain());
                    return;
                }
            } else if was_enable && !is_enable {
                if let Err(e) = self.vfio_disable_msix() {
                    error!("Failed to disable MSI-X, error is {}", e.display_chain());
                    return;
                }
            }
        } else {
            self.pci_config
                .write(offset, data, self.dev_id.load(Ordering::Acquire));
        }
    }
fn write_config ( & mut self , offset : usize , data : & [ u8 ] ) { let size = data . len ( ) ; let end = offset + size ; if end > ( self . config_size as usize ) || size > 4 { error ! ( " " offset size ) ; return ; } // Let vfio device filter data to write. if let Err ( e ) = self . vfio_device . write_region ( data , self . config_offset , offset as u64 ) { error ! ( " " e ) ; return ; } let mut cap_offset = 0 ; if let Some ( msix ) = & self . pci_config . msix { cap_offset = msix . lock ( ) . unwrap ( ) . msix_cap_offset as usize ; } if ranges_overlap ( offset , end , COMMAND as usize , COMMAND as usize + REG_SIZE ) { self . pci_config . write ( offset , data , self . dev_id . load ( Ordering :: Acquire ) ) ; if le_read_u32 ( & self . pci_config . config , offset ) . unwrap ( ) & COMMAND_MEMORY_SPACE as u32 != 0 { let parent_bus = self . parent_bus . upgrade ( ) . unwrap ( ) ; let locked_parent_bus = parent_bus . lock ( ) . unwrap ( ) ; if let Err ( e ) = self . pci_config . update_bar_mapping ( # [ cfg ( target_arch " " ) ] & locked_parent_bus . io_region , & locked_parent_bus . mem_region , ) { error ! ( " " e display_chain ( ) ) ; return ; } drop ( locked_parent_bus ) ; if let Err ( e ) = self . setup_bars_mmap ( ) { error ! ( " " e display_chain ( ) ) ; return ; } } } else if ranges_overlap ( offset , end , BAR_0 as usize , ( BAR_5 as usize ) + REG_SIZE ) { self . pci_config . write ( offset , data , self . dev_id . load ( Ordering :: Acquire ) ) ; if size == 4 && LittleEndian :: read_u32 ( data ) != 0xffff_ffff { let parent_bus = self . parent_bus . upgrade ( ) . unwrap ( ) ; let locked_parent_bus = parent_bus . lock ( ) . unwrap ( ) ; if let Err ( e ) = self . pci_config . update_bar_mapping ( # [ cfg ( target_arch " " ) ] & locked_parent_bus . io_region , & locked_parent_bus . mem_region , ) { error ! ( " " e display_chain ( ) ) ; return ; } } } else if ranges_overlap ( offset , end , cap_offset , cap_offset + MSIX_CAP_SIZE as usize ) { let was_enable = is_msix_enabled ( cap_offset , & self . pci_config . config ) ; self . pci_config . write ( offset , data , self . dev_id . load ( Ordering :: Acquire ) ) ; let is_enable = is_msix_enabled ( cap_offset , & self . pci_config . config ) ; if ! was_enable && is_enable { if let Err ( e ) = self . vfio_enable_msix ( ) { error ! ( " " e display_chain ( ) ) ; return ; } } else if was_enable && ! is_enable { if let Err ( e ) = self . vfio_disable_msix ( ) { error ! ( " " e display_chain ( ) ) ; return ; } } } else { self . pci_config . write ( offset , data , self . dev_id . load ( Ordering :: Acquire ) ) ; } }
Write data to pci config and vfio device at the same time
Write data to pci config and vfio device at the same time
&mut self
offset
usize
data
&[u8]
&mut self
offset
usize
data
&[u8]