1use super::PciCapability;
7use crate::spec::caps::CapabilityId;
8use crate::spec::caps::pci_express;
9use crate::spec::caps::pci_express::LinkSpeed;
10use crate::spec::caps::pci_express::LinkWidth;
11use crate::spec::caps::pci_express::MaxEndEndTlpPrefixes;
12use crate::spec::caps::pci_express::PciExpressCapabilityHeader;
13use crate::spec::caps::pci_express::SupportedLinkSpeedsVector;
14use chipset_device::pci::ByteEnabledDwordRead;
15use chipset_device::pci::ByteEnabledDwordWrite;
16use inspect::Inspect;
17use parking_lot::Mutex;
18use std::sync::Arc;
19
20pub const PCI_EXPRESS_DEVICE_CAPS_FLR_BIT_MASK: u32 = 1 << 28;
22
23pub trait FlrHandler: Send + Sync + Inspect {
25 fn initiate_flr(&self);
27}
28
29#[derive(Debug, Inspect)]
30struct PciExpressState {
31 registers: PciExpressRegisters,
32 presence_detect_state: bool,
33}
34
35#[derive(Debug, Inspect)]
36struct PciExpressRegisters {
37 device_control: pci_express::DeviceControl,
38 link_control: pci_express::LinkControl,
39 slot_control: pci_express::SlotControl,
40 slot_status_events: pci_express::SlotStatus,
41 root_control: pci_express::RootControl,
42 device_control_2: pci_express::DeviceControl2,
43 link_control_2: pci_express::LinkControl2,
44}
45
46impl PciExpressState {
47 fn new() -> Self {
48 Self {
49 registers: PciExpressRegisters::new(),
50 presence_detect_state: false,
51 }
52 }
53
54 fn reset_registers(&mut self) {
55 let Self {
56 registers,
57 presence_detect_state: _,
58 } = self;
59 *registers = PciExpressRegisters::new();
60 }
61
62 fn slot_status(
63 &self,
64 slot_implemented: bool,
65 downstream_port: bool,
66 ) -> pci_express::SlotStatus {
67 self.registers
68 .slot_status_events
69 .with_mrl_sensor_state(0)
70 .with_presence_detect_state(
71 (if slot_implemented {
72 self.presence_detect_state
73 } else {
74 downstream_port
75 })
76 .into(),
77 )
78 .with_electromechanical_interlock_status(0)
79 }
80
81 fn link_status(&self) -> pci_express::LinkStatus {
82 pci_express::LinkStatus::new()
83 .with_current_link_speed(LinkSpeed::Speed32_0GtS)
84 .with_negotiated_link_width(LinkWidth::X16)
85 .with_data_link_layer_link_active(self.presence_detect_state)
86 }
87}
88
89impl PciExpressRegisters {
90 fn new() -> Self {
91 Self {
92 device_control: pci_express::DeviceControl::new()
93 .with_enable_relaxed_ordering(true)
94 .with_enable_no_snoop(true)
95 .with_max_read_request_size(0b010),
96 link_control: pci_express::LinkControl::new(),
97 slot_control: pci_express::SlotControl::new(),
98 slot_status_events: pci_express::SlotStatus::new(),
99 root_control: pci_express::RootControl::new(),
100 device_control_2: pci_express::DeviceControl2::new(),
101 link_control_2: pci_express::LinkControl2::new()
102 .with_target_link_speed(LinkSpeed::Speed32_0GtS),
103 }
104 }
105}
106
107#[derive(Inspect)]
108pub struct PciExpressCapability {
110 pcie_capabilities: pci_express::PciExpressCapabilities,
111 device_capabilities: pci_express::DeviceCapabilities,
112 link_capabilities: pci_express::LinkCapabilities,
113 slot_capabilities: pci_express::SlotCapabilities,
114 root_capabilities: pci_express::RootCapabilities,
115 device_capabilities_2: pci_express::DeviceCapabilities2,
116 link_capabilities_2: pci_express::LinkCapabilities2,
117 slot_capabilities_2: pci_express::SlotCapabilities2,
118 state: Arc<Mutex<PciExpressState>>,
119 #[inspect(skip)]
120 flr_handler: Option<Arc<dyn FlrHandler>>,
121}
122
123impl PciExpressCapability {
124 pub fn new(typ: pci_express::DevicePortType, flr_handler: Option<Arc<dyn FlrHandler>>) -> Self {
130 let ari_forwarding_supported = matches!(
137 typ,
138 pci_express::DevicePortType::RootPort
139 | pci_express::DevicePortType::DownstreamSwitchPort
140 );
141 let function_level_reset =
142 typ == pci_express::DevicePortType::Endpoint && flr_handler.is_some();
143 Self {
144 pcie_capabilities: pci_express::PciExpressCapabilities::new()
145 .with_capability_version(2)
146 .with_device_port_type(typ),
147 device_capabilities: pci_express::DeviceCapabilities::new()
148 .with_role_based_error(true)
149 .with_function_level_reset(function_level_reset),
150 link_capabilities: pci_express::LinkCapabilities::new()
155 .with_max_link_speed(LinkSpeed::Speed32_0GtS)
156 .with_max_link_width(LinkWidth::X16)
157 .with_aspm_optionality_compliance(true),
158 slot_capabilities: pci_express::SlotCapabilities::new(),
159 root_capabilities: pci_express::RootCapabilities::new(),
160 device_capabilities_2: pci_express::DeviceCapabilities2::new()
161 .with_ari_forwarding_supported(ari_forwarding_supported),
162 link_capabilities_2: pci_express::LinkCapabilities2::new()
163 .with_supported_link_speeds_vector(SupportedLinkSpeedsVector::UpToGen5), slot_capabilities_2: pci_express::SlotCapabilities2::new(),
165 state: Arc::new(Mutex::new(PciExpressState::new())),
166 flr_handler,
167 }
168 }
169
170 fn handle_device_control_status_write(&mut self, val: ByteEnabledDwordWrite) {
171 let mut state = self.state.lock();
173 let new_control = pci_express::DeviceControl::from_bits(
174 val.merge_low(state.registers.device_control.into_bits()),
175 );
176
177 if new_control.initiate_function_level_reset()
178 && self.device_capabilities.function_level_reset()
179 {
180 if let Some(handler) = &self.flr_handler {
181 handler.initiate_flr();
182 }
183 }
184
185 state.registers.device_control = pci_express::DeviceControl::from_bits(
186 new_control.into_bits() & self.device_control_writable_mask(),
187 );
188 }
189
190 fn device_control_writable_mask(&self) -> u16 {
191 pci_express::DeviceControl::new()
192 .with_correctable_error_reporting_enable(true)
193 .with_non_fatal_error_reporting_enable(true)
194 .with_fatal_error_reporting_enable(true)
195 .with_unsupported_request_reporting_enable(true)
196 .with_enable_relaxed_ordering(true)
197 .with_max_payload_size(0b111)
198 .with_extended_tag_enable(self.device_capabilities.ext_tag_field())
199 .with_phantom_functions_enable(self.device_capabilities.phantom_functions() != 0)
200 .with_enable_no_snoop(true)
201 .with_max_read_request_size(0b111)
202 .into_bits()
203 }
204
205 fn handle_slot_control_status_write(&mut self, val: ByteEnabledDwordWrite) {
206 let mut state = self.state.lock();
208
209 let new_slot_control = pci_express::SlotControl::from_bits(
210 val.merge_low(state.registers.slot_control.into_bits()),
211 );
212
213 state.registers.slot_control = pci_express::SlotControl::from_bits(
214 new_slot_control.into_bits() & self.slot_control_writable_mask(),
215 );
216
217 let written_status = pci_express::SlotStatus::from_bits(val.extract_high());
218 state.registers.slot_status_events = pci_express::SlotStatus::from_bits(
219 state.registers.slot_status_events.into_bits()
220 & !(written_status.into_bits() & self.slot_status_rw1c_mask()),
221 );
222 }
223
224 fn slot_control_writable_mask(&self) -> u16 {
225 let slot_implemented = self.pcie_capabilities.slot_implemented();
226 let hotplug_capable = slot_implemented && self.slot_capabilities.hot_plug_capable();
227 pci_express::SlotControl::new()
228 .with_attention_button_pressed_enable(
229 slot_implemented && self.slot_capabilities.attention_button_present(),
230 )
231 .with_power_fault_detected_enable(
232 slot_implemented && self.slot_capabilities.power_controller_present(),
233 )
234 .with_mrl_sensor_changed_enable(
235 slot_implemented && self.slot_capabilities.mrl_sensor_present(),
236 )
237 .with_presence_detect_changed_enable(hotplug_capable)
238 .with_command_completed_interrupt_enable(
239 hotplug_capable && !self.slot_capabilities.no_command_completed_support(),
240 )
241 .with_hot_plug_interrupt_enable(hotplug_capable)
242 .with_attention_indicator_control(
243 if slot_implemented && self.slot_capabilities.attention_indicator_present() {
244 0b11
245 } else {
246 0
247 },
248 )
249 .with_power_indicator_control(
250 if slot_implemented && self.slot_capabilities.power_indicator_present() {
251 0b11
252 } else {
253 0
254 },
255 )
256 .with_power_controller_control(
257 slot_implemented && self.slot_capabilities.power_controller_present(),
258 )
259 .with_data_link_layer_state_changed_enable(
260 self.link_capabilities
261 .data_link_layer_link_active_reporting(),
262 )
263 .with_in_band_pd_disable(
264 slot_implemented && self.slot_capabilities_2.in_band_pd_disable_supported(),
265 )
266 .into_bits()
267 }
268
269 fn slot_status_rw1c_mask(&self) -> u16 {
270 let slot_implemented = self.pcie_capabilities.slot_implemented();
271 let hotplug_capable = slot_implemented && self.slot_capabilities.hot_plug_capable();
272 pci_express::SlotStatus::new()
273 .with_attention_button_pressed(
274 slot_implemented && self.slot_capabilities.attention_button_present(),
275 )
276 .with_power_fault_detected(
277 slot_implemented && self.slot_capabilities.power_controller_present(),
278 )
279 .with_mrl_sensor_changed(
280 slot_implemented && self.slot_capabilities.mrl_sensor_present(),
281 )
282 .with_presence_detect_changed(hotplug_capable)
283 .with_command_completed(
284 hotplug_capable && !self.slot_capabilities.no_command_completed_support(),
285 )
286 .with_data_link_layer_state_changed(
287 self.link_capabilities
288 .data_link_layer_link_active_reporting(),
289 )
290 .into_bits()
291 }
292
293 fn handle_link_control_status_write(&mut self, val: ByteEnabledDwordWrite) {
294 let mut state = self.state.lock();
296
297 let new_link_control = pci_express::LinkControl::from_bits(
298 val.merge_low(state.registers.link_control.into_bits()),
299 );
300
301 state.registers.link_control = pci_express::LinkControl::from_bits(
302 new_link_control.into_bits() & self.link_control_writable_mask(),
303 );
304 }
305
306 fn link_control_writable_mask(&self) -> u16 {
307 let port_type = self.pcie_capabilities.device_port_type();
308 let downstream_port = Self::is_downstream_port(port_type);
309 pci_express::LinkControl::new()
313 .with_aspm_control(0b11)
314 .with_read_completion_boundary(matches!(
315 port_type,
316 pci_express::DevicePortType::Endpoint
317 ) as u16)
318 .with_common_clock_configuration(true)
319 .with_extended_synch(true)
320 .with_enable_clock_power_management(
321 matches!(
322 port_type,
323 pci_express::DevicePortType::Endpoint
324 | pci_express::DevicePortType::UpstreamSwitchPort
325 ) && self.link_capabilities.clock_power_management(),
326 )
327 .with_link_bandwidth_management_interrupt_enable(
328 downstream_port
329 && self
330 .link_capabilities
331 .link_bandwidth_notification_capability(),
332 )
333 .with_link_autonomous_bandwidth_interrupt_enable(
334 downstream_port
335 && self
336 .link_capabilities
337 .link_bandwidth_notification_capability(),
338 )
339 .with_drs_signaling_control(
340 if downstream_port && self.link_capabilities_2.drs_supported() {
341 0b11
342 } else {
343 0
344 },
345 )
346 .into_bits()
347 }
348
349 fn handle_link_control_2_write(&mut self, val: ByteEnabledDwordWrite) {
350 let mut state = self.state.lock();
352
353 let new_link_control_2 = pci_express::LinkControl2::from_bits(
354 val.merge_low(state.registers.link_control_2.into_bits()),
355 );
356
357 state.registers.link_control_2 = pci_express::LinkControl2::from_bits(
358 new_link_control_2.into_bits() & Self::link_control_2_writable_mask(),
359 );
360 }
361
362 fn link_control_2_writable_mask() -> u16 {
363 pci_express::LinkControl2::new()
364 .with_target_link_speed(LinkSpeed::from_bits(0b1111))
365 .with_enter_compliance(true)
366 .with_hardware_autonomous_speed_disable(true)
367 .with_transmit_margin(0b111)
368 .with_enter_modified_compliance(true)
369 .with_compliance_sos(true)
370 .with_compliance_preset_de_emphasis(0b1111)
371 .into_bits()
372 }
373
374 fn root_control_writable_mask(&self) -> u16 {
375 let root_port =
376 self.pcie_capabilities.device_port_type() == pci_express::DevicePortType::RootPort;
377 pci_express::RootControl::new()
378 .with_system_error_on_correctable_error_enable(root_port)
379 .with_system_error_on_non_fatal_error_enable(root_port)
380 .with_system_error_on_fatal_error_enable(root_port)
381 .with_pme_interrupt_enable(root_port)
382 .with_crs_software_visibility_enable(
383 root_port && self.root_capabilities.crs_software_visibility(),
384 )
385 .into_bits()
386 }
387
388 fn device_control_2_writable_mask(&self) -> u16 {
389 pci_express::DeviceControl2::new()
390 .with_ari_forwarding_enable(self.device_capabilities_2.ari_forwarding_supported())
391 .into_bits()
392 }
393
394 fn is_downstream_port(port_type: pci_express::DevicePortType) -> bool {
395 matches!(
396 port_type,
397 pci_express::DevicePortType::RootPort
398 | pci_express::DevicePortType::DownstreamSwitchPort
399 )
400 }
401
402 pub fn with_hotplug_support(mut self, slot_number: u32) -> Self {
409 let port_type = self.pcie_capabilities.device_port_type();
410 assert!(
411 Self::is_downstream_port(port_type),
412 "Hotplug support is not valid for device port type {port_type:?}. \
413 Only RootPort and DownstreamSwitchPort support hotplug."
414 );
415
416 self.pcie_capabilities = self.pcie_capabilities.with_slot_implemented(true);
418
419 self.slot_capabilities = self
434 .slot_capabilities
435 .with_hot_plug_surprise(true)
436 .with_hot_plug_capable(true)
437 .with_no_command_completed_support(true)
438 .with_physical_slot_number(slot_number);
439
440 self.link_capabilities = self
442 .link_capabilities
443 .with_data_link_layer_link_active_reporting(true);
444
445 self
446 }
447
448 pub fn with_tlp_prefixing_supported(mut self, max_prefixes: MaxEndEndTlpPrefixes) -> Self {
455 self.device_capabilities_2 = self
456 .device_capabilities_2
457 .with_extended_fmt_field_supported(true)
458 .with_end_end_tlp_prefix_supported(true)
459 .with_max_end_end_tlp_prefixes(max_prefixes);
460 self
461 }
462
463 pub fn set_presence_detect_state(&self, present: bool) {
468 let mut state = self.state.lock();
469 state.presence_detect_state = present;
470 }
471
472 pub fn set_hotplug_changed_bits(&self) {
475 if !self.pcie_capabilities.slot_implemented() || !self.slot_capabilities.hot_plug_capable()
476 {
477 return;
478 }
479
480 let mut state = self.state.lock();
481 state
482 .registers
483 .slot_status_events
484 .set_presence_detect_changed(true);
485 state
486 .registers
487 .slot_status_events
488 .set_data_link_layer_state_changed(true);
489 }
490
491 pub fn set_hotplug_state(&self, present: bool) {
494 if !self.pcie_capabilities.slot_implemented() || !self.slot_capabilities.hot_plug_capable()
495 {
496 return;
497 }
498
499 let mut state = self.state.lock();
500 if state.presence_detect_state == present {
501 return;
502 }
503 state.presence_detect_state = present;
504
505 state
506 .registers
507 .slot_status_events
508 .set_presence_detect_changed(true);
509 state
510 .registers
511 .slot_status_events
512 .set_data_link_layer_state_changed(true);
513 }
514
515 pub fn hot_plug_interrupt_enabled(&self) -> bool {
517 self.state
518 .lock()
519 .registers
520 .slot_control
521 .hot_plug_interrupt_enable()
522 }
523
524 pub fn ari_forwarding_enable(&self) -> bool {
532 self.state
533 .lock()
534 .registers
535 .device_control_2
536 .ari_forwarding_enable()
537 }
538
539 pub fn slot_capabilities(&self) -> &pci_express::SlotCapabilities {
541 &self.slot_capabilities
542 }
543}
544
545impl PciCapability for PciExpressCapability {
546 fn label(&self) -> &str {
547 "pci-express"
548 }
549
550 fn capability_id(&self) -> CapabilityId {
551 CapabilityId::PCI_EXPRESS
552 }
553
554 fn len(&self) -> usize {
555 0x3C
573 }
574
575 fn read(&self, offset: u16, mut value: ByteEnabledDwordRead<'_>) {
576 let state = self.state.lock();
577 let label = self.label();
578 match PciExpressCapabilityHeader(offset) {
579 PciExpressCapabilityHeader::PCIE_CAPS => {
580 value.set_low_high(
582 CapabilityId::PCI_EXPRESS.0.into(),
583 self.pcie_capabilities.into_bits(),
584 )
585 }
586 PciExpressCapabilityHeader::DEVICE_CAPS => {
587 value.set(self.device_capabilities.into_bits())
588 }
589 PciExpressCapabilityHeader::DEVICE_CTL_STS => {
590 value.set_low_high(state.registers.device_control.into_bits(), 0);
592 }
593 PciExpressCapabilityHeader::LINK_CAPS => value.set(self.link_capabilities.into_bits()),
594 PciExpressCapabilityHeader::LINK_CTL_STS => {
595 value.set_low_high(
597 state.registers.link_control.into_bits(),
598 state.link_status().into_bits(),
599 );
600 }
601 PciExpressCapabilityHeader::SLOT_CAPS => value.set(self.slot_capabilities.into_bits()),
602 PciExpressCapabilityHeader::SLOT_CTL_STS => {
603 value.set_low_high(
605 state.registers.slot_control.into_bits(),
606 state
607 .slot_status(
608 self.pcie_capabilities.slot_implemented(),
609 Self::is_downstream_port(self.pcie_capabilities.device_port_type()),
610 )
611 .into_bits(),
612 );
613 }
614 PciExpressCapabilityHeader::ROOT_CTL_CAPS => {
615 value.set_low_high(
617 state.registers.root_control.into_bits(),
618 self.root_capabilities.into_bits(),
619 );
620 }
621 PciExpressCapabilityHeader::ROOT_STS => {
622 value.set(0);
623 }
624 PciExpressCapabilityHeader::DEVICE_CAPS_2 => {
625 value.set(self.device_capabilities_2.into_bits())
626 }
627 PciExpressCapabilityHeader::DEVICE_CTL_STS_2 => {
628 value.set_low_high(state.registers.device_control_2.into_bits(), 0);
630 }
631 PciExpressCapabilityHeader::LINK_CAPS_2 => {
632 value.set(self.link_capabilities_2.into_bits())
633 }
634 PciExpressCapabilityHeader::LINK_CTL_STS_2 => {
635 value.set_low_high(state.registers.link_control_2.into_bits(), 0);
637 }
638 PciExpressCapabilityHeader::SLOT_CAPS_2 => {
639 value.set(self.slot_capabilities_2.into_bits())
640 }
641 PciExpressCapabilityHeader::SLOT_CTL_STS_2 => {
642 value.set(0);
643 }
644 _ => {
645 tracelimit::warn_ratelimited!(
646 ?label,
647 offset,
648 "unhandled pci express capability read"
649 );
650 value.set(0);
651 }
652 }
653 }
654
655 fn write(&mut self, offset: u16, val: ByteEnabledDwordWrite) {
656 let label = self.label();
657 match PciExpressCapabilityHeader(offset) {
658 PciExpressCapabilityHeader::PCIE_CAPS => {
659 tracelimit::warn_ratelimited!(
661 ?label,
662 offset,
663 ?val,
664 "write to read-only pcie capabilities"
665 );
666 }
667 PciExpressCapabilityHeader::DEVICE_CAPS => {
668 tracelimit::warn_ratelimited!(
670 ?label,
671 offset,
672 ?val,
673 "write to read-only device capabilities"
674 );
675 }
676 PciExpressCapabilityHeader::DEVICE_CTL_STS => {
677 self.handle_device_control_status_write(val);
678 }
679 PciExpressCapabilityHeader::LINK_CAPS => {
680 tracelimit::warn_ratelimited!(
682 ?label,
683 offset,
684 ?val,
685 "write to read-only link capabilities"
686 );
687 }
688 PciExpressCapabilityHeader::LINK_CTL_STS => {
689 self.handle_link_control_status_write(val);
690 }
691 PciExpressCapabilityHeader::SLOT_CAPS => {
692 tracelimit::warn_ratelimited!(
694 ?label,
695 offset,
696 ?val,
697 "write to read-only slot capabilities"
698 );
699 }
700 PciExpressCapabilityHeader::SLOT_CTL_STS => {
701 self.handle_slot_control_status_write(val);
702 }
703 PciExpressCapabilityHeader::ROOT_CTL_CAPS => {
704 let mut state = self.state.lock();
706 let new_control = pci_express::RootControl::from_bits(
707 val.merge_low(state.registers.root_control.into_bits()),
708 );
709 state.registers.root_control = pci_express::RootControl::from_bits(
710 new_control.into_bits() & self.root_control_writable_mask(),
711 );
712 }
714 PciExpressCapabilityHeader::ROOT_STS => {
715 }
717 PciExpressCapabilityHeader::DEVICE_CAPS_2 => {
718 tracelimit::warn_ratelimited!(
720 ?label,
721 offset,
722 ?val,
723 "write to read-only device capabilities 2"
724 );
725 }
726 PciExpressCapabilityHeader::DEVICE_CTL_STS_2 => {
727 let mut state = self.state.lock();
729 let new_control = pci_express::DeviceControl2::from_bits(
730 val.merge_low(state.registers.device_control_2.into_bits()),
731 );
732 state.registers.device_control_2 = pci_express::DeviceControl2::from_bits(
733 new_control.into_bits() & self.device_control_2_writable_mask(),
734 );
735 }
736 PciExpressCapabilityHeader::LINK_CAPS_2 => {
737 tracelimit::warn_ratelimited!(
739 ?label,
740 offset,
741 ?val,
742 "write to read-only link capabilities 2"
743 );
744 }
745 PciExpressCapabilityHeader::LINK_CTL_STS_2 => {
746 self.handle_link_control_2_write(val);
747 }
748 PciExpressCapabilityHeader::SLOT_CAPS_2 => {
749 tracelimit::warn_ratelimited!(
751 ?label,
752 offset,
753 ?val,
754 "write to read-only slot capabilities 2"
755 );
756 }
757 PciExpressCapabilityHeader::SLOT_CTL_STS_2 => {
758 }
760 _ => {
761 tracelimit::warn_ratelimited!(
762 ?label,
763 offset,
764 ?val,
765 "unhandled pci express capability write"
766 );
767 }
768 }
769 }
770
771 fn reset(&mut self) {
772 let mut state = self.state.lock();
773 state.reset_registers();
774 }
775
776 fn as_pci_express(&self) -> Option<&PciExpressCapability> {
777 Some(self)
778 }
779
780 fn as_pci_express_mut(&mut self) -> Option<&mut PciExpressCapability> {
781 Some(self)
782 }
783}
784
785mod save_restore {
786 use super::*;
787 use vmcore::save_restore::RestoreError;
788 use vmcore::save_restore::SaveError;
789 use vmcore::save_restore::SaveRestore;
790
791 mod state {
792 use mesh::payload::Protobuf;
793 use vmcore::save_restore::SavedStateRoot;
794
795 #[derive(Protobuf, SavedStateRoot)]
796 #[mesh(package = "pci.capabilities.pci_express")]
797 pub struct SavedState {
798 #[mesh(1)]
799 pub device_control: u16,
800 #[mesh(2)]
801 pub link_control: u16,
802 #[mesh(3)]
803 pub slot_control: u16,
804 #[mesh(4)]
805 pub slot_status_events: u16,
806 #[mesh(5)]
807 pub root_control: u16,
808 #[mesh(6)]
809 pub device_control_2: u16,
810 #[mesh(7)]
811 pub link_control_2: u16,
812 }
813 }
814
815 impl SaveRestore for PciExpressCapability {
816 type SavedState = state::SavedState;
817
818 fn save(&mut self) -> Result<Self::SavedState, SaveError> {
819 let state = self.state.lock();
820 let PciExpressState {
821 registers,
822 presence_detect_state: _,
823 } = &*state;
824 let PciExpressRegisters {
825 device_control,
826 link_control,
827 slot_control,
828 slot_status_events,
829 root_control,
830 device_control_2,
831 link_control_2,
832 } = registers;
833 Ok(state::SavedState {
834 device_control: device_control.into_bits(),
835 link_control: link_control.into_bits(),
836 slot_control: slot_control.into_bits(),
837 slot_status_events: slot_status_events.into_bits(),
838 root_control: root_control.into_bits(),
839 device_control_2: device_control_2.into_bits(),
840 link_control_2: link_control_2.into_bits(),
841 })
842 }
843
844 fn restore(&mut self, saved: Self::SavedState) -> Result<(), RestoreError> {
845 let state::SavedState {
846 device_control,
847 link_control,
848 slot_control,
849 slot_status_events,
850 root_control,
851 device_control_2,
852 link_control_2,
853 } = saved;
854 let mut state = self.state.lock();
855 let PciExpressState {
856 registers,
857 presence_detect_state: _,
858 } = &mut *state;
859 *registers = PciExpressRegisters {
860 device_control: pci_express::DeviceControl::from_bits(
861 device_control & self.device_control_writable_mask(),
862 ),
863 link_control: pci_express::LinkControl::from_bits(
864 link_control & self.link_control_writable_mask(),
865 ),
866 slot_control: pci_express::SlotControl::from_bits(
867 slot_control & self.slot_control_writable_mask(),
868 ),
869 slot_status_events: pci_express::SlotStatus::from_bits(
870 slot_status_events & self.slot_status_rw1c_mask(),
871 ),
872 root_control: pci_express::RootControl::from_bits(
873 root_control & self.root_control_writable_mask(),
874 ),
875 device_control_2: pci_express::DeviceControl2::from_bits(
876 device_control_2 & self.device_control_2_writable_mask(),
877 ),
878 link_control_2: pci_express::LinkControl2::from_bits(
879 link_control_2 & Self::link_control_2_writable_mask(),
880 ),
881 };
882 Ok(())
883 }
884 }
885}
886
887#[cfg(test)]
888mod tests {
889 use super::*;
890 use crate::spec::caps::pci_express::DevicePortType;
891 use crate::test_helpers::read_cap_u32;
892 use crate::test_helpers::write_cap_u32;
893 use chipset_device::pci::ByteEnabledDwordWrite;
894 use chipset_device::pci::PciConfigByteEnable;
895 use std::sync::atomic::AtomicBool;
896 use std::sync::atomic::Ordering;
897
898 #[derive(Debug)]
899 struct TestFlrHandler {
900 flr_initiated: AtomicBool,
901 }
902
903 impl TestFlrHandler {
904 fn new() -> Arc<Self> {
905 Arc::new(Self {
906 flr_initiated: AtomicBool::new(false),
907 })
908 }
909
910 fn was_flr_initiated(&self) -> bool {
911 self.flr_initiated.load(Ordering::Acquire)
912 }
913
914 fn reset(&self) {
915 self.flr_initiated.store(false, Ordering::Release);
916 }
917 }
918
919 impl FlrHandler for TestFlrHandler {
920 fn initiate_flr(&self) {
921 self.flr_initiated.store(true, Ordering::Release);
922 }
923 }
924
925 impl Inspect for TestFlrHandler {
926 fn inspect(&self, req: inspect::Request<'_>) {
927 req.respond()
928 .field("flr_initiated", self.flr_initiated.load(Ordering::Acquire));
929 }
930 }
931
932 #[test]
933 fn test_ari_forwarding_supported_by_port_type() {
934 for (typ, expected) in [
937 (DevicePortType::RootPort, true),
938 (DevicePortType::DownstreamSwitchPort, true),
939 (DevicePortType::UpstreamSwitchPort, false),
940 (DevicePortType::Endpoint, false),
941 ] {
942 let name = format!("{typ:?}");
943 let cap = PciExpressCapability::new(typ, None);
944 let device_caps_2 = read_cap_u32(&cap, 0x24);
945 let ari_supported = device_caps_2 & 0x20 != 0;
946 assert_eq!(ari_supported, expected, "unexpected ARI support for {name}");
947 }
948 }
949
950 #[test]
951 fn test_ari_forwarding_enable_is_guest_writable() {
952 let mut cap = PciExpressCapability::new(DevicePortType::RootPort, None);
953
954 assert!(!cap.ari_forwarding_enable());
956
957 write_cap_u32(&mut cap, 0x28, 0x0020);
959 assert!(cap.ari_forwarding_enable());
960 assert_eq!(read_cap_u32(&cap, 0x28) & 0x0020, 0x0020);
961
962 write_cap_u32(&mut cap, 0x28, 0x0000);
964 assert!(!cap.ari_forwarding_enable());
965 }
966
967 #[test]
968 fn test_tlp_prefixing_supported_max_prefixes() {
969 for max_prefixes in [
970 MaxEndEndTlpPrefixes::One,
971 MaxEndEndTlpPrefixes::Two,
972 MaxEndEndTlpPrefixes::Three,
973 MaxEndEndTlpPrefixes::Four,
974 ] {
975 let cap = PciExpressCapability::new(DevicePortType::Endpoint, None)
976 .with_tlp_prefixing_supported(max_prefixes);
977 let device_caps_2 =
978 pci_express::DeviceCapabilities2::from_bits(read_cap_u32(&cap, 0x24));
979
980 assert!(device_caps_2.extended_fmt_field_supported());
981 assert!(device_caps_2.end_end_tlp_prefix_supported());
982 assert_eq!(
983 device_caps_2.max_end_end_tlp_prefixes().into_bits(),
984 max_prefixes.into_bits(),
985 "unexpected max TLP prefix encoding for {max_prefixes:?}"
986 );
987 }
988 }
989
990 #[test]
991 fn test_pci_express_capability_read_endpoint() {
992 let flr_handler = TestFlrHandler::new();
993 let cap = PciExpressCapability::new(DevicePortType::Endpoint, Some(flr_handler));
994
995 let caps_val = read_cap_u32(&cap, 0x00);
997 assert_eq!(caps_val & 0xFF, 0x10); assert_eq!((caps_val >> 8) & 0xFF, 0x00); assert_eq!((caps_val >> 16) & 0xFFFF, 0x0002); let device_caps_val = read_cap_u32(&cap, 0x04);
1003 assert_eq!(
1004 device_caps_val & PCI_EXPRESS_DEVICE_CAPS_FLR_BIT_MASK,
1005 PCI_EXPRESS_DEVICE_CAPS_FLR_BIT_MASK
1006 ); let device_ctl_sts_val = read_cap_u32(&cap, 0x08);
1010 assert_eq!(device_ctl_sts_val, 0x2810);
1011
1012 let link_ctl_sts_val = read_cap_u32(&cap, 0x10);
1014 let expected_link_status = (LinkSpeed::Speed32_0GtS.into_bits() as u16)
1015 | ((LinkWidth::X16.into_bits() as u16) << 4); assert_eq!(link_ctl_sts_val, (expected_link_status as u32) << 16); }
1018
1019 #[test]
1020 fn test_pci_express_capability_read_root_port() {
1021 let cap = PciExpressCapability::new(DevicePortType::RootPort, None);
1022
1023 let caps_val = read_cap_u32(&cap, 0x00);
1025 assert_eq!(caps_val & 0xFF, 0x10); assert_eq!((caps_val >> 8) & 0xFF, 0x00); assert_eq!((caps_val >> 16) & 0xFFFF, 0x0042); }
1029
1030 #[test]
1031 fn test_pcie_open_enums_preserve_reserved_values() {
1032 assert_eq!(LinkSpeed::from_bits(0).into_bits(), 0);
1033 assert_eq!(LinkWidth::from_bits(0b11_1111).into_bits(), 0b11_1111);
1034 assert_eq!(
1035 SupportedLinkSpeedsVector::from_bits(0b101_0101).into_bits(),
1036 0b101_0101
1037 );
1038
1039 let unknown_port_type = DevicePortType(0b1111);
1040 let capabilities =
1041 pci_express::PciExpressCapabilities::new().with_device_port_type(unknown_port_type);
1042 assert_eq!(capabilities.device_port_type(), unknown_port_type);
1043 }
1044
1045 #[test]
1046 fn test_pci_express_capability_read_no_flr() {
1047 let cap = PciExpressCapability::new(DevicePortType::Endpoint, None);
1048
1049 let device_caps_val = read_cap_u32(&cap, 0x04);
1051 assert_eq!(device_caps_val & PCI_EXPRESS_DEVICE_CAPS_FLR_BIT_MASK, 0);
1052 }
1053
1054 #[test]
1055 fn test_flr_is_only_advertised_by_endpoints() {
1056 let flr_handler = TestFlrHandler::new();
1057 let mut cap =
1058 PciExpressCapability::new(DevicePortType::RootPort, Some(flr_handler.clone()));
1059
1060 assert_eq!(
1061 read_cap_u32(&cap, 0x04) & PCI_EXPRESS_DEVICE_CAPS_FLR_BIT_MASK,
1062 0
1063 );
1064 write_cap_u32(&mut cap, 0x08, 0x8000);
1065 assert!(!flr_handler.was_flr_initiated());
1066 }
1067
1068 #[test]
1069 fn test_pci_express_capability_write_readonly_registers() {
1070 let mut cap = PciExpressCapability::new(DevicePortType::RootPort, None);
1071
1072 let original_caps = read_cap_u32(&cap, 0x00);
1074 write_cap_u32(&mut cap, 0x00, 0xFFFFFFFF);
1075 assert_eq!(read_cap_u32(&cap, 0x00), original_caps); let original_device_caps = read_cap_u32(&cap, 0x04);
1079 write_cap_u32(&mut cap, 0x04, 0xFFFFFFFF);
1080 assert_eq!(read_cap_u32(&cap, 0x04), original_device_caps); }
1082
1083 #[test]
1084 fn test_pci_express_capability_write_device_control() {
1085 let flr_handler = TestFlrHandler::new();
1086 let mut cap =
1087 PciExpressCapability::new(DevicePortType::Endpoint, Some(flr_handler.clone()));
1088
1089 let initial_ctl_sts = read_cap_u32(&cap, 0x08);
1091 assert_eq!(initial_ctl_sts & 0xFFFF, 0x2810);
1092
1093 write_cap_u32(&mut cap, 0x08, 0x0001); let device_ctl_sts = read_cap_u32(&cap, 0x08);
1097 assert_eq!(device_ctl_sts & 0xFFFF, 0x0001); assert!(!flr_handler.was_flr_initiated()); flr_handler.reset();
1102 write_cap_u32(&mut cap, 0x08, 0x8001); let device_ctl_sts_after_flr = read_cap_u32(&cap, 0x08);
1104 assert_eq!(device_ctl_sts_after_flr & 0xFFFF, 0x0001); assert!(flr_handler.was_flr_initiated()); flr_handler.reset();
1109 write_cap_u32(&mut cap, 0x08, 0x8000); let device_ctl_sts_final = read_cap_u32(&cap, 0x08);
1113 assert_eq!(device_ctl_sts_final & 0xFFFF, 0x0000); assert!(flr_handler.was_flr_initiated()); }
1116
1117 #[test]
1118 fn test_unimplemented_status_registers_ignore_writes() {
1119 let mut cap = PciExpressCapability::new(DevicePortType::Endpoint, None);
1120
1121 write_cap_u32(&mut cap, 0x08, 0xffff_0000);
1122 write_cap_u32(&mut cap, 0x20, 0xffff_ffff);
1123 write_cap_u32(&mut cap, 0x28, 0xffff_0000);
1124 write_cap_u32(&mut cap, 0x30, 0xffff_0000);
1125 write_cap_u32(&mut cap, 0x38, 0xffff_ffff);
1126
1127 assert_eq!(read_cap_u32(&cap, 0x08) >> 16, 0);
1128 assert_eq!(read_cap_u32(&cap, 0x20), 0);
1129 assert_eq!(read_cap_u32(&cap, 0x28) >> 16, 0);
1130 assert_eq!(read_cap_u32(&cap, 0x30) >> 16, 0);
1131 assert_eq!(read_cap_u32(&cap, 0x38), 0);
1132 }
1133
1134 #[test]
1135 fn test_unsupported_control_fields_ignore_all_ones_write() {
1136 let mut root_port = PciExpressCapability::new(DevicePortType::RootPort, None);
1137
1138 write_cap_u32(&mut root_port, 0x08, u32::MAX);
1139 write_cap_u32(&mut root_port, 0x10, u32::MAX);
1140 write_cap_u32(&mut root_port, 0x1c, u32::MAX);
1141 write_cap_u32(&mut root_port, 0x28, u32::MAX);
1142 write_cap_u32(&mut root_port, 0x30, u32::MAX);
1143
1144 assert_eq!(read_cap_u32(&root_port, 0x08), 0x0000_78ff);
1145 assert_eq!(read_cap_u32(&root_port, 0x10) & 0xffff, 0x00c3);
1146 assert_eq!(read_cap_u32(&root_port, 0x1c), 0x0000_000f);
1147 assert_eq!(read_cap_u32(&root_port, 0x28), 0x0000_0020);
1148 assert_eq!(read_cap_u32(&root_port, 0x30), 0x0000_ffbf);
1149
1150 let mut endpoint = PciExpressCapability::new(DevicePortType::Endpoint, None);
1151 write_cap_u32(&mut endpoint, 0x10, u32::MAX);
1152 write_cap_u32(&mut endpoint, 0x1c, u32::MAX);
1153 write_cap_u32(&mut endpoint, 0x28, u32::MAX);
1154 assert_eq!(read_cap_u32(&endpoint, 0x10) & 0xffff, 0x00cb);
1155 assert_eq!(read_cap_u32(&endpoint, 0x1c), 0);
1156 assert_eq!(read_cap_u32(&endpoint, 0x28), 0);
1157 }
1158
1159 #[test]
1160 fn test_pci_express_capability_byte_write_control() {
1161 let mut cap = PciExpressCapability::new(DevicePortType::Endpoint, None);
1162
1163 cap.write(
1164 0x08,
1165 ByteEnabledDwordWrite::new(
1166 0x0000_0001,
1167 PciConfigByteEnable::from_offset_len(0x08, 1).unwrap(),
1168 ),
1169 );
1170
1171 let device_ctl_sts = read_cap_u32(&cap, 0x08);
1172 assert_eq!(device_ctl_sts & 0xffff, 0x2801);
1173 assert_eq!(device_ctl_sts & 0xffff_0000, 0);
1174
1175 cap.write(
1176 0x08,
1177 ByteEnabledDwordWrite::new(
1178 0x0001_0000,
1179 PciConfigByteEnable::from_offset_len(0x08, 1).unwrap(),
1180 ),
1181 );
1182
1183 let status_after = read_cap_u32(&cap, 0x08) & 0xffff_0000;
1184 assert_eq!(status_after, 0);
1185 }
1186
1187 #[test]
1188 fn test_pci_express_capability_write_unhandled_offset() {
1189 let mut cap = PciExpressCapability::new(DevicePortType::Endpoint, None);
1190
1191 write_cap_u32(&mut cap, 0x10, 0xFFFFFFFF);
1193 assert_eq!(read_cap_u32(&cap, 0x08), 0x2810);
1195 }
1196
1197 #[test]
1198 fn test_pci_express_capability_reset() {
1199 let mut cap =
1200 PciExpressCapability::new(DevicePortType::RootPort, None).with_hotplug_support(1);
1201 cap.set_presence_detect_state(true);
1202
1203 write_cap_u32(&mut cap, 0x08, 0x0001); let device_ctl_sts = read_cap_u32(&cap, 0x08);
1208 assert_ne!(device_ctl_sts, 0);
1209 let slot_status =
1210 pci_express::SlotStatus::from_bits((read_cap_u32(&cap, 0x18) >> 16) as u16);
1211 let link_status =
1212 pci_express::LinkStatus::from_bits((read_cap_u32(&cap, 0x10) >> 16) as u16);
1213 assert_eq!(slot_status.presence_detect_state(), 1);
1214 assert!(link_status.data_link_layer_link_active());
1215
1216 cap.reset();
1218
1219 let device_ctl_sts_after_reset = read_cap_u32(&cap, 0x08);
1222 assert_eq!(device_ctl_sts_after_reset, 0x2810);
1223 let slot_status =
1224 pci_express::SlotStatus::from_bits((read_cap_u32(&cap, 0x18) >> 16) as u16);
1225 let link_status =
1226 pci_express::LinkStatus::from_bits((read_cap_u32(&cap, 0x10) >> 16) as u16);
1227 assert_eq!(slot_status.presence_detect_state(), 1);
1228 assert!(link_status.data_link_layer_link_active());
1229 }
1230
1231 #[test]
1232 fn test_pci_express_capability_extended_registers() {
1233 let cap = PciExpressCapability::new(DevicePortType::Endpoint, None);
1234
1235 let expected_link_caps =
1238 LinkSpeed::Speed32_0GtS.into_bits() | (LinkWidth::X16.into_bits() << 4) | (1 << 22);
1239 assert_eq!(read_cap_u32(&cap, 0x0C), expected_link_caps); let expected_link_ctl_sts = (LinkSpeed::Speed32_0GtS.into_bits() as u16)
1242 | ((LinkWidth::X16.into_bits() as u16) << 4); assert_eq!(
1244 read_cap_u32(&cap, 0x10),
1245 (expected_link_ctl_sts as u32) << 16
1246 ); assert_eq!(read_cap_u32(&cap, 0x14), 0); assert_eq!(read_cap_u32(&cap, 0x18), 0); assert_eq!(read_cap_u32(&cap, 0x1C), 0); assert_eq!(read_cap_u32(&cap, 0x20), 0); assert_eq!(read_cap_u32(&cap, 0x24), 0); assert_eq!(read_cap_u32(&cap, 0x28), 0); let expected_link_caps_2 = SupportedLinkSpeedsVector::UpToGen5.into_bits() << 1; assert_eq!(read_cap_u32(&cap, 0x2C), expected_link_caps_2); let expected_link_ctl_sts_2 = LinkSpeed::Speed32_0GtS.into_bits() as u16; assert_eq!(read_cap_u32(&cap, 0x30), expected_link_ctl_sts_2 as u32); assert_eq!(read_cap_u32(&cap, 0x34), 0); assert_eq!(read_cap_u32(&cap, 0x38), 0); }
1262
1263 #[test]
1264 fn test_pci_express_capability_length() {
1265 let cap = PciExpressCapability::new(DevicePortType::Endpoint, None);
1266 assert_eq!(cap.len(), 0x3C); }
1268
1269 #[test]
1270 fn test_pci_express_capability_label() {
1271 let cap = PciExpressCapability::new(DevicePortType::Endpoint, None);
1272 assert_eq!(cap.label(), "pci-express");
1273 }
1274
1275 #[test]
1276 fn test_pci_express_capability_with_hotplug_support() {
1277 let cap = PciExpressCapability::new(DevicePortType::RootPort, None);
1279 let cap_with_hotplug = cap.with_hotplug_support(1);
1280
1281 assert_eq!(cap_with_hotplug.label(), "pci-express");
1283 assert_eq!(cap_with_hotplug.len(), 0x3C);
1284
1285 assert!(cap_with_hotplug.slot_capabilities.hot_plug_surprise());
1287 assert!(cap_with_hotplug.slot_capabilities.hot_plug_capable());
1288 assert_eq!(cap_with_hotplug.slot_capabilities.physical_slot_number(), 1);
1289
1290 assert!(
1292 cap_with_hotplug.pcie_capabilities.slot_implemented(),
1293 "slot_implemented should be true when hotplug is enabled"
1294 );
1295
1296 let cap2 = PciExpressCapability::new(DevicePortType::DownstreamSwitchPort, None);
1298 let cap2_with_hotplug = cap2.with_hotplug_support(2);
1299
1300 assert!(cap2_with_hotplug.slot_capabilities.hot_plug_surprise());
1301 assert!(cap2_with_hotplug.slot_capabilities.hot_plug_capable());
1302 assert_eq!(
1303 cap2_with_hotplug.slot_capabilities.physical_slot_number(),
1304 2
1305 );
1306
1307 assert!(
1309 cap2_with_hotplug.pcie_capabilities.slot_implemented(),
1310 "slot_implemented should be true when hotplug is enabled"
1311 );
1312
1313 let cap_no_hotplug = PciExpressCapability::new(DevicePortType::RootPort, None);
1315 assert!(
1316 !cap_no_hotplug.pcie_capabilities.slot_implemented(),
1317 "slot_implemented should be false when hotplug is not enabled"
1318 );
1319 }
1320
1321 #[test]
1322 #[should_panic(expected = "Hotplug support is not valid for device port type Endpoint")]
1323 fn test_pci_express_capability_with_hotplug_support_endpoint_panics() {
1324 let cap = PciExpressCapability::new(DevicePortType::Endpoint, None);
1325 cap.with_hotplug_support(1);
1326 }
1327
1328 #[test]
1329 #[should_panic(
1330 expected = "Hotplug support is not valid for device port type UpstreamSwitchPort"
1331 )]
1332 fn test_pci_express_capability_with_hotplug_support_upstream_panics() {
1333 let cap = PciExpressCapability::new(DevicePortType::UpstreamSwitchPort, None);
1334 cap.with_hotplug_support(1);
1335 }
1336
1337 #[test]
1338 fn test_slot_control_write_protection() {
1339 let mut cap = PciExpressCapability::new(DevicePortType::RootPort, None);
1341 cap = cap.with_hotplug_support(1);
1342
1343 cap.slot_capabilities.set_attention_button_present(false);
1345 cap.slot_capabilities.set_power_controller_present(false);
1346 cap.slot_capabilities.set_mrl_sensor_present(false);
1347 cap.slot_capabilities.set_attention_indicator_present(false);
1348 cap.slot_capabilities.set_power_indicator_present(false);
1349 cap.slot_capabilities
1350 .set_electromechanical_interlock_present(false);
1351 cap.slot_capabilities.set_no_command_completed_support(true);
1352
1353 let slot_ctl_sts_offset = 0x18; let val_to_write = 0xFFFFFFFF; write_cap_u32(&mut cap, slot_ctl_sts_offset, val_to_write);
1358
1359 let read_back = read_cap_u32(&cap, slot_ctl_sts_offset);
1361 let slot_control_value = read_back as u16;
1362 let slot_control = pci_express::SlotControl::from_bits(slot_control_value);
1363
1364 assert!(
1366 !slot_control.attention_button_pressed_enable(),
1367 "Attention button enable should be 0 when capability not present"
1368 );
1369 assert!(
1370 !slot_control.power_fault_detected_enable(),
1371 "Power fault enable should be 0 without a power controller"
1372 );
1373 assert!(
1374 !slot_control.power_controller_control(),
1375 "Power controller control should be 0 when capability not present"
1376 );
1377 assert!(
1378 !slot_control.mrl_sensor_changed_enable(),
1379 "MRL sensor changed enable should be 0 when capability not present"
1380 );
1381 assert_eq!(
1382 slot_control.attention_indicator_control(),
1383 0,
1384 "Attention indicator control should be 0 when capability not present"
1385 );
1386 assert_eq!(
1387 slot_control.power_indicator_control(),
1388 0,
1389 "Power indicator control should be 0 when capability not present"
1390 );
1391 assert!(
1392 !slot_control.electromechanical_interlock_control(),
1393 "Electromechanical interlock control should be 0 when capability not present"
1394 );
1395 assert!(
1396 !slot_control.command_completed_interrupt_enable(),
1397 "Command completed interrupt enable should be 0 when no command completed support"
1398 );
1399 assert!(!slot_control.auto_slot_power_limit_enable());
1400 assert!(!slot_control.in_band_pd_disable());
1401
1402 assert!(slot_control.presence_detect_changed_enable());
1404 assert!(
1405 slot_control.hot_plug_interrupt_enable(),
1406 "Hotplug interrupt enable should be settable when hotplug capable"
1407 );
1408 assert!(slot_control.data_link_layer_state_changed_enable());
1409 }
1410
1411 #[test]
1412 fn test_link_control_retrain_link_behavior() {
1413 let mut cap = PciExpressCapability::new(DevicePortType::RootPort, None);
1415
1416 let link_ctl_sts_offset = 0x10; let write_val = 0x0020; write_cap_u32(&mut cap, link_ctl_sts_offset, write_val);
1421
1422 let read_back = read_cap_u32(&cap, link_ctl_sts_offset);
1424 let link_control = pci_express::LinkControl::from_bits(read_back as u16);
1425
1426 assert!(
1427 !link_control.retrain_link(),
1428 "retrain_link should always read as 0"
1429 );
1430
1431 let write_val_2 = 0x0001; write_cap_u32(&mut cap, link_ctl_sts_offset, write_val_2);
1434
1435 let read_back_2 = read_cap_u32(&cap, link_ctl_sts_offset);
1436 let link_control_2 = pci_express::LinkControl::from_bits(read_back_2 as u16);
1437
1438 assert_eq!(
1439 link_control_2.aspm_control(),
1440 1,
1441 "Other control bits should be settable"
1442 );
1443 assert!(
1444 !link_control_2.retrain_link(),
1445 "retrain_link should still read as 0"
1446 );
1447 }
1448
1449 #[test]
1450 fn test_link_disable_is_read_only() {
1451 let mut cap = PciExpressCapability::new(DevicePortType::RootPort, None);
1452 cap.set_presence_detect_state(true);
1453
1454 write_cap_u32(&mut cap, 0x10, 0x0010);
1455
1456 let link_control = pci_express::LinkControl::from_bits(read_cap_u32(&cap, 0x10) as u16);
1457 assert!(!link_control.link_disable());
1458 assert!(
1459 pci_express::LinkStatus::from_bits((read_cap_u32(&cap, 0x10) >> 16) as u16)
1460 .data_link_layer_link_active()
1461 );
1462 }
1463
1464 #[test]
1465 fn test_hotplug_link_capabilities() {
1466 let cap = PciExpressCapability::new(DevicePortType::RootPort, None);
1468 let cap_with_hotplug = cap.with_hotplug_support(1);
1469
1470 let link_caps_offset = 0x0C; let link_caps = read_cap_u32(&cap_with_hotplug, link_caps_offset);
1472 let link_capabilities = pci_express::LinkCapabilities::from_bits(link_caps);
1473
1474 assert!(
1476 link_capabilities.data_link_layer_link_active_reporting(),
1477 "Data Link Layer Link Active Reporting should be enabled for hotplug"
1478 );
1479
1480 assert_eq!(
1482 link_capabilities.max_link_speed(),
1483 LinkSpeed::Speed32_0GtS,
1484 "Max link speed should be Speed32_0GtS (PCIe 32.0 GT/s)"
1485 );
1486 assert_eq!(
1487 link_capabilities.max_link_width(),
1488 LinkWidth::X16,
1489 "Max link width should be X16 (x16)"
1490 );
1491
1492 let cap_no_hotplug = PciExpressCapability::new(DevicePortType::RootPort, None);
1494 let link_caps_no_hotplug = read_cap_u32(&cap_no_hotplug, link_caps_offset);
1495 let link_capabilities_no_hotplug =
1496 pci_express::LinkCapabilities::from_bits(link_caps_no_hotplug);
1497
1498 assert!(
1499 !link_capabilities_no_hotplug.data_link_layer_link_active_reporting(),
1500 "Data Link Layer Link Active Reporting should be disabled without hotplug"
1501 );
1502 }
1503
1504 #[test]
1505 fn test_link_status_read_only() {
1506 let mut cap =
1508 PciExpressCapability::new(DevicePortType::RootPort, None).with_hotplug_support(1);
1509 cap.set_presence_detect_state(true);
1510
1511 let link_ctl_sts_offset = 0x10; let initial_read = read_cap_u32(&cap, link_ctl_sts_offset);
1515 let initial_link_status = pci_express::LinkStatus::from_bits((initial_read >> 16) as u16);
1516
1517 assert_eq!(
1519 initial_link_status.current_link_speed(),
1520 LinkSpeed::Speed32_0GtS,
1521 "Initial link speed should be set"
1522 );
1523 assert_eq!(
1524 initial_link_status.negotiated_link_width(),
1525 LinkWidth::X16,
1526 "Initial link width should be set"
1527 );
1528 assert!(!initial_link_status.link_training());
1529 assert!(
1530 initial_link_status.data_link_layer_link_active(),
1531 "Initial DLL should be active"
1532 );
1533
1534 let write_val = 0xFFFF0001; write_cap_u32(&mut cap, link_ctl_sts_offset, write_val);
1537
1538 let after_write = read_cap_u32(&cap, link_ctl_sts_offset);
1540 let final_link_status = pci_express::LinkStatus::from_bits((after_write >> 16) as u16);
1541 let final_link_control = pci_express::LinkControl::from_bits(after_write as u16);
1542
1543 assert_eq!(
1545 final_link_status.current_link_speed(),
1546 initial_link_status.current_link_speed(),
1547 "Link Status current_link_speed should be read-only"
1548 );
1549 assert_eq!(
1550 final_link_status.negotiated_link_width(),
1551 initial_link_status.negotiated_link_width(),
1552 "Link Status negotiated_link_width should be read-only"
1553 );
1554 assert!(!final_link_status.link_training());
1555 assert_eq!(
1556 final_link_status.data_link_layer_link_active(),
1557 initial_link_status.data_link_layer_link_active(),
1558 "Link Status data_link_layer_link_active should be read-only"
1559 );
1560
1561 assert_eq!(
1563 final_link_control.aspm_control(),
1564 1,
1565 "Link Control should be writable"
1566 );
1567 }
1568
1569 #[test]
1570 fn test_slot_status_rw1c_behavior() {
1571 let mut cap = PciExpressCapability::new(DevicePortType::RootPort, None);
1573 cap = cap.with_hotplug_support(1);
1574
1575 let slot_ctl_sts_offset = 0x18; cap.set_hotplug_state(true);
1577
1578 let initial_read = read_cap_u32(&cap, slot_ctl_sts_offset);
1580 let initial_status = pci_express::SlotStatus::from_bits((initial_read >> 16) as u16);
1581 assert!(initial_status.presence_detect_changed());
1582 assert!(initial_status.data_link_layer_state_changed());
1583 assert_eq!(initial_status.presence_detect_state(), 1);
1584
1585 let clear_dllsc = pci_express::SlotStatus::new()
1587 .with_data_link_layer_state_changed(true)
1588 .into_bits();
1589 write_cap_u32(&mut cap, slot_ctl_sts_offset, u32::from(clear_dllsc) << 16);
1590 let status = pci_express::SlotStatus::from_bits(
1591 (read_cap_u32(&cap, slot_ctl_sts_offset) >> 16) as u16,
1592 );
1593 assert!(status.presence_detect_changed());
1594 assert!(!status.data_link_layer_state_changed());
1595 assert_eq!(status.presence_detect_state(), 1);
1596
1597 let clear_pdc = pci_express::SlotStatus::new()
1599 .with_presence_detect_changed(true)
1600 .into_bits();
1601 write_cap_u32(&mut cap, slot_ctl_sts_offset, u32::from(clear_pdc) << 16);
1602 let status = pci_express::SlotStatus::from_bits(
1603 (read_cap_u32(&cap, slot_ctl_sts_offset) >> 16) as u16,
1604 );
1605 assert!(!status.presence_detect_changed());
1606 assert_eq!(status.presence_detect_state(), 1);
1607
1608 cap.set_hotplug_state(true);
1610 let status = pci_express::SlotStatus::from_bits(
1611 (read_cap_u32(&cap, slot_ctl_sts_offset) >> 16) as u16,
1612 );
1613 assert!(!status.presence_detect_changed());
1614 assert!(!status.data_link_layer_state_changed());
1615 }
1616
1617 #[test]
1618 fn test_link_control_2_target_speed_validation() {
1619 let mut cap = PciExpressCapability::new(DevicePortType::RootPort, None);
1622
1623 let link_ctl_sts_2_offset = 0x30; let initial_read = read_cap_u32(&cap, link_ctl_sts_2_offset);
1627 let initial_link_control_2 = pci_express::LinkControl2::from_bits(initial_read as u16);
1628 assert_eq!(
1629 initial_link_control_2.target_link_speed(),
1630 LinkSpeed::Speed32_0GtS,
1631 "Initial target link speed should be Speed32_0GtS"
1632 );
1633
1634 let link_ctl_sts_offset = 0x10; let link_ctl_sts = read_cap_u32(&cap, link_ctl_sts_offset);
1637 let link_status = pci_express::LinkStatus::from_bits((link_ctl_sts >> 16) as u16);
1638 assert_eq!(
1639 link_status.current_link_speed(),
1640 LinkSpeed::Speed32_0GtS,
1641 "Initial current link speed should match target speed"
1642 );
1643 assert_eq!(
1644 link_status.negotiated_link_width(),
1645 LinkWidth::X16,
1646 "Initial negotiated link width should be X16"
1647 );
1648
1649 let valid_speed = LinkSpeed::Speed16_0GtS;
1651 write_cap_u32(&mut cap, link_ctl_sts_2_offset, valid_speed.into_bits());
1652
1653 let after_valid_write = read_cap_u32(&cap, link_ctl_sts_2_offset);
1655 let link_control_2_after_valid =
1656 pci_express::LinkControl2::from_bits(after_valid_write as u16);
1657 assert_eq!(
1658 link_control_2_after_valid.target_link_speed(),
1659 valid_speed,
1660 "Target link speed should be set to requested valid speed"
1661 );
1662
1663 let link_ctl_sts_after_valid = read_cap_u32(&cap, link_ctl_sts_offset);
1665 let link_status_after_valid =
1666 pci_express::LinkStatus::from_bits((link_ctl_sts_after_valid >> 16) as u16);
1667 assert_eq!(
1668 link_status_after_valid.current_link_speed(),
1669 LinkSpeed::Speed32_0GtS,
1670 "Target Link Speed must not directly change negotiated link speed"
1671 );
1672
1673 let invalid_speed = LinkSpeed::Speed64_0GtS;
1676 write_cap_u32(&mut cap, link_ctl_sts_2_offset, invalid_speed.into_bits());
1677
1678 let after_invalid_write = read_cap_u32(&cap, link_ctl_sts_2_offset);
1679 let link_control_2_after_invalid =
1680 pci_express::LinkControl2::from_bits(after_invalid_write as u16);
1681 assert_eq!(
1682 link_control_2_after_invalid.target_link_speed(),
1683 invalid_speed,
1684 "Target link speed should preserve the guest value"
1685 );
1686
1687 let link_ctl_sts_after_invalid = read_cap_u32(&cap, link_ctl_sts_offset);
1689 let link_status_after_invalid =
1690 pci_express::LinkStatus::from_bits((link_ctl_sts_after_invalid >> 16) as u16);
1691 assert_eq!(
1692 link_status_after_invalid.current_link_speed(),
1693 LinkSpeed::Speed32_0GtS,
1694 "Target Link Speed must not directly change negotiated link speed"
1695 );
1696
1697 assert_eq!(
1699 link_status_after_valid.negotiated_link_width(),
1700 LinkWidth::X16,
1701 "Negotiated link width should remain unchanged"
1702 );
1703 assert_eq!(
1704 link_status_after_invalid.negotiated_link_width(),
1705 LinkWidth::X16,
1706 "Negotiated link width should remain unchanged"
1707 );
1708 }
1709
1710 #[test]
1711 fn test_with_hotplug_support_slot_number() {
1712 let cap1 = PciExpressCapability::new(DevicePortType::RootPort, None);
1716 let cap1_with_hotplug = cap1.with_hotplug_support(5);
1717
1718 assert!(cap1_with_hotplug.slot_capabilities.hot_plug_capable());
1719 assert_eq!(
1720 cap1_with_hotplug.slot_capabilities.physical_slot_number(),
1721 5
1722 );
1723
1724 let cap2 = PciExpressCapability::new(DevicePortType::DownstreamSwitchPort, None);
1726 let cap2_with_hotplug = cap2.with_hotplug_support(0);
1727
1728 assert!(cap2_with_hotplug.slot_capabilities.hot_plug_capable());
1729 assert_eq!(
1730 cap2_with_hotplug.slot_capabilities.physical_slot_number(),
1731 0
1732 );
1733
1734 let cap3 = PciExpressCapability::new(DevicePortType::RootPort, None);
1736 let cap3_with_hotplug = cap3.with_hotplug_support(255);
1737
1738 assert!(cap3_with_hotplug.slot_capabilities.hot_plug_capable());
1739 assert_eq!(
1740 cap3_with_hotplug.slot_capabilities.physical_slot_number(),
1741 255
1742 );
1743 }
1744
1745 #[test]
1746 fn test_slot_implemented_flag_in_pcie_capabilities_register() {
1747 let cap_no_hotplug = PciExpressCapability::new(DevicePortType::RootPort, None);
1752 let caps_val_no_hotplug = read_cap_u32(&cap_no_hotplug, 0x00);
1753 let pcie_caps_no_hotplug = (caps_val_no_hotplug >> 16) as u16;
1754 let slot_implemented_bit = (pcie_caps_no_hotplug >> 8) & 0x1; assert_eq!(
1756 slot_implemented_bit, 0,
1757 "slot_implemented should be 0 when hotplug is not enabled"
1758 );
1759
1760 let cap_with_hotplug = cap_no_hotplug.with_hotplug_support(1);
1762 let caps_val_with_hotplug = read_cap_u32(&cap_with_hotplug, 0x00);
1763 let pcie_caps_with_hotplug = (caps_val_with_hotplug >> 16) as u16;
1764 let slot_implemented_bit_hotplug = (pcie_caps_with_hotplug >> 8) & 0x1; assert_eq!(
1766 slot_implemented_bit_hotplug, 1,
1767 "slot_implemented should be 1 when hotplug is enabled"
1768 );
1769 }
1770
1771 #[test]
1772 fn test_set_presence_detect_state() {
1773 let cap = PciExpressCapability::new(DevicePortType::RootPort, None).with_hotplug_support(1);
1775
1776 let initial_slot_status = read_cap_u32(&cap, 0x18); let initial_presence_detect = (initial_slot_status >> 22) & 0x1; assert_eq!(
1780 initial_presence_detect, 0,
1781 "Initial presence detect state should be 0"
1782 );
1783
1784 cap.set_presence_detect_state(true);
1786 let present_slot_status = read_cap_u32(&cap, 0x18);
1787 let present_presence_detect = (present_slot_status >> 22) & 0x1;
1788 assert_eq!(
1789 present_presence_detect, 1,
1790 "Presence detect state should be 1 when device is present"
1791 );
1792
1793 cap.set_presence_detect_state(false);
1795 let absent_slot_status = read_cap_u32(&cap, 0x18);
1796 let absent_presence_detect = (absent_slot_status >> 22) & 0x1;
1797 assert_eq!(
1798 absent_presence_detect, 0,
1799 "Presence detect state should be 0 when device is not present"
1800 );
1801 }
1802
1803 #[test]
1804 fn test_set_presence_detect_state_without_slot_implemented() {
1805 let cap = PciExpressCapability::new(DevicePortType::RootPort, None);
1806
1807 let slot_status =
1808 pci_express::SlotStatus::from_bits((read_cap_u32(&cap, 0x18) >> 16) as u16);
1809 assert_eq!(slot_status.presence_detect_state(), 1);
1810
1811 cap.set_presence_detect_state(true);
1812 assert!(
1813 pci_express::LinkStatus::from_bits((read_cap_u32(&cap, 0x10) >> 16) as u16,)
1814 .data_link_layer_link_active()
1815 );
1816 assert_eq!(
1817 pci_express::SlotStatus::from_bits((read_cap_u32(&cap, 0x18) >> 16) as u16)
1818 .presence_detect_state(),
1819 1
1820 );
1821
1822 cap.set_presence_detect_state(false);
1823 assert!(
1824 !pci_express::LinkStatus::from_bits((read_cap_u32(&cap, 0x10) >> 16) as u16,)
1825 .data_link_layer_link_active()
1826 );
1827 }
1828
1829 #[test]
1830 fn test_save_restore_default_state() {
1831 use vmcore::save_restore::SaveRestore;
1832
1833 let mut cap = PciExpressCapability::new(DevicePortType::Endpoint, None);
1835
1836 let saved = cap.save().expect("save should succeed");
1838
1839 assert_eq!(saved.device_control, 0x2810);
1841 assert_eq!(saved.link_control, 0);
1842 assert_eq!(saved.slot_control, 0);
1843 assert_eq!(saved.slot_status_events, 0);
1844 assert_eq!(saved.root_control, 0);
1845 assert_eq!(saved.device_control_2, 0);
1846 let expected_link_control_2 = LinkSpeed::Speed32_0GtS.into_bits() as u16;
1848 assert_eq!(saved.link_control_2, expected_link_control_2);
1849 }
1850
1851 #[test]
1852 fn test_save_restore_modified_state() {
1853 use vmcore::save_restore::SaveRestore;
1854
1855 let mut cap = PciExpressCapability::new(DevicePortType::RootPort, None);
1856
1857 write_cap_u32(&mut cap, 0x08, 0x0005); write_cap_u32(&mut cap, 0x10, 0x0003); write_cap_u32(&mut cap, 0x28, 0x0020); let saved = cap.save().expect("save should succeed");
1869
1870 assert_eq!(saved.device_control, 0x0005);
1872 assert_eq!(saved.link_control, 0x0003);
1873 assert_eq!(saved.device_control_2, 0x0020);
1874 }
1875
1876 #[test]
1877 fn test_save_restore_roundtrip() {
1878 use vmcore::save_restore::SaveRestore;
1879
1880 let mut cap = PciExpressCapability::new(DevicePortType::RootPort, None);
1881
1882 write_cap_u32(&mut cap, 0x08, 0x000F); write_cap_u32(&mut cap, 0x10, 0x0043); write_cap_u32(&mut cap, 0x28, 0x0020); write_cap_u32(&mut cap, 0x30, 0x0004); let saved = cap.save().expect("save should succeed");
1890
1891 let mut cap2 = PciExpressCapability::new(DevicePortType::RootPort, None);
1893 cap2.restore(saved).expect("restore should succeed");
1894
1895 let device_ctl_sts = read_cap_u32(&cap2, 0x08);
1897 assert_eq!(
1898 device_ctl_sts & 0xFFFF,
1899 0x000F,
1900 "Device control should be restored"
1901 );
1902
1903 let link_ctl_sts = read_cap_u32(&cap2, 0x10);
1904 assert_eq!(
1905 link_ctl_sts & 0xFFFF,
1906 0x0043,
1907 "Link control should be restored"
1908 );
1909
1910 let device_ctl_sts_2 = read_cap_u32(&cap2, 0x28);
1911 assert_eq!(
1912 device_ctl_sts_2 & 0xFFFF,
1913 0x0020,
1914 "Device control 2 should be restored"
1915 );
1916
1917 let link_ctl_sts_2 = read_cap_u32(&cap2, 0x30);
1918 assert_eq!(
1919 link_ctl_sts_2 & 0xFFFF,
1920 0x0004,
1921 "Link control 2 should be restored"
1922 );
1923 }
1924
1925 #[test]
1926 fn test_save_restore_with_status_bits() {
1927 use vmcore::save_restore::SaveRestore;
1928
1929 let mut cap = PciExpressCapability::new(DevicePortType::RootPort, None);
1930 cap = cap.with_hotplug_support(1);
1931
1932 cap.set_presence_detect_state(true);
1933
1934 {
1936 let mut state = cap.state.lock();
1937 state
1938 .registers
1939 .slot_status_events
1940 .set_presence_detect_changed(true);
1941 }
1942
1943 let saved = cap.save().expect("save should succeed");
1945
1946 let saved_slot_status = pci_express::SlotStatus::from_bits(saved.slot_status_events);
1948 assert!(saved_slot_status.presence_detect_changed());
1949 assert_eq!(saved_slot_status.presence_detect_state(), 0);
1950
1951 let mut cap2 = PciExpressCapability::new(DevicePortType::RootPort, None);
1954 cap2 = cap2.with_hotplug_support(1);
1955 cap2.restore(saved).expect("restore should succeed");
1956
1957 let slot_ctl_sts = read_cap_u32(&cap2, 0x18);
1959 let restored_slot_status = pci_express::SlotStatus::from_bits((slot_ctl_sts >> 16) as u16);
1960 assert!(
1961 restored_slot_status.presence_detect_changed(),
1962 "Slot status should be restored"
1963 );
1964 assert_eq!(
1965 restored_slot_status.presence_detect_state(),
1966 0,
1967 "Presence detect state should be preserved independently of saved state"
1968 );
1969 }
1970
1971 #[test]
1972 fn test_restore_masks_unsupported_fields() {
1973 use vmcore::save_restore::SaveRestore;
1974
1975 let mut cap = PciExpressCapability::new(DevicePortType::RootPort, None);
1976 let mut saved = cap.save().expect("save should succeed");
1977 saved.device_control = u16::MAX;
1978 saved.link_control = u16::MAX;
1979 saved.slot_control = u16::MAX;
1980 saved.slot_status_events = u16::MAX;
1981 saved.root_control = u16::MAX;
1982 saved.device_control_2 = u16::MAX;
1983 saved.link_control_2 = u16::MAX;
1984
1985 let mut cap2 = PciExpressCapability::new(DevicePortType::RootPort, None);
1986 cap2.restore(saved).expect("restore should succeed");
1987
1988 let saved2 = cap2.save().expect("second save should succeed");
1989 assert_eq!(saved2.device_control, 0x78ff);
1990 assert_eq!(saved2.link_control, 0x00c3);
1991 assert_eq!(saved2.slot_control, 0);
1992 assert_eq!(saved2.slot_status_events, 0);
1993 assert_eq!(saved2.root_control, 0x000f);
1994 assert_eq!(saved2.device_control_2, 0x0020);
1995 assert_eq!(saved2.link_control_2, 0xffbf);
1996 }
1997
1998 #[test]
1999 fn test_save_after_reset() {
2000 use vmcore::save_restore::SaveRestore;
2001
2002 let mut cap = PciExpressCapability::new(DevicePortType::Endpoint, None);
2003
2004 write_cap_u32(&mut cap, 0x08, 0x00FF);
2006 write_cap_u32(&mut cap, 0x10, 0x00FF);
2007
2008 cap.reset();
2010
2011 let saved = cap.save().expect("save should succeed");
2013
2014 assert_eq!(saved.device_control, 0x2810);
2016 assert_eq!(saved.link_control, 0);
2017 assert_eq!(saved.slot_status_events, 0);
2018 }
2019}