1use 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 link_control: pci_express::LinkControl,
28 link_status: pci_express::LinkStatus,
29 slot_control: pci_express::SlotControl,
30 slot_status: pci_express::SlotStatus,
31 root_control: pci_express::RootControl,
32 root_status: pci_express::RootStatus,
33 device_control_2: pci_express::DeviceControl2,
34 device_status_2: pci_express::DeviceStatus2,
35 link_control_2: pci_express::LinkControl2,
36 link_status_2: pci_express::LinkStatus2,
37 slot_control_2: pci_express::SlotControl2,
38 slot_status_2: pci_express::SlotStatus2,
39}
40
41impl PciExpressState {
42 fn new() -> Self {
43 Self {
44 device_control: pci_express::DeviceControl::new(),
45 device_status: pci_express::DeviceStatus::new(),
46 link_control: pci_express::LinkControl::new(),
47 link_status: pci_express::LinkStatus::new(),
48 slot_control: pci_express::SlotControl::new(),
49 slot_status: pci_express::SlotStatus::new(),
50 root_control: pci_express::RootControl::new(),
51 root_status: pci_express::RootStatus::new(),
52 device_control_2: pci_express::DeviceControl2::new(),
53 device_status_2: pci_express::DeviceStatus2::new(),
54 link_control_2: pci_express::LinkControl2::new(),
55 link_status_2: pci_express::LinkStatus2::new(),
56 slot_control_2: pci_express::SlotControl2::new(),
57 slot_status_2: pci_express::SlotStatus2::new(),
58 }
59 }
60}
61
62#[derive(Inspect)]
63pub struct PciExpressCapability {
65 pcie_capabilities: pci_express::PciExpressCapabilities,
66 device_capabilities: pci_express::DeviceCapabilities,
67 link_capabilities: pci_express::LinkCapabilities,
68 slot_capabilities: pci_express::SlotCapabilities,
69 root_capabilities: pci_express::RootCapabilities,
70 device_capabilities_2: pci_express::DeviceCapabilities2,
71 link_capabilities_2: pci_express::LinkCapabilities2,
72 slot_capabilities_2: pci_express::SlotCapabilities2,
73 state: Arc<Mutex<PciExpressState>>,
74 #[inspect(skip)]
75 flr_handler: Option<Arc<dyn FlrHandler>>,
76}
77
78impl PciExpressCapability {
79 pub fn new(typ: pci_express::DevicePortType, flr_handler: Option<Arc<dyn FlrHandler>>) -> Self {
85 Self {
86 pcie_capabilities: pci_express::PciExpressCapabilities::new()
87 .with_capability_version(2)
88 .with_device_port_type(typ),
89 device_capabilities: pci_express::DeviceCapabilities::new()
90 .with_function_level_reset(flr_handler.is_some()),
91 link_capabilities: pci_express::LinkCapabilities::new(),
92 slot_capabilities: pci_express::SlotCapabilities::new(),
93 root_capabilities: pci_express::RootCapabilities::new(),
94 device_capabilities_2: pci_express::DeviceCapabilities2::new(),
95 link_capabilities_2: pci_express::LinkCapabilities2::new(),
96 slot_capabilities_2: pci_express::SlotCapabilities2::new(),
97 state: Arc::new(Mutex::new(PciExpressState::new())),
98 flr_handler,
99 }
100 }
101
102 fn handle_device_control_write(&mut self, new_control: pci_express::DeviceControl) {
103 let mut state = self.state.lock();
104
105 let old_flr = state.device_control.initiate_function_level_reset();
107 let new_flr = new_control.initiate_function_level_reset();
108
109 if new_flr && !old_flr {
113 if let Some(handler) = &self.flr_handler {
114 handler.initiate_flr();
115 }
116 }
117
118 state.device_control = new_control.with_initiate_function_level_reset(false);
120 }
121}
122
123impl PciCapability for PciExpressCapability {
124 fn label(&self) -> &str {
125 "pci-express"
126 }
127
128 fn len(&self) -> usize {
129 0x3C
147 }
148
149 fn read_u32(&self, offset: u16) -> u32 {
150 let label = self.label();
151 match PciExpressCapabilityHeader(offset) {
152 PciExpressCapabilityHeader::PCIE_CAPS => {
153 (self.pcie_capabilities.into_bits() as u32) << 16
155 | CapabilityId::PCI_EXPRESS.0 as u32
156 }
157 PciExpressCapabilityHeader::DEVICE_CAPS => self.device_capabilities.into_bits(),
158 PciExpressCapabilityHeader::DEVICE_CTL_STS => {
159 let state = self.state.lock();
160 let device_control = state.device_control.into_bits() as u32;
161 let device_status = state.device_status.into_bits() as u32;
162 device_control | (device_status << 16)
163 }
164 PciExpressCapabilityHeader::LINK_CAPS => self.link_capabilities.into_bits(),
165 PciExpressCapabilityHeader::LINK_CTL_STS => {
166 let state = self.state.lock();
168 state.link_control.into_bits() as u32
169 | ((state.link_status.into_bits() as u32) << 16)
170 }
171 PciExpressCapabilityHeader::SLOT_CAPS => self.slot_capabilities.into_bits(),
172 PciExpressCapabilityHeader::SLOT_CTL_STS => {
173 let state = self.state.lock();
175 state.slot_control.into_bits() as u32
176 | ((state.slot_status.into_bits() as u32) << 16)
177 }
178 PciExpressCapabilityHeader::ROOT_CTL_CAPS => {
179 let state = self.state.lock();
181 state.root_control.into_bits() as u32
182 | ((self.root_capabilities.into_bits() as u32) << 16)
183 }
184 PciExpressCapabilityHeader::ROOT_STS => {
185 let state = self.state.lock();
187 state.root_status.into_bits()
188 }
189 PciExpressCapabilityHeader::DEVICE_CAPS_2 => self.device_capabilities_2.into_bits(),
190 PciExpressCapabilityHeader::DEVICE_CTL_STS_2 => {
191 let state = self.state.lock();
193 state.device_control_2.into_bits() as u32
194 | ((state.device_status_2.into_bits() as u32) << 16)
195 }
196 PciExpressCapabilityHeader::LINK_CAPS_2 => self.link_capabilities_2.into_bits(),
197 PciExpressCapabilityHeader::LINK_CTL_STS_2 => {
198 let state = self.state.lock();
200 state.link_control_2.into_bits() as u32
201 | ((state.link_status_2.into_bits() as u32) << 16)
202 }
203 PciExpressCapabilityHeader::SLOT_CAPS_2 => self.slot_capabilities_2.into_bits(),
204 PciExpressCapabilityHeader::SLOT_CTL_STS_2 => {
205 let state = self.state.lock();
207 state.slot_control_2.into_bits() as u32
208 | ((state.slot_status_2.into_bits() as u32) << 16)
209 }
210 _ => {
211 tracelimit::warn_ratelimited!(
212 ?label,
213 offset,
214 "unhandled pci express capability read"
215 );
216 0
217 }
218 }
219 }
220
221 fn write_u32(&mut self, offset: u16, val: u32) {
222 let label = self.label();
223 match PciExpressCapabilityHeader(offset) {
224 PciExpressCapabilityHeader::PCIE_CAPS => {
225 tracelimit::warn_ratelimited!(
227 ?label,
228 offset,
229 val,
230 "write to read-only pcie capabilities"
231 );
232 }
233 PciExpressCapabilityHeader::DEVICE_CAPS => {
234 tracelimit::warn_ratelimited!(
236 ?label,
237 offset,
238 val,
239 "write to read-only device capabilities"
240 );
241 }
242 PciExpressCapabilityHeader::DEVICE_CTL_STS => {
243 let new_control = pci_express::DeviceControl::from_bits(val as u16);
246 self.handle_device_control_write(new_control);
247
248 let new_status = pci_express::DeviceStatus::from_bits((val >> 16) as u16);
250 let mut state = self.state.lock();
251 let mut current_status = state.device_status;
252
253 if new_status.correctable_error_detected() {
255 current_status.set_correctable_error_detected(false);
256 }
257 if new_status.non_fatal_error_detected() {
258 current_status.set_non_fatal_error_detected(false);
259 }
260 if new_status.fatal_error_detected() {
261 current_status.set_fatal_error_detected(false);
262 }
263 if new_status.unsupported_request_detected() {
264 current_status.set_unsupported_request_detected(false);
265 }
266
267 state.device_status = current_status;
268 }
269 PciExpressCapabilityHeader::LINK_CAPS => {
270 tracelimit::warn_ratelimited!(
272 ?label,
273 offset,
274 val,
275 "write to read-only link capabilities"
276 );
277 }
278 PciExpressCapabilityHeader::LINK_CTL_STS => {
279 let mut state = self.state.lock();
281 state.link_control = pci_express::LinkControl::from_bits(val as u16);
282 }
285 PciExpressCapabilityHeader::SLOT_CAPS => {
286 tracelimit::warn_ratelimited!(
288 ?label,
289 offset,
290 val,
291 "write to read-only slot capabilities"
292 );
293 }
294 PciExpressCapabilityHeader::SLOT_CTL_STS => {
295 let mut state = self.state.lock();
297 state.slot_control = pci_express::SlotControl::from_bits(val as u16);
298 state.slot_status = pci_express::SlotStatus::from_bits((val >> 16) as u16);
301 }
302 PciExpressCapabilityHeader::ROOT_CTL_CAPS => {
303 let mut state = self.state.lock();
305 state.root_control = pci_express::RootControl::from_bits(val as u16);
306 }
308 PciExpressCapabilityHeader::ROOT_STS => {
309 let mut state = self.state.lock();
311 state.root_status = pci_express::RootStatus::from_bits(val);
313 }
314 PciExpressCapabilityHeader::DEVICE_CAPS_2 => {
315 tracelimit::warn_ratelimited!(
317 ?label,
318 offset,
319 val,
320 "write to read-only device capabilities 2"
321 );
322 }
323 PciExpressCapabilityHeader::DEVICE_CTL_STS_2 => {
324 let mut state = self.state.lock();
326 state.device_control_2 = pci_express::DeviceControl2::from_bits(val as u16);
327 state.device_status_2 = pci_express::DeviceStatus2::from_bits((val >> 16) as u16);
329 }
330 PciExpressCapabilityHeader::LINK_CAPS_2 => {
331 tracelimit::warn_ratelimited!(
333 ?label,
334 offset,
335 val,
336 "write to read-only link capabilities 2"
337 );
338 }
339 PciExpressCapabilityHeader::LINK_CTL_STS_2 => {
340 let mut state = self.state.lock();
342 state.link_control_2 = pci_express::LinkControl2::from_bits(val as u16);
343 }
345 PciExpressCapabilityHeader::SLOT_CAPS_2 => {
346 tracelimit::warn_ratelimited!(
348 ?label,
349 offset,
350 val,
351 "write to read-only slot capabilities 2"
352 );
353 }
354 PciExpressCapabilityHeader::SLOT_CTL_STS_2 => {
355 let mut state = self.state.lock();
357 state.slot_control_2 = pci_express::SlotControl2::from_bits(val as u16);
358 state.slot_status_2 = pci_express::SlotStatus2::from_bits((val >> 16) as u16);
360 }
361 _ => {
362 tracelimit::warn_ratelimited!(
363 ?label,
364 offset,
365 val,
366 "unhandled pci express capability write"
367 );
368 }
369 }
370 }
371
372 fn reset(&mut self) {
373 let mut state = self.state.lock();
374 *state = PciExpressState::new();
375 }
376}
377
378mod save_restore {
379 use super::*;
380 use vmcore::save_restore::RestoreError;
381 use vmcore::save_restore::SaveError;
382 use vmcore::save_restore::SaveRestore;
383
384 mod state {
385 use mesh::payload::Protobuf;
386 use vmcore::save_restore::SavedStateRoot;
387
388 #[derive(Protobuf, SavedStateRoot)]
389 #[mesh(package = "pci.capabilities.pci_express")]
390 pub struct SavedState {
391 #[mesh(1)]
392 pub device_control: u16,
393 #[mesh(2)]
394 pub device_status: u16,
395 #[mesh(3)]
396 pub flr_handler: u16,
397 }
398 }
399
400 impl SaveRestore for PciExpressCapability {
401 type SavedState = state::SavedState;
402
403 fn save(&mut self) -> Result<Self::SavedState, SaveError> {
404 Err(SaveError::NotSupported)
405 }
406
407 fn restore(&mut self, _: Self::SavedState) -> Result<(), RestoreError> {
408 Err(RestoreError::SavedStateNotSupported)
409 }
410 }
411}
412
413#[cfg(test)]
414mod tests {
415 use super::*;
416 use crate::spec::caps::pci_express::DevicePortType;
417 use std::sync::atomic::{AtomicBool, Ordering};
418
419 #[derive(Debug)]
420 struct TestFlrHandler {
421 flr_initiated: AtomicBool,
422 }
423
424 impl TestFlrHandler {
425 fn new() -> Arc<Self> {
426 Arc::new(Self {
427 flr_initiated: AtomicBool::new(false),
428 })
429 }
430
431 fn was_flr_initiated(&self) -> bool {
432 self.flr_initiated.load(Ordering::Acquire)
433 }
434
435 fn reset(&self) {
436 self.flr_initiated.store(false, Ordering::Release);
437 }
438 }
439
440 impl FlrHandler for TestFlrHandler {
441 fn initiate_flr(&self) {
442 self.flr_initiated.store(true, Ordering::Release);
443 }
444 }
445
446 impl Inspect for TestFlrHandler {
447 fn inspect(&self, req: inspect::Request<'_>) {
448 req.respond()
449 .field("flr_initiated", self.flr_initiated.load(Ordering::Acquire));
450 }
451 }
452
453 #[test]
454 fn test_pci_express_capability_read_u32_endpoint() {
455 let flr_handler = TestFlrHandler::new();
456 let cap = PciExpressCapability::new(DevicePortType::Endpoint, Some(flr_handler));
457
458 let caps_val = cap.read_u32(0x00);
460 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);
466 assert_eq!(
467 device_caps_val & PCI_EXPRESS_DEVICE_CAPS_FLR_BIT_MASK,
468 PCI_EXPRESS_DEVICE_CAPS_FLR_BIT_MASK
469 ); let device_ctl_sts_val = cap.read_u32(0x08);
473 assert_eq!(device_ctl_sts_val, 0); let unhandled_val = cap.read_u32(0x10);
477 assert_eq!(unhandled_val, 0);
478 }
479
480 #[test]
481 fn test_pci_express_capability_read_u32_root_port() {
482 let cap = PciExpressCapability::new(DevicePortType::RootPort, None);
483
484 let caps_val = cap.read_u32(0x00);
486 assert_eq!(caps_val & 0xFF, 0x10); assert_eq!((caps_val >> 8) & 0xFF, 0x00); assert_eq!((caps_val >> 16) & 0xFFFF, 0x0042); }
490
491 #[test]
492 fn test_pci_express_capability_read_u32_no_flr() {
493 let cap = PciExpressCapability::new(DevicePortType::Endpoint, None);
494
495 let device_caps_val = cap.read_u32(0x04);
497 assert_eq!(device_caps_val & PCI_EXPRESS_DEVICE_CAPS_FLR_BIT_MASK, 0);
498 }
499
500 #[test]
501 fn test_pci_express_capability_write_u32_readonly_registers() {
502 let mut cap = PciExpressCapability::new(DevicePortType::Endpoint, None);
503
504 let original_caps = cap.read_u32(0x00);
506 cap.write_u32(0x00, 0xFFFFFFFF);
507 assert_eq!(cap.read_u32(0x00), original_caps); let original_device_caps = cap.read_u32(0x04);
511 cap.write_u32(0x04, 0xFFFFFFFF);
512 assert_eq!(cap.read_u32(0x04), original_device_caps); }
514
515 #[test]
516 fn test_pci_express_capability_write_u32_device_control() {
517 let flr_handler = TestFlrHandler::new();
518 let mut cap =
519 PciExpressCapability::new(DevicePortType::Endpoint, Some(flr_handler.clone()));
520
521 let initial_ctl_sts = cap.read_u32(0x08);
523 assert_eq!(initial_ctl_sts & 0xFFFF, 0); cap.write_u32(0x08, 0x0001); let device_ctl_sts = cap.read_u32(0x08);
529 assert_eq!(device_ctl_sts & 0xFFFF, 0x0001); assert!(!flr_handler.was_flr_initiated()); flr_handler.reset();
534 cap.write_u32(0x08, 0x8001); let device_ctl_sts_after_flr = cap.read_u32(0x08);
536 assert_eq!(device_ctl_sts_after_flr & 0xFFFF, 0x0001); assert!(flr_handler.was_flr_initiated()); flr_handler.reset();
541 cap.write_u32(0x08, 0x8000); let device_ctl_sts_final = cap.read_u32(0x08);
545 assert_eq!(device_ctl_sts_final & 0xFFFF, 0x0000); assert!(flr_handler.was_flr_initiated()); }
548
549 #[test]
550 fn test_pci_express_capability_write_u32_device_status() {
551 let mut cap = PciExpressCapability::new(DevicePortType::Endpoint, None);
552
553 {
555 let mut state = cap.state.lock();
556 state.device_status.set_correctable_error_detected(true);
557 state.device_status.set_non_fatal_error_detected(true);
558 state.device_status.set_fatal_error_detected(true);
559 state.device_status.set_unsupported_request_detected(true);
560 }
561
562 let device_ctl_sts = cap.read_u32(0x08);
564 let status_bits = (device_ctl_sts >> 16) & 0xFFFF;
565 assert_ne!(status_bits & 0x0F, 0); cap.write_u32(0x08, 0x00010000); let device_ctl_sts_after = cap.read_u32(0x08);
570 let status_bits_after = (device_ctl_sts_after >> 16) & 0xFFFF;
571 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;
577 assert_eq!(final_status & 0x0F, 0); }
579
580 #[test]
581 fn test_pci_express_capability_write_u32_unhandled_offset() {
582 let mut cap = PciExpressCapability::new(DevicePortType::Endpoint, None);
583
584 cap.write_u32(0x10, 0xFFFFFFFF);
586 assert_eq!(cap.read_u32(0x08), 0); }
589
590 #[test]
591 fn test_pci_express_capability_reset() {
592 let flr_handler = TestFlrHandler::new();
593 let mut cap =
594 PciExpressCapability::new(DevicePortType::Endpoint, Some(flr_handler.clone()));
595
596 cap.write_u32(0x08, 0x0001); {
601 let mut state = cap.state.lock();
602 state.device_status.set_correctable_error_detected(true);
603 }
604
605 let device_ctl_sts = cap.read_u32(0x08);
607 assert_ne!(device_ctl_sts, 0);
608
609 cap.reset();
611
612 let device_ctl_sts_after_reset = cap.read_u32(0x08);
614 assert_eq!(device_ctl_sts_after_reset, 0);
615 }
616
617 #[test]
618 fn test_pci_express_capability_extended_registers() {
619 let cap = PciExpressCapability::new(DevicePortType::Endpoint, None);
620
621 assert_eq!(cap.read_u32(0x0C), 0); assert_eq!(cap.read_u32(0x10), 0); assert_eq!(cap.read_u32(0x14), 0); assert_eq!(cap.read_u32(0x18), 0); assert_eq!(cap.read_u32(0x1C), 0); assert_eq!(cap.read_u32(0x20), 0); assert_eq!(cap.read_u32(0x24), 0); assert_eq!(cap.read_u32(0x28), 0); assert_eq!(cap.read_u32(0x2C), 0); assert_eq!(cap.read_u32(0x30), 0); assert_eq!(cap.read_u32(0x34), 0); assert_eq!(cap.read_u32(0x38), 0); }
635
636 #[test]
637 fn test_pci_express_capability_length() {
638 let cap = PciExpressCapability::new(DevicePortType::Endpoint, None);
639 assert_eq!(cap.len(), 0x3C); }
641
642 #[test]
643 fn test_pci_express_capability_label() {
644 let cap = PciExpressCapability::new(DevicePortType::Endpoint, None);
645 assert_eq!(cap.label(), "pci-express");
646 }
647}