1use super::PciCapability;
7use crate::spec::caps::CapabilityId;
8use crate::spec::caps::pci_express;
9use crate::spec::caps::pci_express::{
10 LinkSpeed, LinkWidth, PciExpressCapabilityHeader, SupportedLinkSpeedsVector,
11};
12use inspect::Inspect;
13use parking_lot::Mutex;
14use std::sync::Arc;
15
16pub const PCI_EXPRESS_DEVICE_CAPS_FLR_BIT_MASK: u32 = 1 << 28;
18
19pub trait FlrHandler: Send + Sync + Inspect {
21 fn initiate_flr(&self);
23}
24
25#[derive(Debug, Inspect)]
26struct PciExpressState {
27 device_control: pci_express::DeviceControl,
28 device_status: pci_express::DeviceStatus,
29 link_control: pci_express::LinkControl,
30 link_status: pci_express::LinkStatus,
31 slot_control: pci_express::SlotControl,
32 slot_status: pci_express::SlotStatus,
33 root_control: pci_express::RootControl,
34 root_status: pci_express::RootStatus,
35 device_control_2: pci_express::DeviceControl2,
36 device_status_2: pci_express::DeviceStatus2,
37 link_control_2: pci_express::LinkControl2,
38 link_status_2: pci_express::LinkStatus2,
39 slot_control_2: pci_express::SlotControl2,
40 slot_status_2: pci_express::SlotStatus2,
41}
42
43impl PciExpressState {
44 fn new() -> Self {
45 Self {
46 device_control: pci_express::DeviceControl::new(),
47 device_status: pci_express::DeviceStatus::new(),
48 link_control: pci_express::LinkControl::new(),
49 link_status: pci_express::LinkStatus::new()
50 .with_current_link_speed(LinkSpeed::Speed32_0GtS.into_bits() as u16)
51 .with_negotiated_link_width(LinkWidth::X16.into_bits() as u16),
52 slot_control: pci_express::SlotControl::new(),
53 slot_status: pci_express::SlotStatus::new(),
54 root_control: pci_express::RootControl::new(),
55 root_status: pci_express::RootStatus::new(),
56 device_control_2: pci_express::DeviceControl2::new(),
57 device_status_2: pci_express::DeviceStatus2::new(),
58 link_control_2: pci_express::LinkControl2::new()
59 .with_target_link_speed(LinkSpeed::Speed32_0GtS.into_bits() as u16),
60 link_status_2: pci_express::LinkStatus2::new(),
61 slot_control_2: pci_express::SlotControl2::new(),
62 slot_status_2: pci_express::SlotStatus2::new(),
63 }
64 }
65}
66
67#[derive(Inspect)]
68pub struct PciExpressCapability {
70 pcie_capabilities: pci_express::PciExpressCapabilities,
71 device_capabilities: pci_express::DeviceCapabilities,
72 link_capabilities: pci_express::LinkCapabilities,
73 slot_capabilities: pci_express::SlotCapabilities,
74 root_capabilities: pci_express::RootCapabilities,
75 device_capabilities_2: pci_express::DeviceCapabilities2,
76 link_capabilities_2: pci_express::LinkCapabilities2,
77 slot_capabilities_2: pci_express::SlotCapabilities2,
78 state: Arc<Mutex<PciExpressState>>,
79 #[inspect(skip)]
80 flr_handler: Option<Arc<dyn FlrHandler>>,
81}
82
83impl PciExpressCapability {
84 pub fn new(typ: pci_express::DevicePortType, flr_handler: Option<Arc<dyn FlrHandler>>) -> Self {
90 Self {
91 pcie_capabilities: pci_express::PciExpressCapabilities::new()
92 .with_capability_version(2)
93 .with_device_port_type(typ),
94 device_capabilities: pci_express::DeviceCapabilities::new()
95 .with_function_level_reset(flr_handler.is_some()),
96 link_capabilities: pci_express::LinkCapabilities::new()
97 .with_max_link_speed(LinkSpeed::Speed32_0GtS.into_bits()) .with_max_link_width(LinkWidth::X16.into_bits()), slot_capabilities: pci_express::SlotCapabilities::new(),
100 root_capabilities: pci_express::RootCapabilities::new(),
101 device_capabilities_2: pci_express::DeviceCapabilities2::new(),
102 link_capabilities_2: pci_express::LinkCapabilities2::new()
103 .with_supported_link_speeds_vector(SupportedLinkSpeedsVector::UpToGen5.into_bits()), slot_capabilities_2: pci_express::SlotCapabilities2::new(),
105 state: Arc::new(Mutex::new(PciExpressState::new())),
106 flr_handler,
107 }
108 }
109
110 fn handle_device_control_status_write(&mut self, val: u32) {
111 let new_control = pci_express::DeviceControl::from_bits(val as u16);
113 let mut state = self.state.lock();
114
115 let old_flr = state.device_control.initiate_function_level_reset();
117 let new_flr = new_control.initiate_function_level_reset();
118
119 if new_flr && !old_flr {
123 if let Some(handler) = &self.flr_handler {
124 handler.initiate_flr();
125 }
126 }
127
128 state.device_control = new_control.with_initiate_function_level_reset(false);
130
131 let new_status = pci_express::DeviceStatus::from_bits((val >> 16) as u16);
133 let mut current_status = state.device_status;
134
135 if new_status.correctable_error_detected() {
137 current_status.set_correctable_error_detected(false);
138 }
139 if new_status.non_fatal_error_detected() {
140 current_status.set_non_fatal_error_detected(false);
141 }
142 if new_status.fatal_error_detected() {
143 current_status.set_fatal_error_detected(false);
144 }
145 if new_status.unsupported_request_detected() {
146 current_status.set_unsupported_request_detected(false);
147 }
148
149 state.device_status = current_status;
150 }
151
152 fn handle_slot_control_status_write(&mut self, val: u32) {
153 let new_slot_control = pci_express::SlotControl::from_bits(val as u16);
155 let mut state = self.state.lock();
156
157 let mut masked_control = new_slot_control;
160
161 if !self.slot_capabilities.attention_button_present() {
163 masked_control.set_attention_button_pressed_enable(false);
164 }
165
166 if !self.slot_capabilities.power_controller_present() {
168 masked_control.set_power_controller_control(false);
169 }
170
171 if !self.slot_capabilities.mrl_sensor_present() {
173 masked_control.set_mrl_sensor_changed_enable(false);
174 }
175
176 if !self.slot_capabilities.attention_indicator_present() {
178 masked_control.set_attention_indicator_control(0);
179 }
180
181 if !self.slot_capabilities.power_indicator_present() {
183 masked_control.set_power_indicator_control(0);
184 }
185
186 if !self.slot_capabilities.hot_plug_capable() {
188 masked_control.set_hot_plug_interrupt_enable(false);
189 }
190
191 if !self.slot_capabilities.electromechanical_interlock_present() {
193 masked_control.set_electromechanical_interlock_control(false);
194 }
195
196 if self.slot_capabilities.no_command_completed_support() {
198 masked_control.set_command_completed_interrupt_enable(false);
199 }
200
201 state.slot_control = masked_control;
202
203 let new_slot_status = pci_express::SlotStatus::from_bits((val >> 16) as u16);
205 let mut current_slot_status = state.slot_status;
206
207 if new_slot_status.attention_button_pressed() {
210 current_slot_status.set_attention_button_pressed(false);
211 }
212 if new_slot_status.power_fault_detected() {
213 current_slot_status.set_power_fault_detected(false);
214 }
215 if new_slot_status.mrl_sensor_changed() {
216 current_slot_status.set_mrl_sensor_changed(false);
217 }
218 if new_slot_status.presence_detect_changed() {
219 current_slot_status.set_presence_detect_changed(false);
220 }
221 if new_slot_status.command_completed() {
222 current_slot_status.set_command_completed(false);
223 }
224 if new_slot_status.data_link_layer_state_changed() {
225 current_slot_status.set_data_link_layer_state_changed(false);
226 }
227
228 state.slot_status = current_slot_status;
232 }
233
234 fn handle_link_control_status_write(&mut self, val: u32) {
235 let new_link_control = pci_express::LinkControl::from_bits(val as u16);
237 let mut state = self.state.lock();
238
239 let mut masked_control = new_link_control;
241 masked_control.set_retrain_link(false); state.link_control = masked_control;
244 }
246
247 fn handle_link_control_2_write(&mut self, val: u32) {
248 let new_link_control_2 = pci_express::LinkControl2::from_bits(val as u16);
250 let mut state = self.state.lock();
251
252 let max_speed = self.link_capabilities.max_link_speed();
254 let requested_speed = new_link_control_2.target_link_speed();
255
256 let actual_speed = if requested_speed > max_speed as u16 {
258 max_speed as u16
259 } else {
260 requested_speed
261 };
262
263 state.link_control_2 = new_link_control_2.with_target_link_speed(actual_speed);
265
266 state.link_status = state.link_status.with_current_link_speed(actual_speed);
269
270 }
272
273 pub fn with_hotplug_support(mut self, slot_number: u32) -> Self {
280 use pci_express::DevicePortType;
281
282 let port_type = self.pcie_capabilities.device_port_type();
284 match port_type {
285 DevicePortType::RootPort | DevicePortType::DownstreamSwitchPort => {
286 }
288 DevicePortType::Endpoint | DevicePortType::UpstreamSwitchPort => {
289 panic!(
290 "Hotplug support is not valid for device port type {:?}. \
291 Only RootPort and DownstreamSwitchPort support hotplug.",
292 port_type
293 );
294 }
295 }
296
297 self.pcie_capabilities = self.pcie_capabilities.with_slot_implemented(true);
299
300 self.slot_capabilities = self
315 .slot_capabilities
316 .with_hot_plug_surprise(true)
317 .with_hot_plug_capable(true)
318 .with_no_command_completed_support(true)
319 .with_physical_slot_number(slot_number);
320
321 self.link_capabilities = self
323 .link_capabilities
324 .with_data_link_layer_link_active_reporting(true);
325
326 self
327 }
328
329 pub fn set_presence_detect_state(&self, present: bool) {
338 if !self.pcie_capabilities.slot_implemented() {
339 return;
341 }
342
343 let mut state = self.state.lock();
344 state.slot_status =
345 state
346 .slot_status
347 .with_presence_detect_state(if present { 1 } else { 0 });
348
349 state.link_status = state.link_status.with_data_link_layer_link_active(present);
352 }
353
354 pub fn set_hotplug_changed_bits(&self) {
357 let mut state = self.state.lock();
358 state.slot_status.set_presence_detect_changed(true);
359 state.slot_status.set_data_link_layer_state_changed(true);
360 }
361
362 pub fn set_hotplug_state(&self, present: bool) {
365 if !self.pcie_capabilities.slot_implemented() {
366 return;
367 }
368
369 let mut state = self.state.lock();
370 state.slot_status =
371 state
372 .slot_status
373 .with_presence_detect_state(if present { 1 } else { 0 });
374 state.link_status = state.link_status.with_data_link_layer_link_active(present);
375
376 if present {
380 state.link_status = state
381 .link_status
382 .with_current_link_speed(LinkSpeed::Speed32_0GtS.into_bits() as u16)
383 .with_negotiated_link_width(LinkWidth::X16.into_bits() as u16);
384 } else {
385 state.link_status = state
386 .link_status
387 .with_current_link_speed(0)
388 .with_negotiated_link_width(0);
389 }
390
391 state.slot_status.set_presence_detect_changed(true);
392 state.slot_status.set_data_link_layer_state_changed(true);
393 }
394
395 pub fn hot_plug_interrupt_enabled(&self) -> bool {
397 self.state.lock().slot_control.hot_plug_interrupt_enable()
398 }
399
400 pub fn slot_capabilities(&self) -> &pci_express::SlotCapabilities {
402 &self.slot_capabilities
403 }
404}
405
406impl PciCapability for PciExpressCapability {
407 fn label(&self) -> &str {
408 "pci-express"
409 }
410
411 fn capability_id(&self) -> CapabilityId {
412 CapabilityId::PCI_EXPRESS
413 }
414
415 fn len(&self) -> usize {
416 0x3C
434 }
435
436 fn read_u32(&self, offset: u16) -> u32 {
437 let label = self.label();
438 match PciExpressCapabilityHeader(offset) {
439 PciExpressCapabilityHeader::PCIE_CAPS => {
440 (self.pcie_capabilities.into_bits() as u32) << 16
442 | CapabilityId::PCI_EXPRESS.0 as u32
443 }
444 PciExpressCapabilityHeader::DEVICE_CAPS => self.device_capabilities.into_bits(),
445 PciExpressCapabilityHeader::DEVICE_CTL_STS => {
446 let state = self.state.lock();
447 let device_control = state.device_control.into_bits() as u32;
448 let device_status = state.device_status.into_bits() as u32;
449 device_control | (device_status << 16)
450 }
451 PciExpressCapabilityHeader::LINK_CAPS => self.link_capabilities.into_bits(),
452 PciExpressCapabilityHeader::LINK_CTL_STS => {
453 let state = self.state.lock();
455 state.link_control.into_bits() as u32
456 | ((state.link_status.into_bits() as u32) << 16)
457 }
458 PciExpressCapabilityHeader::SLOT_CAPS => self.slot_capabilities.into_bits(),
459 PciExpressCapabilityHeader::SLOT_CTL_STS => {
460 let state = self.state.lock();
462 state.slot_control.into_bits() as u32
463 | ((state.slot_status.into_bits() as u32) << 16)
464 }
465 PciExpressCapabilityHeader::ROOT_CTL_CAPS => {
466 let state = self.state.lock();
468 state.root_control.into_bits() as u32
469 | ((self.root_capabilities.into_bits() as u32) << 16)
470 }
471 PciExpressCapabilityHeader::ROOT_STS => {
472 let state = self.state.lock();
474 state.root_status.into_bits()
475 }
476 PciExpressCapabilityHeader::DEVICE_CAPS_2 => self.device_capabilities_2.into_bits(),
477 PciExpressCapabilityHeader::DEVICE_CTL_STS_2 => {
478 let state = self.state.lock();
480 state.device_control_2.into_bits() as u32
481 | ((state.device_status_2.into_bits() as u32) << 16)
482 }
483 PciExpressCapabilityHeader::LINK_CAPS_2 => self.link_capabilities_2.into_bits(),
484 PciExpressCapabilityHeader::LINK_CTL_STS_2 => {
485 let state = self.state.lock();
487 state.link_control_2.into_bits() as u32
488 | ((state.link_status_2.into_bits() as u32) << 16)
489 }
490 PciExpressCapabilityHeader::SLOT_CAPS_2 => self.slot_capabilities_2.into_bits(),
491 PciExpressCapabilityHeader::SLOT_CTL_STS_2 => {
492 let state = self.state.lock();
494 state.slot_control_2.into_bits() as u32
495 | ((state.slot_status_2.into_bits() as u32) << 16)
496 }
497 _ => {
498 tracelimit::warn_ratelimited!(
499 ?label,
500 offset,
501 "unhandled pci express capability read"
502 );
503 0
504 }
505 }
506 }
507
508 fn write_u32(&mut self, offset: u16, val: u32) {
509 let label = self.label();
510 match PciExpressCapabilityHeader(offset) {
511 PciExpressCapabilityHeader::PCIE_CAPS => {
512 tracelimit::warn_ratelimited!(
514 ?label,
515 offset,
516 val,
517 "write to read-only pcie capabilities"
518 );
519 }
520 PciExpressCapabilityHeader::DEVICE_CAPS => {
521 tracelimit::warn_ratelimited!(
523 ?label,
524 offset,
525 val,
526 "write to read-only device capabilities"
527 );
528 }
529 PciExpressCapabilityHeader::DEVICE_CTL_STS => {
530 self.handle_device_control_status_write(val);
531 }
532 PciExpressCapabilityHeader::LINK_CAPS => {
533 tracelimit::warn_ratelimited!(
535 ?label,
536 offset,
537 val,
538 "write to read-only link capabilities"
539 );
540 }
541 PciExpressCapabilityHeader::LINK_CTL_STS => {
542 self.handle_link_control_status_write(val);
543 }
544 PciExpressCapabilityHeader::SLOT_CAPS => {
545 tracelimit::warn_ratelimited!(
547 ?label,
548 offset,
549 val,
550 "write to read-only slot capabilities"
551 );
552 }
553 PciExpressCapabilityHeader::SLOT_CTL_STS => {
554 self.handle_slot_control_status_write(val);
555 }
556 PciExpressCapabilityHeader::ROOT_CTL_CAPS => {
557 let mut state = self.state.lock();
559 state.root_control = pci_express::RootControl::from_bits(val as u16);
560 }
562 PciExpressCapabilityHeader::ROOT_STS => {
563 let mut state = self.state.lock();
565 state.root_status = pci_express::RootStatus::from_bits(val);
567 }
568 PciExpressCapabilityHeader::DEVICE_CAPS_2 => {
569 tracelimit::warn_ratelimited!(
571 ?label,
572 offset,
573 val,
574 "write to read-only device capabilities 2"
575 );
576 }
577 PciExpressCapabilityHeader::DEVICE_CTL_STS_2 => {
578 let mut state = self.state.lock();
580 state.device_control_2 = pci_express::DeviceControl2::from_bits(val as u16);
581 state.device_status_2 = pci_express::DeviceStatus2::from_bits((val >> 16) as u16);
583 }
584 PciExpressCapabilityHeader::LINK_CAPS_2 => {
585 tracelimit::warn_ratelimited!(
587 ?label,
588 offset,
589 val,
590 "write to read-only link capabilities 2"
591 );
592 }
593 PciExpressCapabilityHeader::LINK_CTL_STS_2 => {
594 self.handle_link_control_2_write(val);
595 }
596 PciExpressCapabilityHeader::SLOT_CAPS_2 => {
597 tracelimit::warn_ratelimited!(
599 ?label,
600 offset,
601 val,
602 "write to read-only slot capabilities 2"
603 );
604 }
605 PciExpressCapabilityHeader::SLOT_CTL_STS_2 => {
606 let mut state = self.state.lock();
608 state.slot_control_2 = pci_express::SlotControl2::from_bits(val as u16);
609 state.slot_status_2 = pci_express::SlotStatus2::from_bits((val >> 16) as u16);
611 }
612 _ => {
613 tracelimit::warn_ratelimited!(
614 ?label,
615 offset,
616 val,
617 "unhandled pci express capability write"
618 );
619 }
620 }
621 }
622
623 fn reset(&mut self) {
624 let mut state = self.state.lock();
625 *state = PciExpressState::new();
626 }
627
628 fn as_pci_express(&self) -> Option<&PciExpressCapability> {
629 Some(self)
630 }
631
632 fn as_pci_express_mut(&mut self) -> Option<&mut PciExpressCapability> {
633 Some(self)
634 }
635}
636
637mod save_restore {
638 use super::*;
639 use vmcore::save_restore::RestoreError;
640 use vmcore::save_restore::SaveError;
641 use vmcore::save_restore::SaveRestore;
642
643 mod state {
644 use mesh::payload::Protobuf;
645 use vmcore::save_restore::SavedStateRoot;
646
647 #[derive(Protobuf, SavedStateRoot)]
648 #[mesh(package = "pci.capabilities.pci_express")]
649 pub struct SavedState {
650 #[mesh(1)]
651 pub device_control: u16,
652 #[mesh(2)]
653 pub device_status: u16,
654 #[mesh(3)]
655 pub flr_handler: u16,
656 }
657 }
658
659 impl SaveRestore for PciExpressCapability {
660 type SavedState = state::SavedState;
661
662 fn save(&mut self) -> Result<Self::SavedState, SaveError> {
663 Err(SaveError::NotSupported)
664 }
665
666 fn restore(&mut self, _: Self::SavedState) -> Result<(), RestoreError> {
667 Err(RestoreError::SavedStateNotSupported)
668 }
669 }
670}
671
672#[cfg(test)]
673mod tests {
674 use super::*;
675 use crate::spec::caps::pci_express::DevicePortType;
676 use std::sync::atomic::{AtomicBool, Ordering};
677
678 #[derive(Debug)]
679 struct TestFlrHandler {
680 flr_initiated: AtomicBool,
681 }
682
683 impl TestFlrHandler {
684 fn new() -> Arc<Self> {
685 Arc::new(Self {
686 flr_initiated: AtomicBool::new(false),
687 })
688 }
689
690 fn was_flr_initiated(&self) -> bool {
691 self.flr_initiated.load(Ordering::Acquire)
692 }
693
694 fn reset(&self) {
695 self.flr_initiated.store(false, Ordering::Release);
696 }
697 }
698
699 impl FlrHandler for TestFlrHandler {
700 fn initiate_flr(&self) {
701 self.flr_initiated.store(true, Ordering::Release);
702 }
703 }
704
705 impl Inspect for TestFlrHandler {
706 fn inspect(&self, req: inspect::Request<'_>) {
707 req.respond()
708 .field("flr_initiated", self.flr_initiated.load(Ordering::Acquire));
709 }
710 }
711
712 #[test]
713 fn test_pci_express_capability_read_u32_endpoint() {
714 let flr_handler = TestFlrHandler::new();
715 let cap = PciExpressCapability::new(DevicePortType::Endpoint, Some(flr_handler));
716
717 let caps_val = cap.read_u32(0x00);
719 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);
725 assert_eq!(
726 device_caps_val & PCI_EXPRESS_DEVICE_CAPS_FLR_BIT_MASK,
727 PCI_EXPRESS_DEVICE_CAPS_FLR_BIT_MASK
728 ); let device_ctl_sts_val = cap.read_u32(0x08);
732 assert_eq!(device_ctl_sts_val, 0); let link_ctl_sts_val = cap.read_u32(0x10);
736 let expected_link_status = (LinkSpeed::Speed32_0GtS.into_bits() as u16)
737 | ((LinkWidth::X16.into_bits() as u16) << 4); assert_eq!(link_ctl_sts_val, (expected_link_status as u32) << 16); }
740
741 #[test]
742 fn test_pci_express_capability_read_u32_root_port() {
743 let cap = PciExpressCapability::new(DevicePortType::RootPort, None);
744
745 let caps_val = cap.read_u32(0x00);
747 assert_eq!(caps_val & 0xFF, 0x10); assert_eq!((caps_val >> 8) & 0xFF, 0x00); assert_eq!((caps_val >> 16) & 0xFFFF, 0x0042); }
751
752 #[test]
753 fn test_pci_express_capability_read_u32_no_flr() {
754 let cap = PciExpressCapability::new(DevicePortType::Endpoint, None);
755
756 let device_caps_val = cap.read_u32(0x04);
758 assert_eq!(device_caps_val & PCI_EXPRESS_DEVICE_CAPS_FLR_BIT_MASK, 0);
759 }
760
761 #[test]
762 fn test_pci_express_capability_write_u32_readonly_registers() {
763 let mut cap = PciExpressCapability::new(DevicePortType::Endpoint, None);
764
765 let original_caps = cap.read_u32(0x00);
767 cap.write_u32(0x00, 0xFFFFFFFF);
768 assert_eq!(cap.read_u32(0x00), original_caps); let original_device_caps = cap.read_u32(0x04);
772 cap.write_u32(0x04, 0xFFFFFFFF);
773 assert_eq!(cap.read_u32(0x04), original_device_caps); }
775
776 #[test]
777 fn test_pci_express_capability_write_u32_device_control() {
778 let flr_handler = TestFlrHandler::new();
779 let mut cap =
780 PciExpressCapability::new(DevicePortType::Endpoint, Some(flr_handler.clone()));
781
782 let initial_ctl_sts = cap.read_u32(0x08);
784 assert_eq!(initial_ctl_sts & 0xFFFF, 0); cap.write_u32(0x08, 0x0001); let device_ctl_sts = cap.read_u32(0x08);
790 assert_eq!(device_ctl_sts & 0xFFFF, 0x0001); assert!(!flr_handler.was_flr_initiated()); flr_handler.reset();
795 cap.write_u32(0x08, 0x8001); let device_ctl_sts_after_flr = cap.read_u32(0x08);
797 assert_eq!(device_ctl_sts_after_flr & 0xFFFF, 0x0001); assert!(flr_handler.was_flr_initiated()); flr_handler.reset();
802 cap.write_u32(0x08, 0x8000); let device_ctl_sts_final = cap.read_u32(0x08);
806 assert_eq!(device_ctl_sts_final & 0xFFFF, 0x0000); assert!(flr_handler.was_flr_initiated()); }
809
810 #[test]
811 fn test_pci_express_capability_write_u32_device_status() {
812 let mut cap = PciExpressCapability::new(DevicePortType::Endpoint, None);
813
814 {
816 let mut state = cap.state.lock();
817 state.device_status.set_correctable_error_detected(true);
818 state.device_status.set_non_fatal_error_detected(true);
819 state.device_status.set_fatal_error_detected(true);
820 state.device_status.set_unsupported_request_detected(true);
821 }
822
823 let device_ctl_sts = cap.read_u32(0x08);
825 let status_bits = (device_ctl_sts >> 16) & 0xFFFF;
826 assert_ne!(status_bits & 0x0F, 0); cap.write_u32(0x08, 0x00010000); let device_ctl_sts_after = cap.read_u32(0x08);
831 let status_bits_after = (device_ctl_sts_after >> 16) & 0xFFFF;
832 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;
838 assert_eq!(final_status & 0x0F, 0); }
840
841 #[test]
842 fn test_pci_express_capability_write_u32_unhandled_offset() {
843 let mut cap = PciExpressCapability::new(DevicePortType::Endpoint, None);
844
845 cap.write_u32(0x10, 0xFFFFFFFF);
847 assert_eq!(cap.read_u32(0x08), 0); }
850
851 #[test]
852 fn test_pci_express_capability_reset() {
853 let flr_handler = TestFlrHandler::new();
854 let mut cap =
855 PciExpressCapability::new(DevicePortType::Endpoint, Some(flr_handler.clone()));
856
857 cap.write_u32(0x08, 0x0001); {
862 let mut state = cap.state.lock();
863 state.device_status.set_correctable_error_detected(true);
864 }
865
866 let device_ctl_sts = cap.read_u32(0x08);
868 assert_ne!(device_ctl_sts, 0);
869
870 cap.reset();
872
873 let device_ctl_sts_after_reset = cap.read_u32(0x08);
875 assert_eq!(device_ctl_sts_after_reset, 0);
876 }
877
878 #[test]
879 fn test_pci_express_capability_extended_registers() {
880 let cap = PciExpressCapability::new(DevicePortType::Endpoint, None);
881
882 let expected_link_caps =
885 LinkSpeed::Speed32_0GtS.into_bits() | (LinkWidth::X16.into_bits() << 4); assert_eq!(cap.read_u32(0x0C), expected_link_caps); let expected_link_ctl_sts = (LinkSpeed::Speed32_0GtS.into_bits() as u16)
889 | ((LinkWidth::X16.into_bits() as u16) << 4); assert_eq!(cap.read_u32(0x10), (expected_link_ctl_sts as u32) << 16); 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); let expected_link_caps_2 = SupportedLinkSpeedsVector::UpToGen5.into_bits() << 1; assert_eq!(cap.read_u32(0x2C), expected_link_caps_2); let expected_link_ctl_sts_2 = LinkSpeed::Speed32_0GtS.into_bits() as u16; assert_eq!(cap.read_u32(0x30), expected_link_ctl_sts_2 as u32); assert_eq!(cap.read_u32(0x34), 0); assert_eq!(cap.read_u32(0x38), 0); }
906
907 #[test]
908 fn test_pci_express_capability_length() {
909 let cap = PciExpressCapability::new(DevicePortType::Endpoint, None);
910 assert_eq!(cap.len(), 0x3C); }
912
913 #[test]
914 fn test_pci_express_capability_label() {
915 let cap = PciExpressCapability::new(DevicePortType::Endpoint, None);
916 assert_eq!(cap.label(), "pci-express");
917 }
918
919 #[test]
920 fn test_pci_express_capability_with_hotplug_support() {
921 let cap = PciExpressCapability::new(DevicePortType::RootPort, None);
923 let cap_with_hotplug = cap.with_hotplug_support(1);
924
925 assert_eq!(cap_with_hotplug.label(), "pci-express");
927 assert_eq!(cap_with_hotplug.len(), 0x3C);
928
929 assert!(cap_with_hotplug.slot_capabilities.hot_plug_surprise());
931 assert!(cap_with_hotplug.slot_capabilities.hot_plug_capable());
932 assert_eq!(cap_with_hotplug.slot_capabilities.physical_slot_number(), 1);
933
934 assert!(
936 cap_with_hotplug.pcie_capabilities.slot_implemented(),
937 "slot_implemented should be true when hotplug is enabled"
938 );
939
940 let cap2 = PciExpressCapability::new(DevicePortType::DownstreamSwitchPort, None);
942 let cap2_with_hotplug = cap2.with_hotplug_support(2);
943
944 assert!(cap2_with_hotplug.slot_capabilities.hot_plug_surprise());
945 assert!(cap2_with_hotplug.slot_capabilities.hot_plug_capable());
946 assert_eq!(
947 cap2_with_hotplug.slot_capabilities.physical_slot_number(),
948 2
949 );
950
951 assert!(
953 cap2_with_hotplug.pcie_capabilities.slot_implemented(),
954 "slot_implemented should be true when hotplug is enabled"
955 );
956
957 let cap_no_hotplug = PciExpressCapability::new(DevicePortType::RootPort, None);
959 assert!(
960 !cap_no_hotplug.pcie_capabilities.slot_implemented(),
961 "slot_implemented should be false when hotplug is not enabled"
962 );
963 }
964
965 #[test]
966 #[should_panic(expected = "Hotplug support is not valid for device port type Endpoint")]
967 fn test_pci_express_capability_with_hotplug_support_endpoint_panics() {
968 let cap = PciExpressCapability::new(DevicePortType::Endpoint, None);
969 cap.with_hotplug_support(1);
970 }
971
972 #[test]
973 #[should_panic(
974 expected = "Hotplug support is not valid for device port type UpstreamSwitchPort"
975 )]
976 fn test_pci_express_capability_with_hotplug_support_upstream_panics() {
977 let cap = PciExpressCapability::new(DevicePortType::UpstreamSwitchPort, None);
978 cap.with_hotplug_support(1);
979 }
980
981 #[test]
982 fn test_slot_control_write_protection() {
983 let mut cap = PciExpressCapability::new(DevicePortType::RootPort, None);
985 cap = cap.with_hotplug_support(1);
986
987 cap.slot_capabilities.set_attention_button_present(false);
989 cap.slot_capabilities.set_power_controller_present(false);
990 cap.slot_capabilities.set_mrl_sensor_present(false);
991 cap.slot_capabilities.set_attention_indicator_present(false);
992 cap.slot_capabilities.set_power_indicator_present(false);
993 cap.slot_capabilities
994 .set_electromechanical_interlock_present(false);
995 cap.slot_capabilities.set_no_command_completed_support(true);
996
997 let slot_ctl_sts_offset = 0x18; let val_to_write = 0xFFFFFFFF; cap.write_u32(slot_ctl_sts_offset, val_to_write);
1002
1003 let read_back = cap.read_u32(slot_ctl_sts_offset);
1005 let slot_control_value = read_back as u16;
1006 let slot_control = pci_express::SlotControl::from_bits(slot_control_value);
1007
1008 assert!(
1010 !slot_control.attention_button_pressed_enable(),
1011 "Attention button enable should be 0 when capability not present"
1012 );
1013 assert!(
1014 !slot_control.power_controller_control(),
1015 "Power controller control should be 0 when capability not present"
1016 );
1017 assert!(
1018 !slot_control.mrl_sensor_changed_enable(),
1019 "MRL sensor changed enable should be 0 when capability not present"
1020 );
1021 assert_eq!(
1022 slot_control.attention_indicator_control(),
1023 0,
1024 "Attention indicator control should be 0 when capability not present"
1025 );
1026 assert_eq!(
1027 slot_control.power_indicator_control(),
1028 0,
1029 "Power indicator control should be 0 when capability not present"
1030 );
1031 assert!(
1032 !slot_control.electromechanical_interlock_control(),
1033 "Electromechanical interlock control should be 0 when capability not present"
1034 );
1035 assert!(
1036 !slot_control.command_completed_interrupt_enable(),
1037 "Command completed interrupt enable should be 0 when no command completed support"
1038 );
1039
1040 assert!(
1042 slot_control.hot_plug_interrupt_enable(),
1043 "Hotplug interrupt enable should be settable when hotplug capable"
1044 );
1045 }
1046
1047 #[test]
1048 fn test_link_control_retrain_link_behavior() {
1049 let mut cap = PciExpressCapability::new(DevicePortType::RootPort, None);
1051
1052 let link_ctl_sts_offset = 0x10; let write_val = 0x0020; cap.write_u32(link_ctl_sts_offset, write_val);
1057
1058 let read_back = cap.read_u32(link_ctl_sts_offset);
1060 let link_control = pci_express::LinkControl::from_bits(read_back as u16);
1061
1062 assert!(
1063 !link_control.retrain_link(),
1064 "retrain_link should always read as 0"
1065 );
1066
1067 let write_val_2 = 0x0001; cap.write_u32(link_ctl_sts_offset, write_val_2);
1070
1071 let read_back_2 = cap.read_u32(link_ctl_sts_offset);
1072 let link_control_2 = pci_express::LinkControl::from_bits(read_back_2 as u16);
1073
1074 assert_eq!(
1075 link_control_2.aspm_control(),
1076 1,
1077 "Other control bits should be settable"
1078 );
1079 assert!(
1080 !link_control_2.retrain_link(),
1081 "retrain_link should still read as 0"
1082 );
1083 }
1084
1085 #[test]
1086 fn test_hotplug_link_capabilities() {
1087 let cap = PciExpressCapability::new(DevicePortType::RootPort, None);
1089 let cap_with_hotplug = cap.with_hotplug_support(1);
1090
1091 let link_caps_offset = 0x0C; let link_caps = cap_with_hotplug.read_u32(link_caps_offset);
1093 let link_capabilities = pci_express::LinkCapabilities::from_bits(link_caps);
1094
1095 assert!(
1097 link_capabilities.data_link_layer_link_active_reporting(),
1098 "Data Link Layer Link Active Reporting should be enabled for hotplug"
1099 );
1100
1101 assert_eq!(
1103 link_capabilities.max_link_speed(),
1104 LinkSpeed::Speed32_0GtS.into_bits(),
1105 "Max link speed should be Speed32_0GtS (PCIe 32.0 GT/s)"
1106 );
1107 assert_eq!(
1108 link_capabilities.max_link_width(),
1109 LinkWidth::X16.into_bits(),
1110 "Max link width should be X16 (x16)"
1111 );
1112
1113 let cap_no_hotplug = PciExpressCapability::new(DevicePortType::RootPort, None);
1115 let link_caps_no_hotplug = cap_no_hotplug.read_u32(link_caps_offset);
1116 let link_capabilities_no_hotplug =
1117 pci_express::LinkCapabilities::from_bits(link_caps_no_hotplug);
1118
1119 assert!(
1120 !link_capabilities_no_hotplug.data_link_layer_link_active_reporting(),
1121 "Data Link Layer Link Active Reporting should be disabled without hotplug"
1122 );
1123 }
1124
1125 #[test]
1126 fn test_link_status_read_only() {
1127 let mut cap = PciExpressCapability::new(DevicePortType::RootPort, None);
1129
1130 let link_ctl_sts_offset = 0x10; {
1134 let mut state = cap.state.lock();
1135 state.link_status.set_current_link_speed(0b0001); state.link_status.set_negotiated_link_width(0b000001); state.link_status.set_link_training(true); state.link_status.set_data_link_layer_link_active(true); }
1140
1141 let initial_read = cap.read_u32(link_ctl_sts_offset);
1143 let initial_link_status = pci_express::LinkStatus::from_bits((initial_read >> 16) as u16);
1144
1145 assert_eq!(
1147 initial_link_status.current_link_speed(),
1148 0b0001,
1149 "Initial link speed should be set"
1150 );
1151 assert_eq!(
1152 initial_link_status.negotiated_link_width(),
1153 0b000001,
1154 "Initial link width should be set"
1155 );
1156 assert!(
1157 initial_link_status.link_training(),
1158 "Initial link training should be active"
1159 );
1160 assert!(
1161 initial_link_status.data_link_layer_link_active(),
1162 "Initial DLL should be active"
1163 );
1164
1165 let write_val = 0xFFFF0001; cap.write_u32(link_ctl_sts_offset, write_val);
1168
1169 let after_write = cap.read_u32(link_ctl_sts_offset);
1171 let final_link_status = pci_express::LinkStatus::from_bits((after_write >> 16) as u16);
1172 let final_link_control = pci_express::LinkControl::from_bits(after_write as u16);
1173
1174 assert_eq!(
1176 final_link_status.current_link_speed(),
1177 initial_link_status.current_link_speed(),
1178 "Link Status current_link_speed should be read-only"
1179 );
1180 assert_eq!(
1181 final_link_status.negotiated_link_width(),
1182 initial_link_status.negotiated_link_width(),
1183 "Link Status negotiated_link_width should be read-only"
1184 );
1185 assert_eq!(
1186 final_link_status.link_training(),
1187 initial_link_status.link_training(),
1188 "Link Status link_training should be read-only"
1189 );
1190 assert_eq!(
1191 final_link_status.data_link_layer_link_active(),
1192 initial_link_status.data_link_layer_link_active(),
1193 "Link Status data_link_layer_link_active should be read-only"
1194 );
1195
1196 assert_eq!(
1198 final_link_control.aspm_control(),
1199 1,
1200 "Link Control should be writable"
1201 );
1202 }
1203
1204 #[test]
1205 fn test_slot_status_rw1c_behavior() {
1206 let mut cap = PciExpressCapability::new(DevicePortType::RootPort, None);
1208 cap = cap.with_hotplug_support(1);
1209
1210 let slot_ctl_sts_offset = 0x18; {
1214 let mut state = cap.state.lock();
1215 state.slot_status.set_attention_button_pressed(true);
1216 state.slot_status.set_power_fault_detected(true);
1217 state.slot_status.set_mrl_sensor_changed(true);
1218 state.slot_status.set_presence_detect_changed(true);
1219 state.slot_status.set_command_completed(true);
1220 state.slot_status.set_data_link_layer_state_changed(true);
1221 state.slot_status.set_mrl_sensor_state(1);
1223 state.slot_status.set_presence_detect_state(1);
1224 state.slot_status.set_electromechanical_interlock_status(1);
1225 }
1226
1227 let initial_read = cap.read_u32(slot_ctl_sts_offset);
1229 let initial_status = pci_express::SlotStatus::from_bits((initial_read >> 16) as u16);
1230 assert!(
1231 initial_status.attention_button_pressed(),
1232 "Initial attention button pressed should be set"
1233 );
1234 assert!(
1235 initial_status.power_fault_detected(),
1236 "Initial power fault detected should be set"
1237 );
1238 assert!(
1239 initial_status.mrl_sensor_changed(),
1240 "Initial MRL sensor changed should be set"
1241 );
1242 assert!(
1243 initial_status.presence_detect_changed(),
1244 "Initial presence detect changed should be set"
1245 );
1246 assert!(
1247 initial_status.command_completed(),
1248 "Initial command completed should be set"
1249 );
1250 assert!(
1251 initial_status.data_link_layer_state_changed(),
1252 "Initial data link layer state changed should be set"
1253 );
1254 assert_eq!(
1255 initial_status.mrl_sensor_state(),
1256 1,
1257 "Initial MRL sensor state should be set"
1258 );
1259 assert_eq!(
1260 initial_status.presence_detect_state(),
1261 1,
1262 "Initial presence detect state should be set"
1263 );
1264 assert_eq!(
1265 initial_status.electromechanical_interlock_status(),
1266 1,
1267 "Initial electromechanical interlock status should be set"
1268 );
1269
1270 let write_val = (0b0000_0001_0001_0001_u16 as u32) << 16; cap.write_u32(slot_ctl_sts_offset, write_val);
1275
1276 let after_write = cap.read_u32(slot_ctl_sts_offset);
1278 let final_status = pci_express::SlotStatus::from_bits((after_write >> 16) as u16);
1279
1280 assert!(
1282 !final_status.attention_button_pressed(),
1283 "Attention button pressed should be cleared after write-1"
1284 );
1285 assert!(
1286 !final_status.command_completed(),
1287 "Command completed should be cleared after write-1"
1288 );
1289 assert!(
1290 !final_status.data_link_layer_state_changed(),
1291 "Data link layer state changed should be cleared after write-1"
1292 );
1293
1294 assert!(
1296 final_status.power_fault_detected(),
1297 "Power fault detected should remain set (write-0)"
1298 );
1299 assert!(
1300 final_status.mrl_sensor_changed(),
1301 "MRL sensor changed should remain set (write-0)"
1302 );
1303 assert!(
1304 final_status.presence_detect_changed(),
1305 "Presence detect changed should remain set (write-0)"
1306 );
1307
1308 assert_eq!(
1310 final_status.mrl_sensor_state(),
1311 1,
1312 "MRL sensor state should remain unchanged (RO)"
1313 );
1314 assert_eq!(
1315 final_status.presence_detect_state(),
1316 1,
1317 "Presence detect state should remain unchanged (RO)"
1318 );
1319 assert_eq!(
1320 final_status.electromechanical_interlock_status(),
1321 1,
1322 "Electromechanical interlock status should remain unchanged (RO)"
1323 );
1324 }
1325
1326 #[test]
1327 fn test_link_control_2_target_speed_validation() {
1328 let mut cap = PciExpressCapability::new(DevicePortType::RootPort, None);
1330
1331 let link_ctl_sts_2_offset = 0x30; let initial_read = cap.read_u32(link_ctl_sts_2_offset);
1335 let initial_link_control_2 = pci_express::LinkControl2::from_bits(initial_read as u16);
1336 assert_eq!(
1337 initial_link_control_2.target_link_speed(),
1338 LinkSpeed::Speed32_0GtS.into_bits() as u16,
1339 "Initial target link speed should be Speed32_0GtS"
1340 );
1341
1342 let link_ctl_sts_offset = 0x10; let link_ctl_sts = cap.read_u32(link_ctl_sts_offset);
1345 let link_status = pci_express::LinkStatus::from_bits((link_ctl_sts >> 16) as u16);
1346 assert_eq!(
1347 link_status.current_link_speed(),
1348 LinkSpeed::Speed32_0GtS.into_bits() as u16,
1349 "Initial current link speed should match target speed"
1350 );
1351 assert_eq!(
1352 link_status.negotiated_link_width(),
1353 LinkWidth::X16.into_bits() as u16,
1354 "Initial negotiated link width should be X16"
1355 );
1356
1357 let valid_speed = LinkSpeed::Speed16_0GtS.into_bits() as u16; cap.write_u32(link_ctl_sts_2_offset, valid_speed as u32);
1360
1361 let after_valid_write = cap.read_u32(link_ctl_sts_2_offset);
1363 let link_control_2_after_valid =
1364 pci_express::LinkControl2::from_bits(after_valid_write as u16);
1365 assert_eq!(
1366 link_control_2_after_valid.target_link_speed(),
1367 valid_speed,
1368 "Target link speed should be set to requested valid speed"
1369 );
1370
1371 let link_ctl_sts_after_valid = cap.read_u32(link_ctl_sts_offset);
1373 let link_status_after_valid =
1374 pci_express::LinkStatus::from_bits((link_ctl_sts_after_valid >> 16) as u16);
1375 assert_eq!(
1376 link_status_after_valid.current_link_speed(),
1377 valid_speed,
1378 "Current link speed should be updated to match target speed"
1379 );
1380
1381 let invalid_speed = LinkSpeed::Speed64_0GtS.into_bits() as u16; cap.write_u32(link_ctl_sts_2_offset, invalid_speed as u32);
1384
1385 let after_invalid_write = cap.read_u32(link_ctl_sts_2_offset);
1387 let link_control_2_after_invalid =
1388 pci_express::LinkControl2::from_bits(after_invalid_write as u16);
1389 let max_speed = LinkSpeed::Speed32_0GtS.into_bits() as u16; assert_eq!(
1391 link_control_2_after_invalid.target_link_speed(),
1392 max_speed,
1393 "Target link speed should be clamped to max supported speed"
1394 );
1395
1396 let link_ctl_sts_after_invalid = cap.read_u32(link_ctl_sts_offset);
1398 let link_status_after_invalid =
1399 pci_express::LinkStatus::from_bits((link_ctl_sts_after_invalid >> 16) as u16);
1400 assert_eq!(
1401 link_status_after_invalid.current_link_speed(),
1402 max_speed,
1403 "Current link speed should be updated to clamped max speed"
1404 );
1405
1406 assert_eq!(
1408 link_status_after_valid.negotiated_link_width(),
1409 LinkWidth::X16.into_bits() as u16,
1410 "Negotiated link width should remain unchanged"
1411 );
1412 assert_eq!(
1413 link_status_after_invalid.negotiated_link_width(),
1414 LinkWidth::X16.into_bits() as u16,
1415 "Negotiated link width should remain unchanged"
1416 );
1417 }
1418
1419 #[test]
1420 fn test_with_hotplug_support_slot_number() {
1421 let cap1 = PciExpressCapability::new(DevicePortType::RootPort, None);
1425 let cap1_with_hotplug = cap1.with_hotplug_support(5);
1426
1427 assert!(cap1_with_hotplug.slot_capabilities.hot_plug_capable());
1428 assert_eq!(
1429 cap1_with_hotplug.slot_capabilities.physical_slot_number(),
1430 5
1431 );
1432
1433 let cap2 = PciExpressCapability::new(DevicePortType::DownstreamSwitchPort, None);
1435 let cap2_with_hotplug = cap2.with_hotplug_support(0);
1436
1437 assert!(cap2_with_hotplug.slot_capabilities.hot_plug_capable());
1438 assert_eq!(
1439 cap2_with_hotplug.slot_capabilities.physical_slot_number(),
1440 0
1441 );
1442
1443 let cap3 = PciExpressCapability::new(DevicePortType::RootPort, None);
1445 let cap3_with_hotplug = cap3.with_hotplug_support(255);
1446
1447 assert!(cap3_with_hotplug.slot_capabilities.hot_plug_capable());
1448 assert_eq!(
1449 cap3_with_hotplug.slot_capabilities.physical_slot_number(),
1450 255
1451 );
1452 }
1453
1454 #[test]
1455 fn test_slot_implemented_flag_in_pcie_capabilities_register() {
1456 let cap_no_hotplug = PciExpressCapability::new(DevicePortType::RootPort, None);
1461 let caps_val_no_hotplug = cap_no_hotplug.read_u32(0x00);
1462 let pcie_caps_no_hotplug = (caps_val_no_hotplug >> 16) as u16;
1463 let slot_implemented_bit = (pcie_caps_no_hotplug >> 8) & 0x1; assert_eq!(
1465 slot_implemented_bit, 0,
1466 "slot_implemented should be 0 when hotplug is not enabled"
1467 );
1468
1469 let cap_with_hotplug = cap_no_hotplug.with_hotplug_support(1);
1471 let caps_val_with_hotplug = cap_with_hotplug.read_u32(0x00);
1472 let pcie_caps_with_hotplug = (caps_val_with_hotplug >> 16) as u16;
1473 let slot_implemented_bit_hotplug = (pcie_caps_with_hotplug >> 8) & 0x1; assert_eq!(
1475 slot_implemented_bit_hotplug, 1,
1476 "slot_implemented should be 1 when hotplug is enabled"
1477 );
1478 }
1479
1480 #[test]
1481 fn test_set_presence_detect_state() {
1482 let cap = PciExpressCapability::new(DevicePortType::RootPort, None).with_hotplug_support(1);
1484
1485 let initial_slot_status = cap.read_u32(0x18); let initial_presence_detect = (initial_slot_status >> 22) & 0x1; assert_eq!(
1489 initial_presence_detect, 0,
1490 "Initial presence detect state should be 0"
1491 );
1492
1493 cap.set_presence_detect_state(true);
1495 let present_slot_status = cap.read_u32(0x18);
1496 let present_presence_detect = (present_slot_status >> 22) & 0x1;
1497 assert_eq!(
1498 present_presence_detect, 1,
1499 "Presence detect state should be 1 when device is present"
1500 );
1501
1502 cap.set_presence_detect_state(false);
1504 let absent_slot_status = cap.read_u32(0x18);
1505 let absent_presence_detect = (absent_slot_status >> 22) & 0x1;
1506 assert_eq!(
1507 absent_presence_detect, 0,
1508 "Presence detect state should be 0 when device is not present"
1509 );
1510 }
1511
1512 #[test]
1513 fn test_set_presence_detect_state_without_slot_implemented() {
1514 let cap = PciExpressCapability::new(DevicePortType::RootPort, None);
1516
1517 cap.set_presence_detect_state(true);
1519 cap.set_presence_detect_state(false);
1520 }
1521}