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 link_control: u16,
656 #[mesh(4)]
657 pub link_status: u16,
658 #[mesh(5)]
659 pub slot_control: u16,
660 #[mesh(6)]
661 pub slot_status: u16,
662 #[mesh(7)]
663 pub root_control: u16,
664 #[mesh(8)]
665 pub root_status: u32,
666 #[mesh(9)]
667 pub device_control_2: u16,
668 #[mesh(10)]
669 pub device_status_2: u16,
670 #[mesh(11)]
671 pub link_control_2: u16,
672 #[mesh(12)]
673 pub link_status_2: u16,
674 #[mesh(13)]
675 pub slot_control_2: u16,
676 #[mesh(14)]
677 pub slot_status_2: u16,
678 }
679 }
680
681 impl SaveRestore for PciExpressCapability {
682 type SavedState = state::SavedState;
683
684 fn save(&mut self) -> Result<Self::SavedState, SaveError> {
685 let state = self.state.lock();
686 Ok(state::SavedState {
687 device_control: state.device_control.into_bits(),
688 device_status: state.device_status.into_bits(),
689 link_control: state.link_control.into_bits(),
690 link_status: state.link_status.into_bits(),
691 slot_control: state.slot_control.into_bits(),
692 slot_status: state.slot_status.into_bits(),
693 root_control: state.root_control.into_bits(),
694 root_status: state.root_status.into_bits(),
695 device_control_2: state.device_control_2.into_bits(),
696 device_status_2: state.device_status_2.into_bits(),
697 link_control_2: state.link_control_2.into_bits(),
698 link_status_2: state.link_status_2.into_bits(),
699 slot_control_2: state.slot_control_2.into_bits(),
700 slot_status_2: state.slot_status_2.into_bits(),
701 })
702 }
703
704 fn restore(&mut self, saved: Self::SavedState) -> Result<(), RestoreError> {
705 let mut state = self.state.lock();
706 state.device_control = pci_express::DeviceControl::from_bits(saved.device_control);
707 state.device_status = pci_express::DeviceStatus::from_bits(saved.device_status);
708 state.link_control = pci_express::LinkControl::from_bits(saved.link_control);
709 state.link_status = pci_express::LinkStatus::from_bits(saved.link_status);
710 state.slot_control = pci_express::SlotControl::from_bits(saved.slot_control);
711 state.slot_status = pci_express::SlotStatus::from_bits(saved.slot_status);
712 state.root_control = pci_express::RootControl::from_bits(saved.root_control);
713 state.root_status = pci_express::RootStatus::from_bits(saved.root_status);
714 state.device_control_2 = pci_express::DeviceControl2::from_bits(saved.device_control_2);
715 state.device_status_2 = pci_express::DeviceStatus2::from_bits(saved.device_status_2);
716 state.link_control_2 = pci_express::LinkControl2::from_bits(saved.link_control_2);
717 state.link_status_2 = pci_express::LinkStatus2::from_bits(saved.link_status_2);
718 state.slot_control_2 = pci_express::SlotControl2::from_bits(saved.slot_control_2);
719 state.slot_status_2 = pci_express::SlotStatus2::from_bits(saved.slot_status_2);
720 Ok(())
721 }
722 }
723}
724
725#[cfg(test)]
726mod tests {
727 use super::*;
728 use crate::spec::caps::pci_express::DevicePortType;
729 use std::sync::atomic::{AtomicBool, Ordering};
730
731 #[derive(Debug)]
732 struct TestFlrHandler {
733 flr_initiated: AtomicBool,
734 }
735
736 impl TestFlrHandler {
737 fn new() -> Arc<Self> {
738 Arc::new(Self {
739 flr_initiated: AtomicBool::new(false),
740 })
741 }
742
743 fn was_flr_initiated(&self) -> bool {
744 self.flr_initiated.load(Ordering::Acquire)
745 }
746
747 fn reset(&self) {
748 self.flr_initiated.store(false, Ordering::Release);
749 }
750 }
751
752 impl FlrHandler for TestFlrHandler {
753 fn initiate_flr(&self) {
754 self.flr_initiated.store(true, Ordering::Release);
755 }
756 }
757
758 impl Inspect for TestFlrHandler {
759 fn inspect(&self, req: inspect::Request<'_>) {
760 req.respond()
761 .field("flr_initiated", self.flr_initiated.load(Ordering::Acquire));
762 }
763 }
764
765 #[test]
766 fn test_pci_express_capability_read_u32_endpoint() {
767 let flr_handler = TestFlrHandler::new();
768 let cap = PciExpressCapability::new(DevicePortType::Endpoint, Some(flr_handler));
769
770 let caps_val = cap.read_u32(0x00);
772 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);
778 assert_eq!(
779 device_caps_val & PCI_EXPRESS_DEVICE_CAPS_FLR_BIT_MASK,
780 PCI_EXPRESS_DEVICE_CAPS_FLR_BIT_MASK
781 ); let device_ctl_sts_val = cap.read_u32(0x08);
785 assert_eq!(device_ctl_sts_val, 0); let link_ctl_sts_val = cap.read_u32(0x10);
789 let expected_link_status = (LinkSpeed::Speed32_0GtS.into_bits() as u16)
790 | ((LinkWidth::X16.into_bits() as u16) << 4); assert_eq!(link_ctl_sts_val, (expected_link_status as u32) << 16); }
793
794 #[test]
795 fn test_pci_express_capability_read_u32_root_port() {
796 let cap = PciExpressCapability::new(DevicePortType::RootPort, None);
797
798 let caps_val = cap.read_u32(0x00);
800 assert_eq!(caps_val & 0xFF, 0x10); assert_eq!((caps_val >> 8) & 0xFF, 0x00); assert_eq!((caps_val >> 16) & 0xFFFF, 0x0042); }
804
805 #[test]
806 fn test_pci_express_capability_read_u32_no_flr() {
807 let cap = PciExpressCapability::new(DevicePortType::Endpoint, None);
808
809 let device_caps_val = cap.read_u32(0x04);
811 assert_eq!(device_caps_val & PCI_EXPRESS_DEVICE_CAPS_FLR_BIT_MASK, 0);
812 }
813
814 #[test]
815 fn test_pci_express_capability_write_u32_readonly_registers() {
816 let mut cap = PciExpressCapability::new(DevicePortType::Endpoint, None);
817
818 let original_caps = cap.read_u32(0x00);
820 cap.write_u32(0x00, 0xFFFFFFFF);
821 assert_eq!(cap.read_u32(0x00), original_caps); let original_device_caps = cap.read_u32(0x04);
825 cap.write_u32(0x04, 0xFFFFFFFF);
826 assert_eq!(cap.read_u32(0x04), original_device_caps); }
828
829 #[test]
830 fn test_pci_express_capability_write_u32_device_control() {
831 let flr_handler = TestFlrHandler::new();
832 let mut cap =
833 PciExpressCapability::new(DevicePortType::Endpoint, Some(flr_handler.clone()));
834
835 let initial_ctl_sts = cap.read_u32(0x08);
837 assert_eq!(initial_ctl_sts & 0xFFFF, 0); cap.write_u32(0x08, 0x0001); let device_ctl_sts = cap.read_u32(0x08);
843 assert_eq!(device_ctl_sts & 0xFFFF, 0x0001); assert!(!flr_handler.was_flr_initiated()); flr_handler.reset();
848 cap.write_u32(0x08, 0x8001); let device_ctl_sts_after_flr = cap.read_u32(0x08);
850 assert_eq!(device_ctl_sts_after_flr & 0xFFFF, 0x0001); assert!(flr_handler.was_flr_initiated()); flr_handler.reset();
855 cap.write_u32(0x08, 0x8000); let device_ctl_sts_final = cap.read_u32(0x08);
859 assert_eq!(device_ctl_sts_final & 0xFFFF, 0x0000); assert!(flr_handler.was_flr_initiated()); }
862
863 #[test]
864 fn test_pci_express_capability_write_u32_device_status() {
865 let mut cap = PciExpressCapability::new(DevicePortType::Endpoint, None);
866
867 {
869 let mut state = cap.state.lock();
870 state.device_status.set_correctable_error_detected(true);
871 state.device_status.set_non_fatal_error_detected(true);
872 state.device_status.set_fatal_error_detected(true);
873 state.device_status.set_unsupported_request_detected(true);
874 }
875
876 let device_ctl_sts = cap.read_u32(0x08);
878 let status_bits = (device_ctl_sts >> 16) & 0xFFFF;
879 assert_ne!(status_bits & 0x0F, 0); cap.write_u32(0x08, 0x00010000); let device_ctl_sts_after = cap.read_u32(0x08);
884 let status_bits_after = (device_ctl_sts_after >> 16) & 0xFFFF;
885 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;
891 assert_eq!(final_status & 0x0F, 0); }
893
894 #[test]
895 fn test_pci_express_capability_write_u32_unhandled_offset() {
896 let mut cap = PciExpressCapability::new(DevicePortType::Endpoint, None);
897
898 cap.write_u32(0x10, 0xFFFFFFFF);
900 assert_eq!(cap.read_u32(0x08), 0); }
903
904 #[test]
905 fn test_pci_express_capability_reset() {
906 let flr_handler = TestFlrHandler::new();
907 let mut cap =
908 PciExpressCapability::new(DevicePortType::Endpoint, Some(flr_handler.clone()));
909
910 cap.write_u32(0x08, 0x0001); {
915 let mut state = cap.state.lock();
916 state.device_status.set_correctable_error_detected(true);
917 }
918
919 let device_ctl_sts = cap.read_u32(0x08);
921 assert_ne!(device_ctl_sts, 0);
922
923 cap.reset();
925
926 let device_ctl_sts_after_reset = cap.read_u32(0x08);
928 assert_eq!(device_ctl_sts_after_reset, 0);
929 }
930
931 #[test]
932 fn test_pci_express_capability_extended_registers() {
933 let cap = PciExpressCapability::new(DevicePortType::Endpoint, None);
934
935 let expected_link_caps =
938 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)
942 | ((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); }
959
960 #[test]
961 fn test_pci_express_capability_length() {
962 let cap = PciExpressCapability::new(DevicePortType::Endpoint, None);
963 assert_eq!(cap.len(), 0x3C); }
965
966 #[test]
967 fn test_pci_express_capability_label() {
968 let cap = PciExpressCapability::new(DevicePortType::Endpoint, None);
969 assert_eq!(cap.label(), "pci-express");
970 }
971
972 #[test]
973 fn test_pci_express_capability_with_hotplug_support() {
974 let cap = PciExpressCapability::new(DevicePortType::RootPort, None);
976 let cap_with_hotplug = cap.with_hotplug_support(1);
977
978 assert_eq!(cap_with_hotplug.label(), "pci-express");
980 assert_eq!(cap_with_hotplug.len(), 0x3C);
981
982 assert!(cap_with_hotplug.slot_capabilities.hot_plug_surprise());
984 assert!(cap_with_hotplug.slot_capabilities.hot_plug_capable());
985 assert_eq!(cap_with_hotplug.slot_capabilities.physical_slot_number(), 1);
986
987 assert!(
989 cap_with_hotplug.pcie_capabilities.slot_implemented(),
990 "slot_implemented should be true when hotplug is enabled"
991 );
992
993 let cap2 = PciExpressCapability::new(DevicePortType::DownstreamSwitchPort, None);
995 let cap2_with_hotplug = cap2.with_hotplug_support(2);
996
997 assert!(cap2_with_hotplug.slot_capabilities.hot_plug_surprise());
998 assert!(cap2_with_hotplug.slot_capabilities.hot_plug_capable());
999 assert_eq!(
1000 cap2_with_hotplug.slot_capabilities.physical_slot_number(),
1001 2
1002 );
1003
1004 assert!(
1006 cap2_with_hotplug.pcie_capabilities.slot_implemented(),
1007 "slot_implemented should be true when hotplug is enabled"
1008 );
1009
1010 let cap_no_hotplug = PciExpressCapability::new(DevicePortType::RootPort, None);
1012 assert!(
1013 !cap_no_hotplug.pcie_capabilities.slot_implemented(),
1014 "slot_implemented should be false when hotplug is not enabled"
1015 );
1016 }
1017
1018 #[test]
1019 #[should_panic(expected = "Hotplug support is not valid for device port type Endpoint")]
1020 fn test_pci_express_capability_with_hotplug_support_endpoint_panics() {
1021 let cap = PciExpressCapability::new(DevicePortType::Endpoint, None);
1022 cap.with_hotplug_support(1);
1023 }
1024
1025 #[test]
1026 #[should_panic(
1027 expected = "Hotplug support is not valid for device port type UpstreamSwitchPort"
1028 )]
1029 fn test_pci_express_capability_with_hotplug_support_upstream_panics() {
1030 let cap = PciExpressCapability::new(DevicePortType::UpstreamSwitchPort, None);
1031 cap.with_hotplug_support(1);
1032 }
1033
1034 #[test]
1035 fn test_slot_control_write_protection() {
1036 let mut cap = PciExpressCapability::new(DevicePortType::RootPort, None);
1038 cap = cap.with_hotplug_support(1);
1039
1040 cap.slot_capabilities.set_attention_button_present(false);
1042 cap.slot_capabilities.set_power_controller_present(false);
1043 cap.slot_capabilities.set_mrl_sensor_present(false);
1044 cap.slot_capabilities.set_attention_indicator_present(false);
1045 cap.slot_capabilities.set_power_indicator_present(false);
1046 cap.slot_capabilities
1047 .set_electromechanical_interlock_present(false);
1048 cap.slot_capabilities.set_no_command_completed_support(true);
1049
1050 let slot_ctl_sts_offset = 0x18; let val_to_write = 0xFFFFFFFF; cap.write_u32(slot_ctl_sts_offset, val_to_write);
1055
1056 let read_back = cap.read_u32(slot_ctl_sts_offset);
1058 let slot_control_value = read_back as u16;
1059 let slot_control = pci_express::SlotControl::from_bits(slot_control_value);
1060
1061 assert!(
1063 !slot_control.attention_button_pressed_enable(),
1064 "Attention button enable should be 0 when capability not present"
1065 );
1066 assert!(
1067 !slot_control.power_controller_control(),
1068 "Power controller control should be 0 when capability not present"
1069 );
1070 assert!(
1071 !slot_control.mrl_sensor_changed_enable(),
1072 "MRL sensor changed enable should be 0 when capability not present"
1073 );
1074 assert_eq!(
1075 slot_control.attention_indicator_control(),
1076 0,
1077 "Attention indicator control should be 0 when capability not present"
1078 );
1079 assert_eq!(
1080 slot_control.power_indicator_control(),
1081 0,
1082 "Power indicator control should be 0 when capability not present"
1083 );
1084 assert!(
1085 !slot_control.electromechanical_interlock_control(),
1086 "Electromechanical interlock control should be 0 when capability not present"
1087 );
1088 assert!(
1089 !slot_control.command_completed_interrupt_enable(),
1090 "Command completed interrupt enable should be 0 when no command completed support"
1091 );
1092
1093 assert!(
1095 slot_control.hot_plug_interrupt_enable(),
1096 "Hotplug interrupt enable should be settable when hotplug capable"
1097 );
1098 }
1099
1100 #[test]
1101 fn test_link_control_retrain_link_behavior() {
1102 let mut cap = PciExpressCapability::new(DevicePortType::RootPort, None);
1104
1105 let link_ctl_sts_offset = 0x10; let write_val = 0x0020; cap.write_u32(link_ctl_sts_offset, write_val);
1110
1111 let read_back = cap.read_u32(link_ctl_sts_offset);
1113 let link_control = pci_express::LinkControl::from_bits(read_back as u16);
1114
1115 assert!(
1116 !link_control.retrain_link(),
1117 "retrain_link should always read as 0"
1118 );
1119
1120 let write_val_2 = 0x0001; cap.write_u32(link_ctl_sts_offset, write_val_2);
1123
1124 let read_back_2 = cap.read_u32(link_ctl_sts_offset);
1125 let link_control_2 = pci_express::LinkControl::from_bits(read_back_2 as u16);
1126
1127 assert_eq!(
1128 link_control_2.aspm_control(),
1129 1,
1130 "Other control bits should be settable"
1131 );
1132 assert!(
1133 !link_control_2.retrain_link(),
1134 "retrain_link should still read as 0"
1135 );
1136 }
1137
1138 #[test]
1139 fn test_hotplug_link_capabilities() {
1140 let cap = PciExpressCapability::new(DevicePortType::RootPort, None);
1142 let cap_with_hotplug = cap.with_hotplug_support(1);
1143
1144 let link_caps_offset = 0x0C; let link_caps = cap_with_hotplug.read_u32(link_caps_offset);
1146 let link_capabilities = pci_express::LinkCapabilities::from_bits(link_caps);
1147
1148 assert!(
1150 link_capabilities.data_link_layer_link_active_reporting(),
1151 "Data Link Layer Link Active Reporting should be enabled for hotplug"
1152 );
1153
1154 assert_eq!(
1156 link_capabilities.max_link_speed(),
1157 LinkSpeed::Speed32_0GtS.into_bits(),
1158 "Max link speed should be Speed32_0GtS (PCIe 32.0 GT/s)"
1159 );
1160 assert_eq!(
1161 link_capabilities.max_link_width(),
1162 LinkWidth::X16.into_bits(),
1163 "Max link width should be X16 (x16)"
1164 );
1165
1166 let cap_no_hotplug = PciExpressCapability::new(DevicePortType::RootPort, None);
1168 let link_caps_no_hotplug = cap_no_hotplug.read_u32(link_caps_offset);
1169 let link_capabilities_no_hotplug =
1170 pci_express::LinkCapabilities::from_bits(link_caps_no_hotplug);
1171
1172 assert!(
1173 !link_capabilities_no_hotplug.data_link_layer_link_active_reporting(),
1174 "Data Link Layer Link Active Reporting should be disabled without hotplug"
1175 );
1176 }
1177
1178 #[test]
1179 fn test_link_status_read_only() {
1180 let mut cap = PciExpressCapability::new(DevicePortType::RootPort, None);
1182
1183 let link_ctl_sts_offset = 0x10; {
1187 let mut state = cap.state.lock();
1188 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); }
1193
1194 let initial_read = cap.read_u32(link_ctl_sts_offset);
1196 let initial_link_status = pci_express::LinkStatus::from_bits((initial_read >> 16) as u16);
1197
1198 assert_eq!(
1200 initial_link_status.current_link_speed(),
1201 0b0001,
1202 "Initial link speed should be set"
1203 );
1204 assert_eq!(
1205 initial_link_status.negotiated_link_width(),
1206 0b000001,
1207 "Initial link width should be set"
1208 );
1209 assert!(
1210 initial_link_status.link_training(),
1211 "Initial link training should be active"
1212 );
1213 assert!(
1214 initial_link_status.data_link_layer_link_active(),
1215 "Initial DLL should be active"
1216 );
1217
1218 let write_val = 0xFFFF0001; cap.write_u32(link_ctl_sts_offset, write_val);
1221
1222 let after_write = cap.read_u32(link_ctl_sts_offset);
1224 let final_link_status = pci_express::LinkStatus::from_bits((after_write >> 16) as u16);
1225 let final_link_control = pci_express::LinkControl::from_bits(after_write as u16);
1226
1227 assert_eq!(
1229 final_link_status.current_link_speed(),
1230 initial_link_status.current_link_speed(),
1231 "Link Status current_link_speed should be read-only"
1232 );
1233 assert_eq!(
1234 final_link_status.negotiated_link_width(),
1235 initial_link_status.negotiated_link_width(),
1236 "Link Status negotiated_link_width should be read-only"
1237 );
1238 assert_eq!(
1239 final_link_status.link_training(),
1240 initial_link_status.link_training(),
1241 "Link Status link_training should be read-only"
1242 );
1243 assert_eq!(
1244 final_link_status.data_link_layer_link_active(),
1245 initial_link_status.data_link_layer_link_active(),
1246 "Link Status data_link_layer_link_active should be read-only"
1247 );
1248
1249 assert_eq!(
1251 final_link_control.aspm_control(),
1252 1,
1253 "Link Control should be writable"
1254 );
1255 }
1256
1257 #[test]
1258 fn test_slot_status_rw1c_behavior() {
1259 let mut cap = PciExpressCapability::new(DevicePortType::RootPort, None);
1261 cap = cap.with_hotplug_support(1);
1262
1263 let slot_ctl_sts_offset = 0x18; {
1267 let mut state = cap.state.lock();
1268 state.slot_status.set_attention_button_pressed(true);
1269 state.slot_status.set_power_fault_detected(true);
1270 state.slot_status.set_mrl_sensor_changed(true);
1271 state.slot_status.set_presence_detect_changed(true);
1272 state.slot_status.set_command_completed(true);
1273 state.slot_status.set_data_link_layer_state_changed(true);
1274 state.slot_status.set_mrl_sensor_state(1);
1276 state.slot_status.set_presence_detect_state(1);
1277 state.slot_status.set_electromechanical_interlock_status(1);
1278 }
1279
1280 let initial_read = cap.read_u32(slot_ctl_sts_offset);
1282 let initial_status = pci_express::SlotStatus::from_bits((initial_read >> 16) as u16);
1283 assert!(
1284 initial_status.attention_button_pressed(),
1285 "Initial attention button pressed should be set"
1286 );
1287 assert!(
1288 initial_status.power_fault_detected(),
1289 "Initial power fault detected should be set"
1290 );
1291 assert!(
1292 initial_status.mrl_sensor_changed(),
1293 "Initial MRL sensor changed should be set"
1294 );
1295 assert!(
1296 initial_status.presence_detect_changed(),
1297 "Initial presence detect changed should be set"
1298 );
1299 assert!(
1300 initial_status.command_completed(),
1301 "Initial command completed should be set"
1302 );
1303 assert!(
1304 initial_status.data_link_layer_state_changed(),
1305 "Initial data link layer state changed should be set"
1306 );
1307 assert_eq!(
1308 initial_status.mrl_sensor_state(),
1309 1,
1310 "Initial MRL sensor state should be set"
1311 );
1312 assert_eq!(
1313 initial_status.presence_detect_state(),
1314 1,
1315 "Initial presence detect state should be set"
1316 );
1317 assert_eq!(
1318 initial_status.electromechanical_interlock_status(),
1319 1,
1320 "Initial electromechanical interlock status should be set"
1321 );
1322
1323 let write_val = (0b0000_0001_0001_0001_u16 as u32) << 16; cap.write_u32(slot_ctl_sts_offset, write_val);
1328
1329 let after_write = cap.read_u32(slot_ctl_sts_offset);
1331 let final_status = pci_express::SlotStatus::from_bits((after_write >> 16) as u16);
1332
1333 assert!(
1335 !final_status.attention_button_pressed(),
1336 "Attention button pressed should be cleared after write-1"
1337 );
1338 assert!(
1339 !final_status.command_completed(),
1340 "Command completed should be cleared after write-1"
1341 );
1342 assert!(
1343 !final_status.data_link_layer_state_changed(),
1344 "Data link layer state changed should be cleared after write-1"
1345 );
1346
1347 assert!(
1349 final_status.power_fault_detected(),
1350 "Power fault detected should remain set (write-0)"
1351 );
1352 assert!(
1353 final_status.mrl_sensor_changed(),
1354 "MRL sensor changed should remain set (write-0)"
1355 );
1356 assert!(
1357 final_status.presence_detect_changed(),
1358 "Presence detect changed should remain set (write-0)"
1359 );
1360
1361 assert_eq!(
1363 final_status.mrl_sensor_state(),
1364 1,
1365 "MRL sensor state should remain unchanged (RO)"
1366 );
1367 assert_eq!(
1368 final_status.presence_detect_state(),
1369 1,
1370 "Presence detect state should remain unchanged (RO)"
1371 );
1372 assert_eq!(
1373 final_status.electromechanical_interlock_status(),
1374 1,
1375 "Electromechanical interlock status should remain unchanged (RO)"
1376 );
1377 }
1378
1379 #[test]
1380 fn test_link_control_2_target_speed_validation() {
1381 let mut cap = PciExpressCapability::new(DevicePortType::RootPort, None);
1383
1384 let link_ctl_sts_2_offset = 0x30; let initial_read = cap.read_u32(link_ctl_sts_2_offset);
1388 let initial_link_control_2 = pci_express::LinkControl2::from_bits(initial_read as u16);
1389 assert_eq!(
1390 initial_link_control_2.target_link_speed(),
1391 LinkSpeed::Speed32_0GtS.into_bits() as u16,
1392 "Initial target link speed should be Speed32_0GtS"
1393 );
1394
1395 let link_ctl_sts_offset = 0x10; let link_ctl_sts = cap.read_u32(link_ctl_sts_offset);
1398 let link_status = pci_express::LinkStatus::from_bits((link_ctl_sts >> 16) as u16);
1399 assert_eq!(
1400 link_status.current_link_speed(),
1401 LinkSpeed::Speed32_0GtS.into_bits() as u16,
1402 "Initial current link speed should match target speed"
1403 );
1404 assert_eq!(
1405 link_status.negotiated_link_width(),
1406 LinkWidth::X16.into_bits() as u16,
1407 "Initial negotiated link width should be X16"
1408 );
1409
1410 let valid_speed = LinkSpeed::Speed16_0GtS.into_bits() as u16; cap.write_u32(link_ctl_sts_2_offset, valid_speed as u32);
1413
1414 let after_valid_write = cap.read_u32(link_ctl_sts_2_offset);
1416 let link_control_2_after_valid =
1417 pci_express::LinkControl2::from_bits(after_valid_write as u16);
1418 assert_eq!(
1419 link_control_2_after_valid.target_link_speed(),
1420 valid_speed,
1421 "Target link speed should be set to requested valid speed"
1422 );
1423
1424 let link_ctl_sts_after_valid = cap.read_u32(link_ctl_sts_offset);
1426 let link_status_after_valid =
1427 pci_express::LinkStatus::from_bits((link_ctl_sts_after_valid >> 16) as u16);
1428 assert_eq!(
1429 link_status_after_valid.current_link_speed(),
1430 valid_speed,
1431 "Current link speed should be updated to match target speed"
1432 );
1433
1434 let invalid_speed = LinkSpeed::Speed64_0GtS.into_bits() as u16; cap.write_u32(link_ctl_sts_2_offset, invalid_speed as u32);
1437
1438 let after_invalid_write = cap.read_u32(link_ctl_sts_2_offset);
1440 let link_control_2_after_invalid =
1441 pci_express::LinkControl2::from_bits(after_invalid_write as u16);
1442 let max_speed = LinkSpeed::Speed32_0GtS.into_bits() as u16; assert_eq!(
1444 link_control_2_after_invalid.target_link_speed(),
1445 max_speed,
1446 "Target link speed should be clamped to max supported speed"
1447 );
1448
1449 let link_ctl_sts_after_invalid = cap.read_u32(link_ctl_sts_offset);
1451 let link_status_after_invalid =
1452 pci_express::LinkStatus::from_bits((link_ctl_sts_after_invalid >> 16) as u16);
1453 assert_eq!(
1454 link_status_after_invalid.current_link_speed(),
1455 max_speed,
1456 "Current link speed should be updated to clamped max speed"
1457 );
1458
1459 assert_eq!(
1461 link_status_after_valid.negotiated_link_width(),
1462 LinkWidth::X16.into_bits() as u16,
1463 "Negotiated link width should remain unchanged"
1464 );
1465 assert_eq!(
1466 link_status_after_invalid.negotiated_link_width(),
1467 LinkWidth::X16.into_bits() as u16,
1468 "Negotiated link width should remain unchanged"
1469 );
1470 }
1471
1472 #[test]
1473 fn test_with_hotplug_support_slot_number() {
1474 let cap1 = PciExpressCapability::new(DevicePortType::RootPort, None);
1478 let cap1_with_hotplug = cap1.with_hotplug_support(5);
1479
1480 assert!(cap1_with_hotplug.slot_capabilities.hot_plug_capable());
1481 assert_eq!(
1482 cap1_with_hotplug.slot_capabilities.physical_slot_number(),
1483 5
1484 );
1485
1486 let cap2 = PciExpressCapability::new(DevicePortType::DownstreamSwitchPort, None);
1488 let cap2_with_hotplug = cap2.with_hotplug_support(0);
1489
1490 assert!(cap2_with_hotplug.slot_capabilities.hot_plug_capable());
1491 assert_eq!(
1492 cap2_with_hotplug.slot_capabilities.physical_slot_number(),
1493 0
1494 );
1495
1496 let cap3 = PciExpressCapability::new(DevicePortType::RootPort, None);
1498 let cap3_with_hotplug = cap3.with_hotplug_support(255);
1499
1500 assert!(cap3_with_hotplug.slot_capabilities.hot_plug_capable());
1501 assert_eq!(
1502 cap3_with_hotplug.slot_capabilities.physical_slot_number(),
1503 255
1504 );
1505 }
1506
1507 #[test]
1508 fn test_slot_implemented_flag_in_pcie_capabilities_register() {
1509 let cap_no_hotplug = PciExpressCapability::new(DevicePortType::RootPort, None);
1514 let caps_val_no_hotplug = cap_no_hotplug.read_u32(0x00);
1515 let pcie_caps_no_hotplug = (caps_val_no_hotplug >> 16) as u16;
1516 let slot_implemented_bit = (pcie_caps_no_hotplug >> 8) & 0x1; assert_eq!(
1518 slot_implemented_bit, 0,
1519 "slot_implemented should be 0 when hotplug is not enabled"
1520 );
1521
1522 let cap_with_hotplug = cap_no_hotplug.with_hotplug_support(1);
1524 let caps_val_with_hotplug = cap_with_hotplug.read_u32(0x00);
1525 let pcie_caps_with_hotplug = (caps_val_with_hotplug >> 16) as u16;
1526 let slot_implemented_bit_hotplug = (pcie_caps_with_hotplug >> 8) & 0x1; assert_eq!(
1528 slot_implemented_bit_hotplug, 1,
1529 "slot_implemented should be 1 when hotplug is enabled"
1530 );
1531 }
1532
1533 #[test]
1534 fn test_set_presence_detect_state() {
1535 let cap = PciExpressCapability::new(DevicePortType::RootPort, None).with_hotplug_support(1);
1537
1538 let initial_slot_status = cap.read_u32(0x18); let initial_presence_detect = (initial_slot_status >> 22) & 0x1; assert_eq!(
1542 initial_presence_detect, 0,
1543 "Initial presence detect state should be 0"
1544 );
1545
1546 cap.set_presence_detect_state(true);
1548 let present_slot_status = cap.read_u32(0x18);
1549 let present_presence_detect = (present_slot_status >> 22) & 0x1;
1550 assert_eq!(
1551 present_presence_detect, 1,
1552 "Presence detect state should be 1 when device is present"
1553 );
1554
1555 cap.set_presence_detect_state(false);
1557 let absent_slot_status = cap.read_u32(0x18);
1558 let absent_presence_detect = (absent_slot_status >> 22) & 0x1;
1559 assert_eq!(
1560 absent_presence_detect, 0,
1561 "Presence detect state should be 0 when device is not present"
1562 );
1563 }
1564
1565 #[test]
1566 fn test_set_presence_detect_state_without_slot_implemented() {
1567 let cap = PciExpressCapability::new(DevicePortType::RootPort, None);
1569
1570 cap.set_presence_detect_state(true);
1572 cap.set_presence_detect_state(false);
1573 }
1574
1575 #[test]
1576 fn test_save_restore_default_state() {
1577 use vmcore::save_restore::SaveRestore;
1578
1579 let mut cap = PciExpressCapability::new(DevicePortType::Endpoint, None);
1581
1582 let saved = cap.save().expect("save should succeed");
1584
1585 assert_eq!(saved.device_control, 0);
1587 assert_eq!(saved.device_status, 0);
1588 assert_eq!(saved.link_control, 0);
1589 let expected_link_status = (LinkSpeed::Speed32_0GtS.into_bits() as u16)
1591 | ((LinkWidth::X16.into_bits() as u16) << 4);
1592 assert_eq!(saved.link_status, expected_link_status);
1593 assert_eq!(saved.slot_control, 0);
1594 assert_eq!(saved.slot_status, 0);
1595 assert_eq!(saved.root_control, 0);
1596 assert_eq!(saved.root_status, 0);
1597 assert_eq!(saved.device_control_2, 0);
1598 assert_eq!(saved.device_status_2, 0);
1599 let expected_link_control_2 = LinkSpeed::Speed32_0GtS.into_bits() as u16;
1601 assert_eq!(saved.link_control_2, expected_link_control_2);
1602 assert_eq!(saved.link_status_2, 0);
1603 assert_eq!(saved.slot_control_2, 0);
1604 assert_eq!(saved.slot_status_2, 0);
1605 }
1606
1607 #[test]
1608 fn test_save_restore_modified_state() {
1609 use vmcore::save_restore::SaveRestore;
1610
1611 let mut cap = PciExpressCapability::new(DevicePortType::Endpoint, None);
1612
1613 cap.write_u32(0x08, 0x0005); cap.write_u32(0x10, 0x0003); cap.write_u32(0x28, 0x0010); let saved = cap.save().expect("save should succeed");
1625
1626 assert_eq!(saved.device_control, 0x0005);
1628 assert_eq!(saved.link_control, 0x0003);
1629 assert_eq!(saved.device_control_2, 0x0010);
1630 }
1631
1632 #[test]
1633 fn test_save_restore_roundtrip() {
1634 use vmcore::save_restore::SaveRestore;
1635
1636 let mut cap = PciExpressCapability::new(DevicePortType::RootPort, None);
1637
1638 cap.write_u32(0x08, 0x000F); cap.write_u32(0x10, 0x0007); cap.write_u32(0x28, 0x0020); cap.write_u32(0x30, 0x0004); let saved = cap.save().expect("save should succeed");
1646
1647 let mut cap2 = PciExpressCapability::new(DevicePortType::RootPort, None);
1649 cap2.restore(saved).expect("restore should succeed");
1650
1651 let device_ctl_sts = cap2.read_u32(0x08);
1653 assert_eq!(
1654 device_ctl_sts & 0xFFFF,
1655 0x000F,
1656 "Device control should be restored"
1657 );
1658
1659 let link_ctl_sts = cap2.read_u32(0x10);
1660 assert_eq!(
1661 link_ctl_sts & 0xFFFF,
1662 0x0007,
1663 "Link control should be restored"
1664 );
1665
1666 let device_ctl_sts_2 = cap2.read_u32(0x28);
1667 assert_eq!(
1668 device_ctl_sts_2 & 0xFFFF,
1669 0x0020,
1670 "Device control 2 should be restored"
1671 );
1672
1673 let link_ctl_sts_2 = cap2.read_u32(0x30);
1674 assert_eq!(
1675 link_ctl_sts_2 & 0xFFFF,
1676 0x0004,
1677 "Link control 2 should be restored"
1678 );
1679 }
1680
1681 #[test]
1682 fn test_save_restore_with_status_bits() {
1683 use vmcore::save_restore::SaveRestore;
1684
1685 let mut cap = PciExpressCapability::new(DevicePortType::RootPort, None);
1686 cap = cap.with_hotplug_support(1);
1687
1688 {
1690 let mut state = cap.state.lock();
1691 state.device_status.set_correctable_error_detected(true);
1692 state.device_status.set_non_fatal_error_detected(true);
1693 state.slot_status.set_presence_detect_changed(true);
1694 state.slot_status.set_presence_detect_state(1);
1695 }
1696
1697 let saved = cap.save().expect("save should succeed");
1699
1700 let saved_device_status = pci_express::DeviceStatus::from_bits(saved.device_status);
1702 let saved_slot_status = pci_express::SlotStatus::from_bits(saved.slot_status);
1703 assert!(saved_device_status.correctable_error_detected());
1704 assert!(saved_device_status.non_fatal_error_detected());
1705 assert!(saved_slot_status.presence_detect_changed());
1706 assert_eq!(saved_slot_status.presence_detect_state(), 1);
1707
1708 let mut cap2 = PciExpressCapability::new(DevicePortType::RootPort, None);
1710 cap2 = cap2.with_hotplug_support(1);
1711 cap2.restore(saved).expect("restore should succeed");
1712
1713 let device_ctl_sts = cap2.read_u32(0x08);
1715 let restored_device_status =
1716 pci_express::DeviceStatus::from_bits((device_ctl_sts >> 16) as u16);
1717 assert!(
1718 restored_device_status.correctable_error_detected(),
1719 "Device status should be restored"
1720 );
1721 assert!(
1722 restored_device_status.non_fatal_error_detected(),
1723 "Device status should be restored"
1724 );
1725
1726 let slot_ctl_sts = cap2.read_u32(0x18);
1727 let restored_slot_status = pci_express::SlotStatus::from_bits((slot_ctl_sts >> 16) as u16);
1728 assert!(
1729 restored_slot_status.presence_detect_changed(),
1730 "Slot status should be restored"
1731 );
1732 assert_eq!(
1733 restored_slot_status.presence_detect_state(),
1734 1,
1735 "Presence detect state should be restored"
1736 );
1737 }
1738
1739 #[test]
1740 fn test_save_restore_all_fields() {
1741 use vmcore::save_restore::SaveRestore;
1742
1743 let mut cap = PciExpressCapability::new(DevicePortType::RootPort, None);
1744
1745 {
1747 let mut state = cap.state.lock();
1748 state.device_control = pci_express::DeviceControl::from_bits(0x1111);
1749 state.device_status = pci_express::DeviceStatus::from_bits(0x2222);
1750 state.link_control = pci_express::LinkControl::from_bits(0x3333);
1751 state.link_status = pci_express::LinkStatus::from_bits(0x4444);
1752 state.slot_control = pci_express::SlotControl::from_bits(0x5555);
1753 state.slot_status = pci_express::SlotStatus::from_bits(0x6666);
1754 state.root_control = pci_express::RootControl::from_bits(0x7777);
1755 state.root_status = pci_express::RootStatus::from_bits(0x88888888);
1756 state.device_control_2 = pci_express::DeviceControl2::from_bits(0x9999);
1757 state.device_status_2 = pci_express::DeviceStatus2::from_bits(0xAAAA);
1758 state.link_control_2 = pci_express::LinkControl2::from_bits(0xBBBB);
1759 state.link_status_2 = pci_express::LinkStatus2::from_bits(0xCCCC);
1760 state.slot_control_2 = pci_express::SlotControl2::from_bits(0xDDDD);
1761 state.slot_status_2 = pci_express::SlotStatus2::from_bits(0xEEEE);
1762 }
1763
1764 let saved = cap.save().expect("save should succeed");
1766
1767 assert_eq!(saved.device_control, 0x1111);
1769 assert_eq!(saved.device_status, 0x2222);
1770 assert_eq!(saved.link_control, 0x3333);
1771 assert_eq!(saved.link_status, 0x4444);
1772 assert_eq!(saved.slot_control, 0x5555);
1773 assert_eq!(saved.slot_status, 0x6666);
1774 assert_eq!(saved.root_control, 0x7777);
1775 assert_eq!(saved.root_status, 0x88888888);
1776 assert_eq!(saved.device_control_2, 0x9999);
1777 assert_eq!(saved.device_status_2, 0xAAAA);
1778 assert_eq!(saved.link_control_2, 0xBBBB);
1779 assert_eq!(saved.link_status_2, 0xCCCC);
1780 assert_eq!(saved.slot_control_2, 0xDDDD);
1781 assert_eq!(saved.slot_status_2, 0xEEEE);
1782
1783 let mut cap2 = PciExpressCapability::new(DevicePortType::RootPort, None);
1785 cap2.restore(saved).expect("restore should succeed");
1786
1787 let saved2 = cap2.save().expect("second save should succeed");
1789 assert_eq!(saved2.device_control, 0x1111);
1790 assert_eq!(saved2.device_status, 0x2222);
1791 assert_eq!(saved2.link_control, 0x3333);
1792 assert_eq!(saved2.link_status, 0x4444);
1793 assert_eq!(saved2.slot_control, 0x5555);
1794 assert_eq!(saved2.slot_status, 0x6666);
1795 assert_eq!(saved2.root_control, 0x7777);
1796 assert_eq!(saved2.root_status, 0x88888888);
1797 assert_eq!(saved2.device_control_2, 0x9999);
1798 assert_eq!(saved2.device_status_2, 0xAAAA);
1799 assert_eq!(saved2.link_control_2, 0xBBBB);
1800 assert_eq!(saved2.link_status_2, 0xCCCC);
1801 assert_eq!(saved2.slot_control_2, 0xDDDD);
1802 assert_eq!(saved2.slot_status_2, 0xEEEE);
1803 }
1804
1805 #[test]
1806 fn test_save_after_reset() {
1807 use vmcore::save_restore::SaveRestore;
1808
1809 let mut cap = PciExpressCapability::new(DevicePortType::Endpoint, None);
1810
1811 cap.write_u32(0x08, 0x00FF);
1813 cap.write_u32(0x10, 0x00FF);
1814
1815 cap.reset();
1817
1818 let saved = cap.save().expect("save should succeed");
1820
1821 assert_eq!(saved.device_control, 0);
1823 assert_eq!(saved.device_status, 0);
1824 assert_eq!(saved.link_control, 0);
1825 let expected_link_status = (LinkSpeed::Speed32_0GtS.into_bits() as u16)
1827 | ((LinkWidth::X16.into_bits() as u16) << 4);
1828 assert_eq!(saved.link_status, expected_link_status);
1829 }
1830}