vm-virtio: Update VirtioPciCap and introduce VirtioPciCap64

Based on the latest version of the virtio specification, the structure
virtio_pci_cap has been updated and a new structure virtio_pci_cap64 has
been introduced.

virtio_pci_cap now includes a field "id" that does not modify the
existing structure size since there was a 3 bytes reserved field
already there. The id is used in the context of shared memory regions
which need to be identified since there could be more than one of this
kind of capability.

virtio_pci_cap64 is a new structure that includes virtio_pci_cap and
extends it to allow 64 bits offsets and 64 bits region length. This is
used in the context of shared memory regions capability, as we might need
to describe regions of 4G or more, that could be placed at a 4G offset
or more in the associated BAR.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
This commit is contained in:
Sebastien Boeuf 2019-08-05 16:26:21 -07:00 committed by Samuel Ortiz
parent d180deb679
commit d97079d793

View File

@ -42,6 +42,7 @@ enum PciCapabilityType {
IsrConfig = 3, IsrConfig = 3,
DeviceConfig = 4, DeviceConfig = 4,
PciConfig = 5, PciConfig = 5,
SharedMemoryConfig = 8,
} }
#[allow(dead_code)] #[allow(dead_code)]
@ -51,7 +52,8 @@ struct VirtioPciCap {
cap_len: u8, // Generic PCI field: capability length cap_len: u8, // Generic PCI field: capability length
cfg_type: u8, // Identifies the structure. cfg_type: u8, // Identifies the structure.
pci_bar: u8, // Where to find it. pci_bar: u8, // Where to find it.
padding: [u8; 3], // Pad to full dword. id: u8, // Multiple capabilities of the same type
padding: [u8; 2], // Pad to full dword.
offset: Le32, // Offset within bar. offset: Le32, // Offset within bar.
length: Le32, // Length of the structure, in bytes. length: Le32, // Length of the structure, in bytes.
} }
@ -76,7 +78,8 @@ impl VirtioPciCap {
cap_len: (std::mem::size_of::<VirtioPciCap>() as u8) + VIRTIO_PCI_CAP_LEN_OFFSET, cap_len: (std::mem::size_of::<VirtioPciCap>() as u8) + VIRTIO_PCI_CAP_LEN_OFFSET,
cfg_type: cfg_type as u8, cfg_type: cfg_type as u8,
pci_bar, pci_bar,
padding: [0; 3], id: 0,
padding: [0; 2],
offset: Le32::from(offset), offset: Le32::from(offset),
length: Le32::from(length), length: Le32::from(length),
} }
@ -117,7 +120,8 @@ impl VirtioPciNotifyCap {
+ VIRTIO_PCI_CAP_LEN_OFFSET, + VIRTIO_PCI_CAP_LEN_OFFSET,
cfg_type: cfg_type as u8, cfg_type: cfg_type as u8,
pci_bar, pci_bar,
padding: [0; 3], id: 0,
padding: [0; 2],
offset: Le32::from(offset), offset: Le32::from(offset),
length: Le32::from(length), length: Le32::from(length),
}, },
@ -126,6 +130,45 @@ impl VirtioPciNotifyCap {
} }
} }
#[allow(dead_code)]
#[repr(packed)]
#[derive(Clone, Copy, Default)]
struct VirtioPciCap64 {
cap: VirtioPciCap,
offset_hi: Le32,
length_hi: Le32,
}
// It is safe to implement ByteValued. All members are simple numbers and any value is valid.
unsafe impl ByteValued for VirtioPciCap64 {}
impl PciCapability for VirtioPciCap64 {
fn bytes(&self) -> &[u8] {
self.as_slice()
}
fn id(&self) -> PciCapabilityID {
PciCapabilityID::VendorSpecific
}
}
impl VirtioPciCap64 {
pub fn new(cfg_type: PciCapabilityType, pci_bar: u8, id: u8, offset: u64, length: u64) -> Self {
VirtioPciCap64 {
cap: VirtioPciCap {
cap_len: (std::mem::size_of::<VirtioPciCap64>() as u8) + VIRTIO_PCI_CAP_LEN_OFFSET,
cfg_type: cfg_type as u8,
pci_bar,
id,
padding: [0; 2],
offset: Le32::from(offset as u32),
length: Le32::from(length as u32),
},
offset_hi: Le32::from((offset >> 32) as u32),
length_hi: Le32::from((length >> 32) as u32),
}
}
}
#[allow(dead_code)] #[allow(dead_code)]
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
pub enum PciVirtioSubclass { pub enum PciVirtioSubclass {
@ -351,6 +394,17 @@ impl VirtioPciDevice {
.add_capability(&configuration_cap) .add_capability(&configuration_cap)
.map_err(PciDeviceError::CapabilitiesSetup)?; .map_err(PciDeviceError::CapabilitiesSetup)?;
let shm_cap = VirtioPciCap64::new(
PciCapabilityType::SharedMemoryConfig,
settings_bar,
0,
0u64,
0u64,
);
self.configuration
.add_capability(&shm_cap)
.map_err(PciDeviceError::CapabilitiesSetup)?;
if self.msix_config.is_some() { if self.msix_config.is_some() {
let msix_cap = MsixCap::new( let msix_cap = MsixCap::new(
settings_bar, settings_bar,