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
302 .slot_capabilities
303 .with_hot_plug_surprise(true)
304 .with_hot_plug_capable(true)
305 .with_physical_slot_number(slot_number);
306
307 self.link_capabilities = self
309 .link_capabilities
310 .with_data_link_layer_link_active_reporting(true);
311
312 self
313 }
314
315 pub fn set_presence_detect_state(&self, present: bool) {
324 if !self.pcie_capabilities.slot_implemented() {
325 return;
327 }
328
329 let mut state = self.state.lock();
330 state.slot_status =
331 state
332 .slot_status
333 .with_presence_detect_state(if present { 1 } else { 0 });
334 }
335}
336
337impl PciCapability for PciExpressCapability {
338 fn label(&self) -> &str {
339 "pci-express"
340 }
341
342 fn capability_id(&self) -> CapabilityId {
343 CapabilityId::PCI_EXPRESS
344 }
345
346 fn len(&self) -> usize {
347 0x3C
365 }
366
367 fn read_u32(&self, offset: u16) -> u32 {
368 let label = self.label();
369 match PciExpressCapabilityHeader(offset) {
370 PciExpressCapabilityHeader::PCIE_CAPS => {
371 (self.pcie_capabilities.into_bits() as u32) << 16
373 | CapabilityId::PCI_EXPRESS.0 as u32
374 }
375 PciExpressCapabilityHeader::DEVICE_CAPS => self.device_capabilities.into_bits(),
376 PciExpressCapabilityHeader::DEVICE_CTL_STS => {
377 let state = self.state.lock();
378 let device_control = state.device_control.into_bits() as u32;
379 let device_status = state.device_status.into_bits() as u32;
380 device_control | (device_status << 16)
381 }
382 PciExpressCapabilityHeader::LINK_CAPS => self.link_capabilities.into_bits(),
383 PciExpressCapabilityHeader::LINK_CTL_STS => {
384 let state = self.state.lock();
386 state.link_control.into_bits() as u32
387 | ((state.link_status.into_bits() as u32) << 16)
388 }
389 PciExpressCapabilityHeader::SLOT_CAPS => self.slot_capabilities.into_bits(),
390 PciExpressCapabilityHeader::SLOT_CTL_STS => {
391 let state = self.state.lock();
393 state.slot_control.into_bits() as u32
394 | ((state.slot_status.into_bits() as u32) << 16)
395 }
396 PciExpressCapabilityHeader::ROOT_CTL_CAPS => {
397 let state = self.state.lock();
399 state.root_control.into_bits() as u32
400 | ((self.root_capabilities.into_bits() as u32) << 16)
401 }
402 PciExpressCapabilityHeader::ROOT_STS => {
403 let state = self.state.lock();
405 state.root_status.into_bits()
406 }
407 PciExpressCapabilityHeader::DEVICE_CAPS_2 => self.device_capabilities_2.into_bits(),
408 PciExpressCapabilityHeader::DEVICE_CTL_STS_2 => {
409 let state = self.state.lock();
411 state.device_control_2.into_bits() as u32
412 | ((state.device_status_2.into_bits() as u32) << 16)
413 }
414 PciExpressCapabilityHeader::LINK_CAPS_2 => self.link_capabilities_2.into_bits(),
415 PciExpressCapabilityHeader::LINK_CTL_STS_2 => {
416 let state = self.state.lock();
418 state.link_control_2.into_bits() as u32
419 | ((state.link_status_2.into_bits() as u32) << 16)
420 }
421 PciExpressCapabilityHeader::SLOT_CAPS_2 => self.slot_capabilities_2.into_bits(),
422 PciExpressCapabilityHeader::SLOT_CTL_STS_2 => {
423 let state = self.state.lock();
425 state.slot_control_2.into_bits() as u32
426 | ((state.slot_status_2.into_bits() as u32) << 16)
427 }
428 _ => {
429 tracelimit::warn_ratelimited!(
430 ?label,
431 offset,
432 "unhandled pci express capability read"
433 );
434 0
435 }
436 }
437 }
438
439 fn write_u32(&mut self, offset: u16, val: u32) {
440 let label = self.label();
441 match PciExpressCapabilityHeader(offset) {
442 PciExpressCapabilityHeader::PCIE_CAPS => {
443 tracelimit::warn_ratelimited!(
445 ?label,
446 offset,
447 val,
448 "write to read-only pcie capabilities"
449 );
450 }
451 PciExpressCapabilityHeader::DEVICE_CAPS => {
452 tracelimit::warn_ratelimited!(
454 ?label,
455 offset,
456 val,
457 "write to read-only device capabilities"
458 );
459 }
460 PciExpressCapabilityHeader::DEVICE_CTL_STS => {
461 self.handle_device_control_status_write(val);
462 }
463 PciExpressCapabilityHeader::LINK_CAPS => {
464 tracelimit::warn_ratelimited!(
466 ?label,
467 offset,
468 val,
469 "write to read-only link capabilities"
470 );
471 }
472 PciExpressCapabilityHeader::LINK_CTL_STS => {
473 self.handle_link_control_status_write(val);
474 }
475 PciExpressCapabilityHeader::SLOT_CAPS => {
476 tracelimit::warn_ratelimited!(
478 ?label,
479 offset,
480 val,
481 "write to read-only slot capabilities"
482 );
483 }
484 PciExpressCapabilityHeader::SLOT_CTL_STS => {
485 self.handle_slot_control_status_write(val);
486 }
487 PciExpressCapabilityHeader::ROOT_CTL_CAPS => {
488 let mut state = self.state.lock();
490 state.root_control = pci_express::RootControl::from_bits(val as u16);
491 }
493 PciExpressCapabilityHeader::ROOT_STS => {
494 let mut state = self.state.lock();
496 state.root_status = pci_express::RootStatus::from_bits(val);
498 }
499 PciExpressCapabilityHeader::DEVICE_CAPS_2 => {
500 tracelimit::warn_ratelimited!(
502 ?label,
503 offset,
504 val,
505 "write to read-only device capabilities 2"
506 );
507 }
508 PciExpressCapabilityHeader::DEVICE_CTL_STS_2 => {
509 let mut state = self.state.lock();
511 state.device_control_2 = pci_express::DeviceControl2::from_bits(val as u16);
512 state.device_status_2 = pci_express::DeviceStatus2::from_bits((val >> 16) as u16);
514 }
515 PciExpressCapabilityHeader::LINK_CAPS_2 => {
516 tracelimit::warn_ratelimited!(
518 ?label,
519 offset,
520 val,
521 "write to read-only link capabilities 2"
522 );
523 }
524 PciExpressCapabilityHeader::LINK_CTL_STS_2 => {
525 self.handle_link_control_2_write(val);
526 }
527 PciExpressCapabilityHeader::SLOT_CAPS_2 => {
528 tracelimit::warn_ratelimited!(
530 ?label,
531 offset,
532 val,
533 "write to read-only slot capabilities 2"
534 );
535 }
536 PciExpressCapabilityHeader::SLOT_CTL_STS_2 => {
537 let mut state = self.state.lock();
539 state.slot_control_2 = pci_express::SlotControl2::from_bits(val as u16);
540 state.slot_status_2 = pci_express::SlotStatus2::from_bits((val >> 16) as u16);
542 }
543 _ => {
544 tracelimit::warn_ratelimited!(
545 ?label,
546 offset,
547 val,
548 "unhandled pci express capability write"
549 );
550 }
551 }
552 }
553
554 fn reset(&mut self) {
555 let mut state = self.state.lock();
556 *state = PciExpressState::new();
557 }
558
559 fn as_pci_express(&self) -> Option<&PciExpressCapability> {
560 Some(self)
561 }
562
563 fn as_pci_express_mut(&mut self) -> Option<&mut PciExpressCapability> {
564 Some(self)
565 }
566}
567
568mod save_restore {
569 use super::*;
570 use vmcore::save_restore::RestoreError;
571 use vmcore::save_restore::SaveError;
572 use vmcore::save_restore::SaveRestore;
573
574 mod state {
575 use mesh::payload::Protobuf;
576 use vmcore::save_restore::SavedStateRoot;
577
578 #[derive(Protobuf, SavedStateRoot)]
579 #[mesh(package = "pci.capabilities.pci_express")]
580 pub struct SavedState {
581 #[mesh(1)]
582 pub device_control: u16,
583 #[mesh(2)]
584 pub device_status: u16,
585 #[mesh(3)]
586 pub flr_handler: u16,
587 }
588 }
589
590 impl SaveRestore for PciExpressCapability {
591 type SavedState = state::SavedState;
592
593 fn save(&mut self) -> Result<Self::SavedState, SaveError> {
594 Err(SaveError::NotSupported)
595 }
596
597 fn restore(&mut self, _: Self::SavedState) -> Result<(), RestoreError> {
598 Err(RestoreError::SavedStateNotSupported)
599 }
600 }
601}
602
603#[cfg(test)]
604mod tests {
605 use super::*;
606 use crate::spec::caps::pci_express::DevicePortType;
607 use std::sync::atomic::{AtomicBool, Ordering};
608
609 #[derive(Debug)]
610 struct TestFlrHandler {
611 flr_initiated: AtomicBool,
612 }
613
614 impl TestFlrHandler {
615 fn new() -> Arc<Self> {
616 Arc::new(Self {
617 flr_initiated: AtomicBool::new(false),
618 })
619 }
620
621 fn was_flr_initiated(&self) -> bool {
622 self.flr_initiated.load(Ordering::Acquire)
623 }
624
625 fn reset(&self) {
626 self.flr_initiated.store(false, Ordering::Release);
627 }
628 }
629
630 impl FlrHandler for TestFlrHandler {
631 fn initiate_flr(&self) {
632 self.flr_initiated.store(true, Ordering::Release);
633 }
634 }
635
636 impl Inspect for TestFlrHandler {
637 fn inspect(&self, req: inspect::Request<'_>) {
638 req.respond()
639 .field("flr_initiated", self.flr_initiated.load(Ordering::Acquire));
640 }
641 }
642
643 #[test]
644 fn test_pci_express_capability_read_u32_endpoint() {
645 let flr_handler = TestFlrHandler::new();
646 let cap = PciExpressCapability::new(DevicePortType::Endpoint, Some(flr_handler));
647
648 let caps_val = cap.read_u32(0x00);
650 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);
656 assert_eq!(
657 device_caps_val & PCI_EXPRESS_DEVICE_CAPS_FLR_BIT_MASK,
658 PCI_EXPRESS_DEVICE_CAPS_FLR_BIT_MASK
659 ); let device_ctl_sts_val = cap.read_u32(0x08);
663 assert_eq!(device_ctl_sts_val, 0); let link_ctl_sts_val = cap.read_u32(0x10);
667 let expected_link_status = (LinkSpeed::Speed32_0GtS.into_bits() as u16)
668 | ((LinkWidth::X16.into_bits() as u16) << 4); assert_eq!(link_ctl_sts_val, (expected_link_status as u32) << 16); }
671
672 #[test]
673 fn test_pci_express_capability_read_u32_root_port() {
674 let cap = PciExpressCapability::new(DevicePortType::RootPort, None);
675
676 let caps_val = cap.read_u32(0x00);
678 assert_eq!(caps_val & 0xFF, 0x10); assert_eq!((caps_val >> 8) & 0xFF, 0x00); assert_eq!((caps_val >> 16) & 0xFFFF, 0x0042); }
682
683 #[test]
684 fn test_pci_express_capability_read_u32_no_flr() {
685 let cap = PciExpressCapability::new(DevicePortType::Endpoint, None);
686
687 let device_caps_val = cap.read_u32(0x04);
689 assert_eq!(device_caps_val & PCI_EXPRESS_DEVICE_CAPS_FLR_BIT_MASK, 0);
690 }
691
692 #[test]
693 fn test_pci_express_capability_write_u32_readonly_registers() {
694 let mut cap = PciExpressCapability::new(DevicePortType::Endpoint, None);
695
696 let original_caps = cap.read_u32(0x00);
698 cap.write_u32(0x00, 0xFFFFFFFF);
699 assert_eq!(cap.read_u32(0x00), original_caps); let original_device_caps = cap.read_u32(0x04);
703 cap.write_u32(0x04, 0xFFFFFFFF);
704 assert_eq!(cap.read_u32(0x04), original_device_caps); }
706
707 #[test]
708 fn test_pci_express_capability_write_u32_device_control() {
709 let flr_handler = TestFlrHandler::new();
710 let mut cap =
711 PciExpressCapability::new(DevicePortType::Endpoint, Some(flr_handler.clone()));
712
713 let initial_ctl_sts = cap.read_u32(0x08);
715 assert_eq!(initial_ctl_sts & 0xFFFF, 0); cap.write_u32(0x08, 0x0001); let device_ctl_sts = cap.read_u32(0x08);
721 assert_eq!(device_ctl_sts & 0xFFFF, 0x0001); assert!(!flr_handler.was_flr_initiated()); flr_handler.reset();
726 cap.write_u32(0x08, 0x8001); let device_ctl_sts_after_flr = cap.read_u32(0x08);
728 assert_eq!(device_ctl_sts_after_flr & 0xFFFF, 0x0001); assert!(flr_handler.was_flr_initiated()); flr_handler.reset();
733 cap.write_u32(0x08, 0x8000); let device_ctl_sts_final = cap.read_u32(0x08);
737 assert_eq!(device_ctl_sts_final & 0xFFFF, 0x0000); assert!(flr_handler.was_flr_initiated()); }
740
741 #[test]
742 fn test_pci_express_capability_write_u32_device_status() {
743 let mut cap = PciExpressCapability::new(DevicePortType::Endpoint, None);
744
745 {
747 let mut state = cap.state.lock();
748 state.device_status.set_correctable_error_detected(true);
749 state.device_status.set_non_fatal_error_detected(true);
750 state.device_status.set_fatal_error_detected(true);
751 state.device_status.set_unsupported_request_detected(true);
752 }
753
754 let device_ctl_sts = cap.read_u32(0x08);
756 let status_bits = (device_ctl_sts >> 16) & 0xFFFF;
757 assert_ne!(status_bits & 0x0F, 0); cap.write_u32(0x08, 0x00010000); let device_ctl_sts_after = cap.read_u32(0x08);
762 let status_bits_after = (device_ctl_sts_after >> 16) & 0xFFFF;
763 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;
769 assert_eq!(final_status & 0x0F, 0); }
771
772 #[test]
773 fn test_pci_express_capability_write_u32_unhandled_offset() {
774 let mut cap = PciExpressCapability::new(DevicePortType::Endpoint, None);
775
776 cap.write_u32(0x10, 0xFFFFFFFF);
778 assert_eq!(cap.read_u32(0x08), 0); }
781
782 #[test]
783 fn test_pci_express_capability_reset() {
784 let flr_handler = TestFlrHandler::new();
785 let mut cap =
786 PciExpressCapability::new(DevicePortType::Endpoint, Some(flr_handler.clone()));
787
788 cap.write_u32(0x08, 0x0001); {
793 let mut state = cap.state.lock();
794 state.device_status.set_correctable_error_detected(true);
795 }
796
797 let device_ctl_sts = cap.read_u32(0x08);
799 assert_ne!(device_ctl_sts, 0);
800
801 cap.reset();
803
804 let device_ctl_sts_after_reset = cap.read_u32(0x08);
806 assert_eq!(device_ctl_sts_after_reset, 0);
807 }
808
809 #[test]
810 fn test_pci_express_capability_extended_registers() {
811 let cap = PciExpressCapability::new(DevicePortType::Endpoint, None);
812
813 let expected_link_caps =
816 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)
820 | ((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); }
837
838 #[test]
839 fn test_pci_express_capability_length() {
840 let cap = PciExpressCapability::new(DevicePortType::Endpoint, None);
841 assert_eq!(cap.len(), 0x3C); }
843
844 #[test]
845 fn test_pci_express_capability_label() {
846 let cap = PciExpressCapability::new(DevicePortType::Endpoint, None);
847 assert_eq!(cap.label(), "pci-express");
848 }
849
850 #[test]
851 fn test_pci_express_capability_with_hotplug_support() {
852 let cap = PciExpressCapability::new(DevicePortType::RootPort, None);
854 let cap_with_hotplug = cap.with_hotplug_support(1);
855
856 assert_eq!(cap_with_hotplug.label(), "pci-express");
858 assert_eq!(cap_with_hotplug.len(), 0x3C);
859
860 assert!(cap_with_hotplug.slot_capabilities.hot_plug_surprise());
862 assert!(cap_with_hotplug.slot_capabilities.hot_plug_capable());
863 assert_eq!(cap_with_hotplug.slot_capabilities.physical_slot_number(), 1);
864
865 assert!(
867 cap_with_hotplug.pcie_capabilities.slot_implemented(),
868 "slot_implemented should be true when hotplug is enabled"
869 );
870
871 let cap2 = PciExpressCapability::new(DevicePortType::DownstreamSwitchPort, None);
873 let cap2_with_hotplug = cap2.with_hotplug_support(2);
874
875 assert!(cap2_with_hotplug.slot_capabilities.hot_plug_surprise());
876 assert!(cap2_with_hotplug.slot_capabilities.hot_plug_capable());
877 assert_eq!(
878 cap2_with_hotplug.slot_capabilities.physical_slot_number(),
879 2
880 );
881
882 assert!(
884 cap2_with_hotplug.pcie_capabilities.slot_implemented(),
885 "slot_implemented should be true when hotplug is enabled"
886 );
887
888 let cap_no_hotplug = PciExpressCapability::new(DevicePortType::RootPort, None);
890 assert!(
891 !cap_no_hotplug.pcie_capabilities.slot_implemented(),
892 "slot_implemented should be false when hotplug is not enabled"
893 );
894 }
895
896 #[test]
897 #[should_panic(expected = "Hotplug support is not valid for device port type Endpoint")]
898 fn test_pci_express_capability_with_hotplug_support_endpoint_panics() {
899 let cap = PciExpressCapability::new(DevicePortType::Endpoint, None);
900 cap.with_hotplug_support(1);
901 }
902
903 #[test]
904 #[should_panic(
905 expected = "Hotplug support is not valid for device port type UpstreamSwitchPort"
906 )]
907 fn test_pci_express_capability_with_hotplug_support_upstream_panics() {
908 let cap = PciExpressCapability::new(DevicePortType::UpstreamSwitchPort, None);
909 cap.with_hotplug_support(1);
910 }
911
912 #[test]
913 fn test_slot_control_write_protection() {
914 let mut cap = PciExpressCapability::new(DevicePortType::RootPort, None);
916 cap = cap.with_hotplug_support(1);
917
918 cap.slot_capabilities.set_attention_button_present(false);
920 cap.slot_capabilities.set_power_controller_present(false);
921 cap.slot_capabilities.set_mrl_sensor_present(false);
922 cap.slot_capabilities.set_attention_indicator_present(false);
923 cap.slot_capabilities.set_power_indicator_present(false);
924 cap.slot_capabilities
925 .set_electromechanical_interlock_present(false);
926 cap.slot_capabilities.set_no_command_completed_support(true);
927
928 let slot_ctl_sts_offset = 0x18; let val_to_write = 0xFFFFFFFF; cap.write_u32(slot_ctl_sts_offset, val_to_write);
933
934 let read_back = cap.read_u32(slot_ctl_sts_offset);
936 let slot_control_value = read_back as u16;
937 let slot_control = pci_express::SlotControl::from_bits(slot_control_value);
938
939 assert!(
941 !slot_control.attention_button_pressed_enable(),
942 "Attention button enable should be 0 when capability not present"
943 );
944 assert!(
945 !slot_control.power_controller_control(),
946 "Power controller control should be 0 when capability not present"
947 );
948 assert!(
949 !slot_control.mrl_sensor_changed_enable(),
950 "MRL sensor changed enable should be 0 when capability not present"
951 );
952 assert_eq!(
953 slot_control.attention_indicator_control(),
954 0,
955 "Attention indicator control should be 0 when capability not present"
956 );
957 assert_eq!(
958 slot_control.power_indicator_control(),
959 0,
960 "Power indicator control should be 0 when capability not present"
961 );
962 assert!(
963 !slot_control.electromechanical_interlock_control(),
964 "Electromechanical interlock control should be 0 when capability not present"
965 );
966 assert!(
967 !slot_control.command_completed_interrupt_enable(),
968 "Command completed interrupt enable should be 0 when no command completed support"
969 );
970
971 assert!(
973 slot_control.hot_plug_interrupt_enable(),
974 "Hotplug interrupt enable should be settable when hotplug capable"
975 );
976 }
977
978 #[test]
979 fn test_link_control_retrain_link_behavior() {
980 let mut cap = PciExpressCapability::new(DevicePortType::RootPort, None);
982
983 let link_ctl_sts_offset = 0x10; let write_val = 0x0020; cap.write_u32(link_ctl_sts_offset, write_val);
988
989 let read_back = cap.read_u32(link_ctl_sts_offset);
991 let link_control = pci_express::LinkControl::from_bits(read_back as u16);
992
993 assert!(
994 !link_control.retrain_link(),
995 "retrain_link should always read as 0"
996 );
997
998 let write_val_2 = 0x0001; cap.write_u32(link_ctl_sts_offset, write_val_2);
1001
1002 let read_back_2 = cap.read_u32(link_ctl_sts_offset);
1003 let link_control_2 = pci_express::LinkControl::from_bits(read_back_2 as u16);
1004
1005 assert_eq!(
1006 link_control_2.aspm_control(),
1007 1,
1008 "Other control bits should be settable"
1009 );
1010 assert!(
1011 !link_control_2.retrain_link(),
1012 "retrain_link should still read as 0"
1013 );
1014 }
1015
1016 #[test]
1017 fn test_hotplug_link_capabilities() {
1018 let cap = PciExpressCapability::new(DevicePortType::RootPort, None);
1020 let cap_with_hotplug = cap.with_hotplug_support(1);
1021
1022 let link_caps_offset = 0x0C; let link_caps = cap_with_hotplug.read_u32(link_caps_offset);
1024 let link_capabilities = pci_express::LinkCapabilities::from_bits(link_caps);
1025
1026 assert!(
1028 link_capabilities.data_link_layer_link_active_reporting(),
1029 "Data Link Layer Link Active Reporting should be enabled for hotplug"
1030 );
1031
1032 assert_eq!(
1034 link_capabilities.max_link_speed(),
1035 LinkSpeed::Speed32_0GtS.into_bits(),
1036 "Max link speed should be Speed32_0GtS (PCIe 32.0 GT/s)"
1037 );
1038 assert_eq!(
1039 link_capabilities.max_link_width(),
1040 LinkWidth::X16.into_bits(),
1041 "Max link width should be X16 (x16)"
1042 );
1043
1044 let cap_no_hotplug = PciExpressCapability::new(DevicePortType::RootPort, None);
1046 let link_caps_no_hotplug = cap_no_hotplug.read_u32(link_caps_offset);
1047 let link_capabilities_no_hotplug =
1048 pci_express::LinkCapabilities::from_bits(link_caps_no_hotplug);
1049
1050 assert!(
1051 !link_capabilities_no_hotplug.data_link_layer_link_active_reporting(),
1052 "Data Link Layer Link Active Reporting should be disabled without hotplug"
1053 );
1054 }
1055
1056 #[test]
1057 fn test_link_status_read_only() {
1058 let mut cap = PciExpressCapability::new(DevicePortType::RootPort, None);
1060
1061 let link_ctl_sts_offset = 0x10; {
1065 let mut state = cap.state.lock();
1066 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); }
1071
1072 let initial_read = cap.read_u32(link_ctl_sts_offset);
1074 let initial_link_status = pci_express::LinkStatus::from_bits((initial_read >> 16) as u16);
1075
1076 assert_eq!(
1078 initial_link_status.current_link_speed(),
1079 0b0001,
1080 "Initial link speed should be set"
1081 );
1082 assert_eq!(
1083 initial_link_status.negotiated_link_width(),
1084 0b000001,
1085 "Initial link width should be set"
1086 );
1087 assert!(
1088 initial_link_status.link_training(),
1089 "Initial link training should be active"
1090 );
1091 assert!(
1092 initial_link_status.data_link_layer_link_active(),
1093 "Initial DLL should be active"
1094 );
1095
1096 let write_val = 0xFFFF0001; cap.write_u32(link_ctl_sts_offset, write_val);
1099
1100 let after_write = cap.read_u32(link_ctl_sts_offset);
1102 let final_link_status = pci_express::LinkStatus::from_bits((after_write >> 16) as u16);
1103 let final_link_control = pci_express::LinkControl::from_bits(after_write as u16);
1104
1105 assert_eq!(
1107 final_link_status.current_link_speed(),
1108 initial_link_status.current_link_speed(),
1109 "Link Status current_link_speed should be read-only"
1110 );
1111 assert_eq!(
1112 final_link_status.negotiated_link_width(),
1113 initial_link_status.negotiated_link_width(),
1114 "Link Status negotiated_link_width should be read-only"
1115 );
1116 assert_eq!(
1117 final_link_status.link_training(),
1118 initial_link_status.link_training(),
1119 "Link Status link_training should be read-only"
1120 );
1121 assert_eq!(
1122 final_link_status.data_link_layer_link_active(),
1123 initial_link_status.data_link_layer_link_active(),
1124 "Link Status data_link_layer_link_active should be read-only"
1125 );
1126
1127 assert_eq!(
1129 final_link_control.aspm_control(),
1130 1,
1131 "Link Control should be writable"
1132 );
1133 }
1134
1135 #[test]
1136 fn test_slot_status_rw1c_behavior() {
1137 let mut cap = PciExpressCapability::new(DevicePortType::RootPort, None);
1139 cap = cap.with_hotplug_support(1);
1140
1141 let slot_ctl_sts_offset = 0x18; {
1145 let mut state = cap.state.lock();
1146 state.slot_status.set_attention_button_pressed(true);
1147 state.slot_status.set_power_fault_detected(true);
1148 state.slot_status.set_mrl_sensor_changed(true);
1149 state.slot_status.set_presence_detect_changed(true);
1150 state.slot_status.set_command_completed(true);
1151 state.slot_status.set_data_link_layer_state_changed(true);
1152 state.slot_status.set_mrl_sensor_state(1);
1154 state.slot_status.set_presence_detect_state(1);
1155 state.slot_status.set_electromechanical_interlock_status(1);
1156 }
1157
1158 let initial_read = cap.read_u32(slot_ctl_sts_offset);
1160 let initial_status = pci_express::SlotStatus::from_bits((initial_read >> 16) as u16);
1161 assert!(
1162 initial_status.attention_button_pressed(),
1163 "Initial attention button pressed should be set"
1164 );
1165 assert!(
1166 initial_status.power_fault_detected(),
1167 "Initial power fault detected should be set"
1168 );
1169 assert!(
1170 initial_status.mrl_sensor_changed(),
1171 "Initial MRL sensor changed should be set"
1172 );
1173 assert!(
1174 initial_status.presence_detect_changed(),
1175 "Initial presence detect changed should be set"
1176 );
1177 assert!(
1178 initial_status.command_completed(),
1179 "Initial command completed should be set"
1180 );
1181 assert!(
1182 initial_status.data_link_layer_state_changed(),
1183 "Initial data link layer state changed should be set"
1184 );
1185 assert_eq!(
1186 initial_status.mrl_sensor_state(),
1187 1,
1188 "Initial MRL sensor state should be set"
1189 );
1190 assert_eq!(
1191 initial_status.presence_detect_state(),
1192 1,
1193 "Initial presence detect state should be set"
1194 );
1195 assert_eq!(
1196 initial_status.electromechanical_interlock_status(),
1197 1,
1198 "Initial electromechanical interlock status should be set"
1199 );
1200
1201 let write_val = (0b0000_0001_0001_0001_u16 as u32) << 16; cap.write_u32(slot_ctl_sts_offset, write_val);
1206
1207 let after_write = cap.read_u32(slot_ctl_sts_offset);
1209 let final_status = pci_express::SlotStatus::from_bits((after_write >> 16) as u16);
1210
1211 assert!(
1213 !final_status.attention_button_pressed(),
1214 "Attention button pressed should be cleared after write-1"
1215 );
1216 assert!(
1217 !final_status.command_completed(),
1218 "Command completed should be cleared after write-1"
1219 );
1220 assert!(
1221 !final_status.data_link_layer_state_changed(),
1222 "Data link layer state changed should be cleared after write-1"
1223 );
1224
1225 assert!(
1227 final_status.power_fault_detected(),
1228 "Power fault detected should remain set (write-0)"
1229 );
1230 assert!(
1231 final_status.mrl_sensor_changed(),
1232 "MRL sensor changed should remain set (write-0)"
1233 );
1234 assert!(
1235 final_status.presence_detect_changed(),
1236 "Presence detect changed should remain set (write-0)"
1237 );
1238
1239 assert_eq!(
1241 final_status.mrl_sensor_state(),
1242 1,
1243 "MRL sensor state should remain unchanged (RO)"
1244 );
1245 assert_eq!(
1246 final_status.presence_detect_state(),
1247 1,
1248 "Presence detect state should remain unchanged (RO)"
1249 );
1250 assert_eq!(
1251 final_status.electromechanical_interlock_status(),
1252 1,
1253 "Electromechanical interlock status should remain unchanged (RO)"
1254 );
1255 }
1256
1257 #[test]
1258 fn test_link_control_2_target_speed_validation() {
1259 let mut cap = PciExpressCapability::new(DevicePortType::RootPort, None);
1261
1262 let link_ctl_sts_2_offset = 0x30; let initial_read = cap.read_u32(link_ctl_sts_2_offset);
1266 let initial_link_control_2 = pci_express::LinkControl2::from_bits(initial_read as u16);
1267 assert_eq!(
1268 initial_link_control_2.target_link_speed(),
1269 LinkSpeed::Speed32_0GtS.into_bits() as u16,
1270 "Initial target link speed should be Speed32_0GtS"
1271 );
1272
1273 let link_ctl_sts_offset = 0x10; let link_ctl_sts = cap.read_u32(link_ctl_sts_offset);
1276 let link_status = pci_express::LinkStatus::from_bits((link_ctl_sts >> 16) as u16);
1277 assert_eq!(
1278 link_status.current_link_speed(),
1279 LinkSpeed::Speed32_0GtS.into_bits() as u16,
1280 "Initial current link speed should match target speed"
1281 );
1282 assert_eq!(
1283 link_status.negotiated_link_width(),
1284 LinkWidth::X16.into_bits() as u16,
1285 "Initial negotiated link width should be X16"
1286 );
1287
1288 let valid_speed = LinkSpeed::Speed16_0GtS.into_bits() as u16; cap.write_u32(link_ctl_sts_2_offset, valid_speed as u32);
1291
1292 let after_valid_write = cap.read_u32(link_ctl_sts_2_offset);
1294 let link_control_2_after_valid =
1295 pci_express::LinkControl2::from_bits(after_valid_write as u16);
1296 assert_eq!(
1297 link_control_2_after_valid.target_link_speed(),
1298 valid_speed,
1299 "Target link speed should be set to requested valid speed"
1300 );
1301
1302 let link_ctl_sts_after_valid = cap.read_u32(link_ctl_sts_offset);
1304 let link_status_after_valid =
1305 pci_express::LinkStatus::from_bits((link_ctl_sts_after_valid >> 16) as u16);
1306 assert_eq!(
1307 link_status_after_valid.current_link_speed(),
1308 valid_speed,
1309 "Current link speed should be updated to match target speed"
1310 );
1311
1312 let invalid_speed = LinkSpeed::Speed64_0GtS.into_bits() as u16; cap.write_u32(link_ctl_sts_2_offset, invalid_speed as u32);
1315
1316 let after_invalid_write = cap.read_u32(link_ctl_sts_2_offset);
1318 let link_control_2_after_invalid =
1319 pci_express::LinkControl2::from_bits(after_invalid_write as u16);
1320 let max_speed = LinkSpeed::Speed32_0GtS.into_bits() as u16; assert_eq!(
1322 link_control_2_after_invalid.target_link_speed(),
1323 max_speed,
1324 "Target link speed should be clamped to max supported speed"
1325 );
1326
1327 let link_ctl_sts_after_invalid = cap.read_u32(link_ctl_sts_offset);
1329 let link_status_after_invalid =
1330 pci_express::LinkStatus::from_bits((link_ctl_sts_after_invalid >> 16) as u16);
1331 assert_eq!(
1332 link_status_after_invalid.current_link_speed(),
1333 max_speed,
1334 "Current link speed should be updated to clamped max speed"
1335 );
1336
1337 assert_eq!(
1339 link_status_after_valid.negotiated_link_width(),
1340 LinkWidth::X16.into_bits() as u16,
1341 "Negotiated link width should remain unchanged"
1342 );
1343 assert_eq!(
1344 link_status_after_invalid.negotiated_link_width(),
1345 LinkWidth::X16.into_bits() as u16,
1346 "Negotiated link width should remain unchanged"
1347 );
1348 }
1349
1350 #[test]
1351 fn test_with_hotplug_support_slot_number() {
1352 let cap1 = PciExpressCapability::new(DevicePortType::RootPort, None);
1356 let cap1_with_hotplug = cap1.with_hotplug_support(5);
1357
1358 assert!(cap1_with_hotplug.slot_capabilities.hot_plug_capable());
1359 assert_eq!(
1360 cap1_with_hotplug.slot_capabilities.physical_slot_number(),
1361 5
1362 );
1363
1364 let cap2 = PciExpressCapability::new(DevicePortType::DownstreamSwitchPort, None);
1366 let cap2_with_hotplug = cap2.with_hotplug_support(0);
1367
1368 assert!(cap2_with_hotplug.slot_capabilities.hot_plug_capable());
1369 assert_eq!(
1370 cap2_with_hotplug.slot_capabilities.physical_slot_number(),
1371 0
1372 );
1373
1374 let cap3 = PciExpressCapability::new(DevicePortType::RootPort, None);
1376 let cap3_with_hotplug = cap3.with_hotplug_support(255);
1377
1378 assert!(cap3_with_hotplug.slot_capabilities.hot_plug_capable());
1379 assert_eq!(
1380 cap3_with_hotplug.slot_capabilities.physical_slot_number(),
1381 255
1382 );
1383 }
1384
1385 #[test]
1386 fn test_slot_implemented_flag_in_pcie_capabilities_register() {
1387 let cap_no_hotplug = PciExpressCapability::new(DevicePortType::RootPort, None);
1392 let caps_val_no_hotplug = cap_no_hotplug.read_u32(0x00);
1393 let pcie_caps_no_hotplug = (caps_val_no_hotplug >> 16) as u16;
1394 let slot_implemented_bit = (pcie_caps_no_hotplug >> 8) & 0x1; assert_eq!(
1396 slot_implemented_bit, 0,
1397 "slot_implemented should be 0 when hotplug is not enabled"
1398 );
1399
1400 let cap_with_hotplug = cap_no_hotplug.with_hotplug_support(1);
1402 let caps_val_with_hotplug = cap_with_hotplug.read_u32(0x00);
1403 let pcie_caps_with_hotplug = (caps_val_with_hotplug >> 16) as u16;
1404 let slot_implemented_bit_hotplug = (pcie_caps_with_hotplug >> 8) & 0x1; assert_eq!(
1406 slot_implemented_bit_hotplug, 1,
1407 "slot_implemented should be 1 when hotplug is enabled"
1408 );
1409 }
1410
1411 #[test]
1412 fn test_set_presence_detect_state() {
1413 let cap = PciExpressCapability::new(DevicePortType::RootPort, None).with_hotplug_support(1);
1415
1416 let initial_slot_status = cap.read_u32(0x18); let initial_presence_detect = (initial_slot_status >> 22) & 0x1; assert_eq!(
1420 initial_presence_detect, 0,
1421 "Initial presence detect state should be 0"
1422 );
1423
1424 cap.set_presence_detect_state(true);
1426 let present_slot_status = cap.read_u32(0x18);
1427 let present_presence_detect = (present_slot_status >> 22) & 0x1;
1428 assert_eq!(
1429 present_presence_detect, 1,
1430 "Presence detect state should be 1 when device is present"
1431 );
1432
1433 cap.set_presence_detect_state(false);
1435 let absent_slot_status = cap.read_u32(0x18);
1436 let absent_presence_detect = (absent_slot_status >> 22) & 0x1;
1437 assert_eq!(
1438 absent_presence_detect, 0,
1439 "Presence detect state should be 0 when device is not present"
1440 );
1441 }
1442
1443 #[test]
1444 fn test_set_presence_detect_state_without_slot_implemented() {
1445 let cap = PciExpressCapability::new(DevicePortType::RootPort, None);
1447
1448 cap.set_presence_detect_state(true);
1450 cap.set_presence_detect_state(false);
1451 }
1452}