@@ -731,67 +731,75 @@ impl PciDevice for VirtioPciDevice {
731731 offset : u8 ,
732732 data : & [ u8 ] ,
733733 ) -> Option < Arc < Barrier > > {
734- if BAR0_REG_IDX <= reg_idx && reg_idx < BAR0_REG_IDX + u16:: from ( NUM_BAR_REGS ) {
734+ let in_bars = BAR0_REG_IDX <= reg_idx && reg_idx < BAR0_REG_IDX + u16:: from ( NUM_BAR_REGS ) ;
735+ let in_msix_config = reg_idx * 4 == self . msix_config_cap_offset ;
736+ let in_pci_cfg = {
737+ let base = reg_idx * 4 ;
738+ let cap_start = self . cap_pci_cfg_info . offset ;
739+ let cap_end =
740+ self . cap_pci_cfg_info . offset as usize + self . cap_pci_cfg_info . cap . bytes ( ) . len ( ) ;
741+ let write_start = base + u16:: from ( offset) ;
742+ let write_end = ( base + u16:: from ( offset) ) as usize + data. len ( ) ;
743+ cap_start <= write_start && write_end <= cap_end
744+ } ;
745+ if in_bars {
735746 // reg_idx is in [BAR0_REG_IDX, BAR0_REG_IDX+NUM_BAR_REGS), so the difference is 0..5.
736747 #[ allow( clippy:: cast_possible_truncation) ]
737748 let bar_idx = ( reg_idx - BAR0_REG_IDX ) as u8 ;
738749 self . bars . write ( bar_idx, offset, data) ;
739750 None
751+ } else if in_msix_config {
752+ self . msix_config
753+ . lock ( )
754+ . unwrap ( )
755+ . write_msg_ctl_register ( offset, data) ;
756+ self . configuration
757+ . write_config_register ( reg_idx, offset, data) ;
758+ None
759+ } else if in_pci_cfg {
760+ let offset = ( reg_idx * 4 + u16:: from ( offset) - self . cap_pci_cfg_info . offset ) as usize ;
761+ self . write_cap_pci_cfg ( offset, data)
740762 } else {
741- // Handle access to the header of the MsixCapability. The rest of the
742- // capability is handled by the PciConfiguration.
743- let base = reg_idx * 4 ;
744- if base == self . msix_config_cap_offset {
745- self . msix_config
746- . lock ( )
747- . unwrap ( )
748- . write_msg_ctl_register ( offset, data) ;
749- }
750- if base + u16:: from ( offset) >= self . cap_pci_cfg_info . offset
751- && ( base + u16:: from ( offset) ) as usize + data. len ( )
752- <= self . cap_pci_cfg_info . offset as usize
753- + self . cap_pci_cfg_info . cap . bytes ( ) . len ( )
754- {
755- let offset = ( base + u16:: from ( offset) - self . cap_pci_cfg_info . offset ) as usize ;
756- self . write_cap_pci_cfg ( offset, data)
757- } else {
758- self . configuration
759- . write_config_register ( reg_idx, offset, data) ;
760- None
761- }
763+ self . configuration
764+ . write_config_register ( reg_idx, offset, data) ;
765+ None
762766 }
763767 }
764768
765769 fn read_config_register ( & mut self , reg_idx : u16 ) -> u32 {
766- if BAR0_REG_IDX <= reg_idx && reg_idx < BAR0_REG_IDX + u16:: from ( NUM_BAR_REGS ) {
770+ let in_bars = BAR0_REG_IDX <= reg_idx && reg_idx < BAR0_REG_IDX + u16:: from ( NUM_BAR_REGS ) ;
771+ let in_pci_cfg = {
772+ let base = reg_idx * 4 ;
773+ let cap_start = self . cap_pci_cfg_info . offset ;
774+ let cap_end =
775+ self . cap_pci_cfg_info . offset as usize + self . cap_pci_cfg_info . cap . bytes ( ) . len ( ) ;
776+ let write_start = base;
777+ let write_end = ( base + 4 ) as usize ;
778+ cap_start <= write_start && write_end <= cap_end
779+ } ;
780+
781+ if in_bars {
767782 // reg_idx is in [BAR0_REG_IDX, BAR0_REG_IDX+NUM_BAR_REGS), so the difference is 0..5.
768783 #[ allow( clippy:: cast_possible_truncation) ]
769784 let bar_idx = ( reg_idx - BAR0_REG_IDX ) as u8 ;
770785 let mut value: u32 = 0 ;
771786 self . bars . read ( bar_idx, 0 , value. as_mut_bytes ( ) ) ;
772787 value
773- } else {
788+ } else if in_pci_cfg {
774789 // Handle the special case where the capability VIRTIO_PCI_CAP_PCI_CFG
775790 // is accessed. This capability has a special meaning as it allows the
776791 // guest to access other capabilities without mapping the PCI BAR.
777- let base = reg_idx as usize * 4 ;
778- if base >= self . cap_pci_cfg_info . offset as usize
779- && base + 4
780- <= self . cap_pci_cfg_info . offset as usize
781- + self . cap_pci_cfg_info . cap . bytes ( ) . len ( )
782- {
783- let offset = base - self . cap_pci_cfg_info . offset as usize ;
784- let mut data = [ 0u8 ; 4 ] ;
785- let len = u32:: from ( self . cap_pci_cfg_info . cap . cap . length ) as usize ;
786- if len <= 4 {
787- self . read_cap_pci_cfg ( offset, & mut data[ ..len] ) ;
788- u32:: from_le_bytes ( data)
789- } else {
790- 0
791- }
792+ let offset = ( reg_idx * 4 - self . cap_pci_cfg_info . offset ) as usize ;
793+ let mut data = [ 0u8 ; 4 ] ;
794+ let len = u32:: from ( self . cap_pci_cfg_info . cap . cap . length ) as usize ;
795+ if len <= 4 {
796+ self . read_cap_pci_cfg ( offset, & mut data[ ..len] ) ;
797+ u32:: from_le_bytes ( data)
792798 } else {
793- self . configuration . read_reg ( reg_idx )
799+ 0
794800 }
801+ } else {
802+ self . configuration . read_reg ( reg_idx)
795803 }
796804 }
797805
0 commit comments