@@ -736,67 +736,75 @@ impl PciDevice for VirtioPciDevice {
736736 offset : u8 ,
737737 data : & [ u8 ] ,
738738 ) -> Option < Arc < Barrier > > {
739- if BAR0_REG_IDX <= reg_idx && reg_idx < BAR0_REG_IDX + u16:: from ( NUM_BAR_REGS ) {
739+ let in_bars = BAR0_REG_IDX <= reg_idx && reg_idx < BAR0_REG_IDX + u16:: from ( NUM_BAR_REGS ) ;
740+ let in_msix_config = reg_idx * 4 == self . msix_config_cap_offset ;
741+ let in_pci_cfg = {
742+ let base = reg_idx * 4 ;
743+ let cap_start = self . cap_pci_cfg_info . offset ;
744+ let cap_end =
745+ self . cap_pci_cfg_info . offset as usize + self . cap_pci_cfg_info . cap . bytes ( ) . len ( ) ;
746+ let write_start = base + u16:: from ( offset) ;
747+ let write_end = ( base + u16:: from ( offset) ) as usize + data. len ( ) ;
748+ cap_start <= write_start && write_end <= cap_end
749+ } ;
750+ if in_bars {
740751 // reg_idx is in [BAR0_REG_IDX, BAR0_REG_IDX+NUM_BAR_REGS), so the difference is 0..5.
741752 #[ allow( clippy:: cast_possible_truncation) ]
742753 let bar_idx = ( reg_idx - BAR0_REG_IDX ) as u8 ;
743754 self . bars . write ( bar_idx, offset, data) ;
744755 None
756+ } else if in_msix_config {
757+ self . msix_config
758+ . lock ( )
759+ . unwrap ( )
760+ . write_msg_ctl_register ( offset, data) ;
761+ self . configuration
762+ . write_config_register ( reg_idx, offset, data) ;
763+ None
764+ } else if in_pci_cfg {
765+ let offset = ( reg_idx * 4 + u16:: from ( offset) - self . cap_pci_cfg_info . offset ) as usize ;
766+ self . write_cap_pci_cfg ( offset, data)
745767 } else {
746- // Handle access to the header of the MsixCapability. The rest of the
747- // capability is handled by the PciConfiguration.
748- let base = reg_idx * 4 ;
749- if base == self . msix_config_cap_offset {
750- self . msix_config
751- . lock ( )
752- . unwrap ( )
753- . write_msg_ctl_register ( offset, data) ;
754- }
755- if base + u16:: from ( offset) >= self . cap_pci_cfg_info . offset
756- && ( base + u16:: from ( offset) ) as usize + data. len ( )
757- <= self . cap_pci_cfg_info . offset as usize
758- + self . cap_pci_cfg_info . cap . bytes ( ) . len ( )
759- {
760- let offset = ( base + u16:: from ( offset) - self . cap_pci_cfg_info . offset ) as usize ;
761- self . write_cap_pci_cfg ( offset, data)
762- } else {
763- self . configuration
764- . write_config_register ( reg_idx, offset, data) ;
765- None
766- }
768+ self . configuration
769+ . write_config_register ( reg_idx, offset, data) ;
770+ None
767771 }
768772 }
769773
770774 fn read_config_register ( & mut self , reg_idx : u16 ) -> u32 {
771- if BAR0_REG_IDX <= reg_idx && reg_idx < BAR0_REG_IDX + u16:: from ( NUM_BAR_REGS ) {
775+ let in_bars = BAR0_REG_IDX <= reg_idx && reg_idx < BAR0_REG_IDX + u16:: from ( NUM_BAR_REGS ) ;
776+ let in_pci_cfg = {
777+ let base = reg_idx * 4 ;
778+ let cap_start = self . cap_pci_cfg_info . offset ;
779+ let cap_end =
780+ self . cap_pci_cfg_info . offset as usize + self . cap_pci_cfg_info . cap . bytes ( ) . len ( ) ;
781+ let write_start = base;
782+ let write_end = ( base + 4 ) as usize ;
783+ cap_start <= write_start && write_end <= cap_end
784+ } ;
785+
786+ if in_bars {
772787 // reg_idx is in [BAR0_REG_IDX, BAR0_REG_IDX+NUM_BAR_REGS), so the difference is 0..5.
773788 #[ allow( clippy:: cast_possible_truncation) ]
774789 let bar_idx = ( reg_idx - BAR0_REG_IDX ) as u8 ;
775790 let mut value: u32 = 0 ;
776791 self . bars . read ( bar_idx, 0 , value. as_mut_bytes ( ) ) ;
777792 value
778- } else {
793+ } else if in_pci_cfg {
779794 // Handle the special case where the capability VIRTIO_PCI_CAP_PCI_CFG
780795 // is accessed. This capability has a special meaning as it allows the
781796 // guest to access other capabilities without mapping the PCI BAR.
782- let base = reg_idx as usize * 4 ;
783- if base >= self . cap_pci_cfg_info . offset as usize
784- && base + 4
785- <= self . cap_pci_cfg_info . offset as usize
786- + self . cap_pci_cfg_info . cap . bytes ( ) . len ( )
787- {
788- let offset = base - self . cap_pci_cfg_info . offset as usize ;
789- let mut data = [ 0u8 ; 4 ] ;
790- let len = u32:: from ( self . cap_pci_cfg_info . cap . cap . length ) as usize ;
791- if len <= 4 {
792- self . read_cap_pci_cfg ( offset, & mut data[ ..len] ) ;
793- u32:: from_le_bytes ( data)
794- } else {
795- 0
796- }
797+ let offset = ( reg_idx * 4 - self . cap_pci_cfg_info . offset ) as usize ;
798+ let mut data = [ 0u8 ; 4 ] ;
799+ let len = u32:: from ( self . cap_pci_cfg_info . cap . cap . length ) as usize ;
800+ if len <= 4 {
801+ self . read_cap_pci_cfg ( offset, & mut data[ ..len] ) ;
802+ u32:: from_le_bytes ( data)
797803 } else {
798- self . configuration . read_reg ( reg_idx )
804+ 0
799805 }
806+ } else {
807+ self . configuration . read_reg ( reg_idx)
800808 }
801809 }
802810
0 commit comments