Skip to content

Commit 6460b81

Browse files
committed
pci: refactor: make read/write_config_register a bit easier to read
Move the comparisons into boolean vars to make dispatch code a bit more readable. Signed-off-by: Egor Lazarchuk <yegorlz@amazon.co.uk>
1 parent 7bb0fa9 commit 6460b81

1 file changed

Lines changed: 46 additions & 40 deletions

File tree

  • src/vmm/src/devices/virtio/transport/pci

src/vmm/src/devices/virtio/transport/pci/device.rs

Lines changed: 46 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,17 @@ struct VirtioPciCfgCapInfo {
189189
cap: VirtioPciCfgCap,
190190
}
191191

192+
impl VirtioPciCfgCapInfo {
193+
fn in_range(&self, reg_idx: u16, offset: u8, data_len: usize) -> bool {
194+
let base = reg_idx * 4;
195+
let cap_start = self.offset;
196+
let cap_end = self.offset as usize + self.cap.bytes().len();
197+
let start = base + u16::from(offset);
198+
let end = (base + u16::from(offset)) as usize + data_len;
199+
cap_start <= start && end <= cap_end
200+
}
201+
}
202+
192203
#[derive(Debug, Copy, Clone)]
193204
#[repr(u8)]
194205
pub enum PciVirtioSubclass {
@@ -736,67 +747,62 @@ impl PciDevice for VirtioPciDevice {
736747
offset: u8,
737748
data: &[u8],
738749
) -> Option<Arc<Barrier>> {
739-
if BAR0_REG_IDX <= reg_idx && reg_idx < BAR0_REG_IDX + u16::from(NUM_BAR_REGS) {
750+
let in_bars = BAR0_REG_IDX <= reg_idx && reg_idx < BAR0_REG_IDX + u16::from(NUM_BAR_REGS);
751+
let in_msix_cap_header = reg_idx * 4 == self.msix_config_cap_offset;
752+
let in_pci_cfg = self.cap_pci_cfg_info.in_range(reg_idx, offset, data.len());
753+
if in_bars {
740754
// reg_idx is in [BAR0_REG_IDX, BAR0_REG_IDX+NUM_BAR_REGS), so the difference is 0..5.
741755
#[allow(clippy::cast_possible_truncation)]
742756
let bar_idx = (reg_idx - BAR0_REG_IDX) as u8;
743757
self.bars.write(bar_idx, offset, data);
744758
None
759+
} else if in_msix_cap_header {
760+
// For writes to MsixCap structure, we need to capture write to the second 2 bytes
761+
// of the capability header where the Function Mask and MSI-X Enable bits are present.
762+
// Everything else can be served from `self.configuration`.
763+
self.msix_config
764+
.lock()
765+
.unwrap()
766+
.write_msg_ctl_register(offset, data);
767+
self.configuration
768+
.write_config_register(reg_idx, offset, data);
769+
None
770+
} else if in_pci_cfg {
771+
let offset = (reg_idx * 4 + u16::from(offset) - self.cap_pci_cfg_info.offset) as usize;
772+
self.write_cap_pci_cfg(offset, data)
745773
} 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-
}
774+
self.configuration
775+
.write_config_register(reg_idx, offset, data);
776+
None
767777
}
768778
}
769779

770780
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) {
781+
let in_bars = BAR0_REG_IDX <= reg_idx && reg_idx < BAR0_REG_IDX + u16::from(NUM_BAR_REGS);
782+
let in_pci_cfg = self.cap_pci_cfg_info.in_range(reg_idx, 0, 4);
783+
784+
if in_bars {
772785
// reg_idx is in [BAR0_REG_IDX, BAR0_REG_IDX+NUM_BAR_REGS), so the difference is 0..5.
773786
#[allow(clippy::cast_possible_truncation)]
774787
let bar_idx = (reg_idx - BAR0_REG_IDX) as u8;
775788
let mut value: u32 = 0;
776789
self.bars.read(bar_idx, 0, value.as_mut_bytes());
777790
value
778-
} else {
791+
} else if in_pci_cfg {
779792
// Handle the special case where the capability VIRTIO_PCI_CAP_PCI_CFG
780793
// is accessed. This capability has a special meaning as it allows the
781794
// 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-
}
795+
let offset = (reg_idx * 4 - self.cap_pci_cfg_info.offset) as usize;
796+
let mut data = [0u8; 4];
797+
let len = u32::from(self.cap_pci_cfg_info.cap.cap.length) as usize;
798+
if len <= 4 {
799+
self.read_cap_pci_cfg(offset, &mut data[..len]);
800+
u32::from_le_bytes(data)
797801
} else {
798-
self.configuration.read_reg(reg_idx)
802+
0
799803
}
804+
} else {
805+
self.configuration.read_reg(reg_idx)
800806
}
801807
}
802808

0 commit comments

Comments
 (0)