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}