pci_core/capabilities/
pci_express.rs1use super::PciCapability;
7use crate::spec::caps::CapabilityId;
8use crate::spec::caps::pci_express;
9use crate::spec::caps::pci_express::PciExpressCapabilityHeader;
10use inspect::Inspect;
11use parking_lot::Mutex;
12use std::sync::Arc;
13
14pub const PCI_EXPRESS_DEVICE_CAPS_FLR_BIT_MASK: u32 = 1 << 28;
16
17pub trait FlrHandler: Send + Sync + Inspect {
19 fn initiate_flr(&self);
21}
22
23#[derive(Debug, Inspect)]
24struct PciExpressState {
25 device_control: pci_express::DeviceControl,
26 device_status: pci_express::DeviceStatus,
27}
28
29impl PciExpressState {
30 fn new() -> Self {
31 Self {
32 device_control: pci_express::DeviceControl::new(),
33 device_status: pci_express::DeviceStatus::new(),
34 }
35 }
36}
37
38#[derive(Inspect)]
39pub struct PciExpressCapability {
41 device_capabilities: pci_express::DeviceCapabilities,
42 state: Arc<Mutex<PciExpressState>>,
43 #[inspect(skip)]
44 flr_handler: Option<Arc<dyn FlrHandler>>,
45}
46
47impl PciExpressCapability {
48 pub fn new(flr_handler: Option<Arc<dyn FlrHandler>>) -> Self {
53 Self {
54 device_capabilities: pci_express::DeviceCapabilities::new()
55 .with_function_level_reset(flr_handler.is_some()),
56 state: Arc::new(Mutex::new(PciExpressState::new())),
57 flr_handler,
58 }
59 }
60
61 fn handle_device_control_write(&mut self, new_control: pci_express::DeviceControl) {
62 let mut state = self.state.lock();
63
64 let old_flr = state.device_control.initiate_function_level_reset();
66 let new_flr = new_control.initiate_function_level_reset();
67
68 if new_flr && !old_flr {
72 if let Some(handler) = &self.flr_handler {
73 handler.initiate_flr();
74 }
75 }
76
77 state.device_control = new_control.with_initiate_function_level_reset(false);
79 }
80}
81
82impl PciCapability for PciExpressCapability {
83 fn label(&self) -> &str {
84 "pci-express"
85 }
86
87 fn len(&self) -> usize {
88 0x0C
94 }
95
96 fn read_u32(&self, offset: u16) -> u32 {
97 let label = self.label();
98 match PciExpressCapabilityHeader(offset) {
99 PciExpressCapabilityHeader::PCIE_CAPS => {
100 let pcie_caps: u16 = 0x0002; (pcie_caps as u32) << 16 | CapabilityId::PCI_EXPRESS.0 as u32
104 }
105 PciExpressCapabilityHeader::DEVICE_CAPS => self.device_capabilities.into_bits(),
106 PciExpressCapabilityHeader::DEVICE_CTL_STS => {
107 let state = self.state.lock();
108 let device_control = state.device_control.into_bits() as u32;
109 let device_status = state.device_status.into_bits() as u32;
110 device_control | (device_status << 16)
111 }
112 _ => {
113 tracelimit::warn_ratelimited!(
114 ?label,
115 offset,
116 "unhandled pci express capability read"
117 );
118 0
119 }
120 }
121 }
122
123 fn write_u32(&mut self, offset: u16, val: u32) {
124 let label = self.label();
125 match PciExpressCapabilityHeader(offset) {
126 PciExpressCapabilityHeader::PCIE_CAPS => {
127 tracelimit::warn_ratelimited!(
129 ?label,
130 offset,
131 val,
132 "write to read-only pcie capabilities"
133 );
134 }
135 PciExpressCapabilityHeader::DEVICE_CAPS => {
136 tracelimit::warn_ratelimited!(
138 ?label,
139 offset,
140 val,
141 "write to read-only device capabilities"
142 );
143 }
144 PciExpressCapabilityHeader::DEVICE_CTL_STS => {
145 let new_control = pci_express::DeviceControl::from_bits(val as u16);
148 self.handle_device_control_write(new_control);
149
150 let new_status = pci_express::DeviceStatus::from_bits((val >> 16) as u16);
152 let mut state = self.state.lock();
153 let mut current_status = state.device_status;
154
155 if new_status.correctable_error_detected() {
157 current_status.set_correctable_error_detected(false);
158 }
159 if new_status.non_fatal_error_detected() {
160 current_status.set_non_fatal_error_detected(false);
161 }
162 if new_status.fatal_error_detected() {
163 current_status.set_fatal_error_detected(false);
164 }
165 if new_status.unsupported_request_detected() {
166 current_status.set_unsupported_request_detected(false);
167 }
168
169 state.device_status = current_status;
170 }
171 _ => {
172 tracelimit::warn_ratelimited!(
173 ?label,
174 offset,
175 val,
176 "unhandled pci express capability write"
177 );
178 }
179 }
180 }
181
182 fn reset(&mut self) {
183 let mut state = self.state.lock();
184 *state = PciExpressState::new();
185 }
186}
187
188mod save_restore {
189 use super::*;
190 use vmcore::save_restore::RestoreError;
191 use vmcore::save_restore::SaveError;
192 use vmcore::save_restore::SaveRestore;
193
194 mod state {
195 use mesh::payload::Protobuf;
196 use vmcore::save_restore::SavedStateRoot;
197
198 #[derive(Protobuf, SavedStateRoot)]
199 #[mesh(package = "pci.capabilities.pci_express")]
200 pub struct SavedState {
201 #[mesh(1)]
202 pub device_control: u16,
203 #[mesh(2)]
204 pub device_status: u16,
205 #[mesh(3)]
206 pub flr_handler: u16,
207 }
208 }
209
210 impl SaveRestore for PciExpressCapability {
211 type SavedState = state::SavedState;
212
213 fn save(&mut self) -> Result<Self::SavedState, SaveError> {
214 Err(SaveError::NotSupported)
215 }
216
217 fn restore(&mut self, _: Self::SavedState) -> Result<(), RestoreError> {
218 Err(RestoreError::SavedStateNotSupported)
219 }
220 }
221}
222
223#[cfg(test)]
224mod tests {
225 use super::*;
226 use std::sync::atomic::{AtomicBool, Ordering};
227
228 #[derive(Debug)]
229 struct TestFlrHandler {
230 flr_initiated: AtomicBool,
231 }
232
233 impl TestFlrHandler {
234 fn new() -> Arc<Self> {
235 Arc::new(Self {
236 flr_initiated: AtomicBool::new(false),
237 })
238 }
239
240 fn was_flr_initiated(&self) -> bool {
241 self.flr_initiated.load(Ordering::Acquire)
242 }
243
244 fn reset(&self) {
245 self.flr_initiated.store(false, Ordering::Release);
246 }
247 }
248
249 impl FlrHandler for TestFlrHandler {
250 fn initiate_flr(&self) {
251 self.flr_initiated.store(true, Ordering::Release);
252 }
253 }
254
255 impl Inspect for TestFlrHandler {
256 fn inspect(&self, req: inspect::Request<'_>) {
257 req.respond()
258 .field("flr_initiated", self.flr_initiated.load(Ordering::Acquire));
259 }
260 }
261
262 #[test]
263 fn test_pci_express_capability_read_u32() {
264 let flr_handler = TestFlrHandler::new();
265 let cap = PciExpressCapability::new(Some(flr_handler));
266
267 let caps_val = cap.read_u32(0x00);
269 assert_eq!(caps_val & 0xFF, 0x10); assert_eq!((caps_val >> 8) & 0xFF, 0x00); assert_eq!((caps_val >> 16) & 0xFFFF, 0x0002); let device_caps_val = cap.read_u32(0x04);
275 assert_eq!(
276 device_caps_val & PCI_EXPRESS_DEVICE_CAPS_FLR_BIT_MASK,
277 PCI_EXPRESS_DEVICE_CAPS_FLR_BIT_MASK
278 ); let device_ctl_sts_val = cap.read_u32(0x08);
282 assert_eq!(device_ctl_sts_val, 0); let unhandled_val = cap.read_u32(0x10);
286 assert_eq!(unhandled_val, 0);
287 }
288
289 #[test]
290 fn test_pci_express_capability_read_u32_no_flr() {
291 let cap = PciExpressCapability::new(None);
292
293 let device_caps_val = cap.read_u32(0x04);
295 assert_eq!(device_caps_val & PCI_EXPRESS_DEVICE_CAPS_FLR_BIT_MASK, 0);
296 }
297
298 #[test]
299 fn test_pci_express_capability_write_u32_readonly_registers() {
300 let mut cap = PciExpressCapability::new(None);
301
302 let original_caps = cap.read_u32(0x00);
304 cap.write_u32(0x00, 0xFFFFFFFF);
305 assert_eq!(cap.read_u32(0x00), original_caps); let original_device_caps = cap.read_u32(0x04);
309 cap.write_u32(0x04, 0xFFFFFFFF);
310 assert_eq!(cap.read_u32(0x04), original_device_caps); }
312
313 #[test]
314 fn test_pci_express_capability_write_u32_device_control() {
315 let flr_handler = TestFlrHandler::new();
316 let mut cap = PciExpressCapability::new(Some(flr_handler.clone()));
317
318 let initial_ctl_sts = cap.read_u32(0x08);
320 assert_eq!(initial_ctl_sts & 0xFFFF, 0); cap.write_u32(0x08, 0x0001); let device_ctl_sts = cap.read_u32(0x08);
326 assert_eq!(device_ctl_sts & 0xFFFF, 0x0001); assert!(!flr_handler.was_flr_initiated()); flr_handler.reset();
331 cap.write_u32(0x08, 0x8001); let device_ctl_sts_after_flr = cap.read_u32(0x08);
333 assert_eq!(device_ctl_sts_after_flr & 0xFFFF, 0x0001); assert!(flr_handler.was_flr_initiated()); flr_handler.reset();
338 cap.write_u32(0x08, 0x8000); let device_ctl_sts_final = cap.read_u32(0x08);
342 assert_eq!(device_ctl_sts_final & 0xFFFF, 0x0000); assert!(flr_handler.was_flr_initiated()); }
345
346 #[test]
347 fn test_pci_express_capability_write_u32_device_status() {
348 let mut cap = PciExpressCapability::new(None);
349
350 {
352 let mut state = cap.state.lock();
353 state.device_status.set_correctable_error_detected(true);
354 state.device_status.set_non_fatal_error_detected(true);
355 state.device_status.set_fatal_error_detected(true);
356 state.device_status.set_unsupported_request_detected(true);
357 }
358
359 let device_ctl_sts = cap.read_u32(0x08);
361 let status_bits = (device_ctl_sts >> 16) & 0xFFFF;
362 assert_ne!(status_bits & 0x0F, 0); cap.write_u32(0x08, 0x00010000); let device_ctl_sts_after = cap.read_u32(0x08);
367 let status_bits_after = (device_ctl_sts_after >> 16) & 0xFFFF;
368 assert_eq!(status_bits_after & 0x01, 0); assert_ne!(status_bits_after & 0x0E, 0); cap.write_u32(0x08, 0x000E0000); let final_status = (cap.read_u32(0x08) >> 16) & 0xFFFF;
374 assert_eq!(final_status & 0x0F, 0); }
376
377 #[test]
378 fn test_pci_express_capability_write_u32_unhandled_offset() {
379 let mut cap = PciExpressCapability::new(None);
380
381 cap.write_u32(0x10, 0xFFFFFFFF);
383 assert_eq!(cap.read_u32(0x08), 0); }
386
387 #[test]
388 fn test_pci_express_capability_reset() {
389 let flr_handler = TestFlrHandler::new();
390 let mut cap = PciExpressCapability::new(Some(flr_handler.clone()));
391
392 cap.write_u32(0x08, 0x0001); {
397 let mut state = cap.state.lock();
398 state.device_status.set_correctable_error_detected(true);
399 }
400
401 let device_ctl_sts = cap.read_u32(0x08);
403 assert_ne!(device_ctl_sts, 0);
404
405 cap.reset();
407
408 let device_ctl_sts_after_reset = cap.read_u32(0x08);
410 assert_eq!(device_ctl_sts_after_reset, 0);
411 }
412
413 #[test]
414 fn test_pci_express_capability_length() {
415 let cap = PciExpressCapability::new(None);
416 assert_eq!(cap.len(), 0x0C); }
418
419 #[test]
420 fn test_pci_express_capability_label() {
421 let cap = PciExpressCapability::new(None);
422 assert_eq!(cap.label(), "pci-express");
423 }
424}