Skip to main content

pci_core/capabilities/extended/
mod.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! PCIe extended capabilities.
5
6use chipset_device::pci::ByteEnabledDwordRead;
7use chipset_device::pci::ByteEnabledDwordWrite;
8use inspect::Inspect;
9use vmcore::save_restore::ProtobufSaveRestore;
10
11pub mod acs;
12
13/// A generic PCIe extended capability structure.
14pub trait PciExtendedCapability: Send + Sync + Inspect + ProtobufSaveRestore {
15    /// A descriptive label for use in Save/Restore + Inspect output.
16    fn label(&self) -> &str;
17
18    /// Returns the PCIe extended capability ID for this capability.
19    fn extended_capability_id(&self) -> u16;
20
21    /// Returns this extended capability structure version.
22    fn capability_version(&self) -> u8;
23
24    /// Length of the extended capability structure in bytes.
25    ///
26    /// Implementations must satisfy all of the following invariants:
27    /// - Length must be non-zero.
28    /// - Length must be 32-bit aligned (a multiple of 4).
29    /// - When packed into config space by `cfg_space_emu` starting at 0x100,
30    ///   the cumulative size of all extended capabilities must not exceed
31    ///   0x1000.
32    fn len(&self) -> usize;
33
34    /// Read a byte-enabled DWORD at the given capability-relative offset.
35    /// The offset must be 32-bit aligned.
36    fn read(&self, offset: u16, value: ByteEnabledDwordRead<'_>);
37
38    /// Write a byte-enabled DWORD to the given capability-relative offset.
39    /// The offset must be 32-bit aligned.
40    fn write(&mut self, offset: u16, val: ByteEnabledDwordWrite);
41
42    /// Reset the capability.
43    fn reset(&mut self);
44}
45
46#[cfg(test)]
47pub(crate) fn assert_extended_header_contract(cap: &dyn PciExtendedCapability) {
48    let mut value = 0;
49    cap.read(0, ByteEnabledDwordRead::with_all_bytes_enabled(&mut value));
50    let expected =
51        u32::from(cap.extended_capability_id()) | (u32::from(cap.capability_version()) << 16);
52
53    // Capability-local header must contain ID+Version only.
54    // Next-pointer bits are injected by cfg_space_emu list traversal.
55    assert_eq!(value & 0x000f_ffff, expected);
56    assert_eq!(value & 0xfff0_0000, 0);
57}