Skip to content

Commit 4e2673b

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 cef26c1 commit 4e2673b

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 {
@@ -734,67 +745,62 @@ impl PciDevice for VirtioPciDevice {
734745
offset: u8,
735746
data: &[u8],
736747
) -> Option<Arc<Barrier>> {
737-
if BAR0_REG_IDX <= reg_idx && reg_idx < BAR0_REG_IDX + u16::from(NUM_BAR_REGS) {
748+
let in_bars = BAR0_REG_IDX <= reg_idx && reg_idx < BAR0_REG_IDX + u16::from(NUM_BAR_REGS);
749+
let in_msix_cap_header = reg_idx * 4 == self.msix_config_cap_offset;
750+
let in_pci_cfg = self.cap_pci_cfg_info.in_range(reg_idx, offset, data.len());
751+
if in_bars {
738752
// reg_idx is in [BAR0_REG_IDX, BAR0_REG_IDX+NUM_BAR_REGS), so the difference is 0..5.
739753
#[allow(clippy::cast_possible_truncation)]
740754
let bar_idx = (reg_idx - BAR0_REG_IDX) as u8;
741755
self.bars.write(bar_idx, offset, data);
742756
None
757+
} else if in_msix_cap_header {
758+
// For the MsixCap structure, we need to capture writes to the second 2 bytes
759+
// of the capability header where Function Mask and MSI-X Enable bits are present.
760+
// Everything else can be served from `self.configuration`.
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)
743771
} else {
744-
// Handle access to the header of the MsixCapability. The rest of the
745-
// capability is handled by the PciConfiguration.
746-
let base = reg_idx * 4;
747-
if base == self.msix_config_cap_offset {
748-
self.msix_config
749-
.lock()
750-
.unwrap()
751-
.write_msg_ctl_register(offset, data);
752-
}
753-
if base + u16::from(offset) >= self.cap_pci_cfg_info.offset
754-
&& (base + u16::from(offset)) as usize + data.len()
755-
<= self.cap_pci_cfg_info.offset as usize
756-
+ self.cap_pci_cfg_info.cap.bytes().len()
757-
{
758-
let offset = (base + u16::from(offset) - self.cap_pci_cfg_info.offset) as usize;
759-
self.write_cap_pci_cfg(offset, data)
760-
} else {
761-
self.configuration
762-
.write_config_register(reg_idx, offset, data);
763-
None
764-
}
772+
self.configuration
773+
.write_config_register(reg_idx, offset, data);
774+
None
765775
}
766776
}
767777

768778
fn read_config_register(&mut self, reg_idx: u16) -> u32 {
769-
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 = self.cap_pci_cfg_info.in_range(reg_idx, 0, 4);
781+
782+
if in_bars {
770783
// reg_idx is in [BAR0_REG_IDX, BAR0_REG_IDX+NUM_BAR_REGS), so the difference is 0..5.
771784
#[allow(clippy::cast_possible_truncation)]
772785
let bar_idx = (reg_idx - BAR0_REG_IDX) as u8;
773786
let mut value: u32 = 0;
774787
self.bars.read(bar_idx, 0, value.as_mut_bytes());
775788
value
776-
} else {
789+
} else if in_pci_cfg {
777790
// Handle the special case where the capability VIRTIO_PCI_CAP_PCI_CFG
778791
// is accessed. This capability has a special meaning as it allows the
779792
// guest to access other capabilities without mapping the PCI BAR.
780-
let base = reg_idx as usize * 4;
781-
if base >= self.cap_pci_cfg_info.offset as usize
782-
&& base + 4
783-
<= self.cap_pci_cfg_info.offset as usize
784-
+ self.cap_pci_cfg_info.cap.bytes().len()
785-
{
786-
let offset = base - self.cap_pci_cfg_info.offset as usize;
787-
let mut data = [0u8; 4];
788-
let len = u32::from(self.cap_pci_cfg_info.cap.cap.length) as usize;
789-
if len <= 4 {
790-
self.read_cap_pci_cfg(offset, &mut data[..len]);
791-
u32::from_le_bytes(data)
792-
} else {
793-
0
794-
}
793+
let offset = (reg_idx * 4 - self.cap_pci_cfg_info.offset) as usize;
794+
let mut data = [0u8; 4];
795+
let len = u32::from(self.cap_pci_cfg_info.cap.cap.length) as usize;
796+
if len <= 4 {
797+
self.read_cap_pci_cfg(offset, &mut data[..len]);
798+
u32::from_le_bytes(data)
795799
} else {
796-
self.configuration.read_reg(reg_idx)
800+
0
797801
}
802+
} else {
803+
self.configuration.read_reg(reg_idx)
798804
}
799805
}
800806

0 commit comments

Comments
 (0)