summary refs log tree commit diff
path: root/devices/src
diff options
context:
space:
mode:
Diffstat (limited to 'devices/src')
-rw-r--r--devices/src/pci/pci_configuration.rs26
-rw-r--r--devices/src/virtio/virtio_pci_device.rs15
2 files changed, 26 insertions, 15 deletions
diff --git a/devices/src/pci/pci_configuration.rs b/devices/src/pci/pci_configuration.rs
index 532faef..a8f9b65 100644
--- a/devices/src/pci/pci_configuration.rs
+++ b/devices/src/pci/pci_configuration.rs
@@ -419,14 +419,11 @@ impl PciConfiguration {
     }
 
     /// Adds the capability `cap_data` to the list of capabilities.
-    /// `cap_data` should not include the two-byte PCI capability header (type, next);
-    /// it will be generated automatically based on `cap_data.id()`.
+    /// `cap_data` should include the two-byte PCI capability header (type, next),
+    /// but not populate it. Correct values will be generated automatically based
+    /// on `cap_data.id()`.
     pub fn add_capability(&mut self, cap_data: &PciCapability) -> Result<usize> {
-        let total_len = cap_data
-            .bytes()
-            .len()
-            .checked_add(2)
-            .ok_or(Error::CapabilityLengthInvalid(cap_data.bytes().len()))?;
+        let total_len = cap_data.bytes().len();
         // Check that the length is valid.
         if cap_data.bytes().is_empty() {
             return Err(Error::CapabilityEmpty);
@@ -445,8 +442,8 @@ impl PciConfiguration {
         self.write_byte_internal(tail_offset, cap_offset as u8, false);
         self.write_byte_internal(cap_offset, cap_data.id() as u8, false);
         self.write_byte_internal(cap_offset + 1, 0, false); // Next pointer.
-        for (i, byte) in cap_data.bytes().iter().enumerate() {
-            self.write_byte_internal(cap_offset + i + 2, *byte, false);
+        for (i, byte) in cap_data.bytes().iter().enumerate().skip(2) {
+            self.write_byte_internal(cap_offset + i, *byte, false);
         }
         self.last_capability = Some((cap_offset, total_len));
         Ok(cap_offset)
@@ -517,6 +514,8 @@ mod tests {
     #[derive(Clone, Copy)]
     #[allow(dead_code)]
     struct TestCap {
+        _vndr: u8,
+        _next: u8,
         len: u8,
         foo: u8,
     }
@@ -548,11 +547,18 @@ mod tests {
         );
 
         // Add two capabilities with different contents.
-        let cap1 = TestCap { len: 4, foo: 0xAA };
+        let cap1 = TestCap {
+            _vndr: 0,
+            _next: 0,
+            len: 4,
+            foo: 0xAA,
+        };
         let cap1_offset = cfg.add_capability(&cap1).unwrap();
         assert_eq!(cap1_offset % 4, 0);
 
         let cap2 = TestCap {
+            _vndr: 0,
+            _next: 0,
             len: 0x04,
             foo: 0x55,
         };
diff --git a/devices/src/virtio/virtio_pci_device.rs b/devices/src/virtio/virtio_pci_device.rs
index 071c7d6..4ba5437 100644
--- a/devices/src/virtio/virtio_pci_device.rs
+++ b/devices/src/virtio/virtio_pci_device.rs
@@ -29,9 +29,12 @@ pub enum PciCapabilityType {
 }
 
 #[allow(dead_code)]
-#[repr(packed)]
+#[repr(C)]
 #[derive(Clone, Copy)]
 struct VirtioPciCap {
+    // _cap_vndr and _cap_next are autofilled based on id() in pci configuration
+    _cap_vndr: u8,    // Generic PCI field: PCI_CAP_ID_VNDR
+    _cap_next: u8,    // Generic PCI field: next ptr
     cap_len: u8,      // Generic PCI field: capability length
     cfg_type: u8,     // Identifies the structure.
     bar: u8,          // Where to find it.
@@ -52,12 +55,12 @@ impl PciCapability for VirtioPciCap {
     }
 }
 
-const VIRTIO_PCI_CAPABILITY_BYTES: u8 = 16;
-
 impl VirtioPciCap {
     pub fn new(cfg_type: PciCapabilityType, bar: u8, offset: u32, length: u32) -> Self {
         VirtioPciCap {
-            cap_len: VIRTIO_PCI_CAPABILITY_BYTES,
+            _cap_vndr: 0,
+            _cap_next: 0,
+            cap_len: std::mem::size_of::<VirtioPciCap>() as u8,
             cfg_type: cfg_type as u8,
             bar,
             padding: [0; 3],
@@ -68,7 +71,7 @@ impl VirtioPciCap {
 }
 
 #[allow(dead_code)]
-#[repr(packed)]
+#[repr(C)]
 #[derive(Clone, Copy)]
 pub struct VirtioPciNotifyCap {
     cap: VirtioPciCap,
@@ -97,6 +100,8 @@ impl VirtioPciNotifyCap {
     ) -> Self {
         VirtioPciNotifyCap {
             cap: VirtioPciCap {
+                _cap_vndr: 0,
+                _cap_next: 0,
                 cap_len: std::mem::size_of::<VirtioPciNotifyCap>() as u8,
                 cfg_type: cfg_type as u8,
                 bar,