@@ -740,67 +740,75 @@ impl PciDevice for VirtioPciDevice {
740740 offset : u8 ,
741741 data : & [ u8 ] ,
742742 ) -> Option < Arc < Barrier > > {
743- if BAR0_REG_IDX <= reg_idx && reg_idx < BAR0_REG_IDX + u16:: from ( NUM_BAR_REGS ) {
743+ let in_bars = BAR0_REG_IDX <= reg_idx && reg_idx < BAR0_REG_IDX + u16:: from ( NUM_BAR_REGS ) ;
744+ let in_msix_config = reg_idx * 4 == self . msix_config_cap_offset ;
745+ let in_pci_cfg = {
746+ let base = reg_idx * 4 ;
747+ let cap_start = self . cap_pci_cfg_info . offset ;
748+ let cap_end =
749+ self . cap_pci_cfg_info . offset as usize + self . cap_pci_cfg_info . cap . bytes ( ) . len ( ) ;
750+ let write_start = base + u16:: from ( offset) ;
751+ let write_end = ( base + u16:: from ( offset) ) as usize + data. len ( ) ;
752+ cap_start <= write_start && write_end <= cap_end
753+ } ;
754+ if in_bars {
744755 // reg_idx is in [BAR0_REG_IDX, BAR0_REG_IDX+NUM_BAR_REGS), so the difference is 0..5.
745756 #[ allow( clippy:: cast_possible_truncation) ]
746757 let bar_idx = ( reg_idx - BAR0_REG_IDX ) as u8 ;
747758 self . bars . write ( bar_idx, offset, data) ;
748759 None
760+ } else if in_msix_config {
761+ self . msix_config
762+ . lock ( )
763+ . unwrap ( )
764+ . write_msg_ctl_register ( offset, data) ;
765+ self . configuration
766+ . write_config_register ( reg_idx, offset, data) ;
767+ None
768+ } else if in_pci_cfg {
769+ let offset = ( reg_idx * 4 + u16:: from ( offset) - self . cap_pci_cfg_info . offset ) as usize ;
770+ self . write_cap_pci_cfg ( offset, data)
749771 } else {
750- // Handle access to the header of the MsixCapability. The rest of the
751- // capability is handled by the PciConfiguration.
752- let base = reg_idx * 4 ;
753- if base == self . msix_config_cap_offset {
754- self . msix_config
755- . lock ( )
756- . unwrap ( )
757- . write_msg_ctl_register ( offset, data) ;
758- }
759- if base + u16:: from ( offset) >= self . cap_pci_cfg_info . offset
760- && ( base + u16:: from ( offset) ) as usize + data. len ( )
761- <= self . cap_pci_cfg_info . offset as usize
762- + self . cap_pci_cfg_info . cap . bytes ( ) . len ( )
763- {
764- let offset = ( base + u16:: from ( offset) - self . cap_pci_cfg_info . offset ) as usize ;
765- self . write_cap_pci_cfg ( offset, data)
766- } else {
767- self . configuration
768- . write_config_register ( reg_idx, offset, data) ;
769- None
770- }
772+ self . configuration
773+ . write_config_register ( reg_idx, offset, data) ;
774+ None
771775 }
772776 }
773777
774778 fn read_config_register ( & mut self , reg_idx : u16 ) -> u32 {
775- if BAR0_REG_IDX <= reg_idx && reg_idx < BAR0_REG_IDX + u16:: from ( NUM_BAR_REGS ) {
779+ let in_bars = BAR0_REG_IDX <= reg_idx && reg_idx < BAR0_REG_IDX + u16:: from ( NUM_BAR_REGS ) ;
780+ let in_pci_cfg = {
781+ let base = reg_idx * 4 ;
782+ let cap_start = self . cap_pci_cfg_info . offset ;
783+ let cap_end =
784+ self . cap_pci_cfg_info . offset as usize + self . cap_pci_cfg_info . cap . bytes ( ) . len ( ) ;
785+ let write_start = base;
786+ let write_end = ( base + 4 ) as usize ;
787+ cap_start <= write_start && write_end <= cap_end
788+ } ;
789+
790+ if in_bars {
776791 // reg_idx is in [BAR0_REG_IDX, BAR0_REG_IDX+NUM_BAR_REGS), so the difference is 0..5.
777792 #[ allow( clippy:: cast_possible_truncation) ]
778793 let bar_idx = ( reg_idx - BAR0_REG_IDX ) as u8 ;
779794 let mut value: u32 = 0 ;
780795 self . bars . read ( bar_idx, 0 , value. as_mut_bytes ( ) ) ;
781796 value
782- } else {
797+ } else if in_pci_cfg {
783798 // Handle the special case where the capability VIRTIO_PCI_CAP_PCI_CFG
784799 // is accessed. This capability has a special meaning as it allows the
785800 // guest to access other capabilities without mapping the PCI BAR.
786- let base = reg_idx as usize * 4 ;
787- if base >= self . cap_pci_cfg_info . offset as usize
788- && base + 4
789- <= self . cap_pci_cfg_info . offset as usize
790- + self . cap_pci_cfg_info . cap . bytes ( ) . len ( )
791- {
792- let offset = base - 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)
798- } else {
799- 0
800- }
801+ let offset = ( reg_idx * 4 - self . cap_pci_cfg_info . offset ) as usize ;
802+ let mut data = [ 0u8 ; 4 ] ;
803+ let len = u32:: from ( self . cap_pci_cfg_info . cap . cap . length ) as usize ;
804+ if len <= 4 {
805+ self . read_cap_pci_cfg ( offset, & mut data[ ..len] ) ;
806+ u32:: from_le_bytes ( data)
801807 } else {
802- self . configuration . read_reg ( reg_idx )
808+ 0
803809 }
810+ } else {
811+ self . configuration . read_reg ( reg_idx)
804812 }
805813 }
806814
0 commit comments