devices: implement msix capability structure
The MSI-X feature is ported from Cloud-hypervisor commit 69e27288a2e.
(https://github.com/intel/cloud-hypervisor.git)
In this commit:
- add a new "msix" module to the pci crate.
- implement the MSI-X Capability Structure.
- implement per virtio device msix_vectors() function which represents the
supported MSI-X vector for this device.
BUG=chromium:854765
TEST=launch Crosvm on eve and Linux
TEST=cargo test -p devices
TEST=./bin/clippy
TEST=./build_test.py --x86_64-sysroot /build/eve
Change-Id: I5498b15a3bf115e34764e6610407b3ba204dae7f
Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
Signed-off-by: Zide Chen <zide.chen@intel.corp-partner.google.com>
Signed-off-by: Sainath Grandhi <sainath.grandhi@intel.corp-partner.google.com>
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/1873356
Reviewed-by: Daniel Verkamp <dverkamp@chromium.org>
Tested-by: kokoro <noreply+kokoro@google.com>
Commit-Queue: Stephen Barber <smbarber@chromium.org>
diff --git a/devices/src/pci/msix.rs b/devices/src/pci/msix.rs
new file mode 100644
index 0000000..55e71ba
--- /dev/null
+++ b/devices/src/pci/msix.rs
@@ -0,0 +1,69 @@
+// Copyright 2019 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+use crate::pci::{PciCapability, PciCapabilityID};
+
+use data_model::DataInit;
+
+const MAX_MSIX_VECTORS_PER_DEVICE: u16 = 2048;
+
+// It is safe to implement DataInit; all members are simple numbers and any value is valid.
+unsafe impl DataInit for MsixCap {}
+
+#[allow(dead_code)]
+#[repr(C)]
+#[derive(Clone, Copy, Default)]
+/// MSI-X Capability Structure
+pub struct MsixCap {
+ // To make add_capability() happy
+ _cap_vndr: u8,
+ _cap_next: u8,
+ // Message Control Register
+ // 10-0: MSI-X Table size
+ // 13-11: Reserved
+ // 14: Mask. Mask all MSI-X when set.
+ // 15: Enable. Enable all MSI-X when set.
+ msg_ctl: u16,
+ // Table. Contains the offset and the BAR indicator (BIR)
+ // 2-0: Table BAR indicator (BIR). Can be 0 to 5.
+ // 31-3: Table offset in the BAR pointed by the BIR.
+ table: u32,
+ // Pending Bit Array. Contains the offset and the BAR indicator (BIR)
+ // 2-0: PBA BAR indicator (BIR). Can be 0 to 5.
+ // 31-3: PBA offset in the BAR pointed by the BIR.
+ pba: u32,
+}
+
+impl PciCapability for MsixCap {
+ fn bytes(&self) -> &[u8] {
+ self.as_slice()
+ }
+
+ fn id(&self) -> PciCapabilityID {
+ PciCapabilityID::MSIX
+ }
+}
+
+impl MsixCap {
+ pub fn new(
+ table_pci_bar: u8,
+ table_size: u16,
+ table_off: u32,
+ pba_pci_bar: u8,
+ pba_off: u32,
+ ) -> Self {
+ assert!(table_size < MAX_MSIX_VECTORS_PER_DEVICE);
+
+ // Set the table size and enable MSI-X.
+ let msg_ctl: u16 = 0x8000u16 + table_size - 1;
+
+ MsixCap {
+ _cap_vndr: 0,
+ _cap_next: 0,
+ msg_ctl,
+ table: (table_off & 0xffff_fff8u32) | u32::from(table_pci_bar & 0x7u8),
+ pba: (pba_off & 0xffff_fff8u32) | u32::from(pba_pci_bar & 0x7u8),
+ }
+ }
+}