Skip to main content

pci_core/capabilities/
pci_express.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! PCI Express Capability with Function Level Reset (FLR) support.
5
6use 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
20/// FLR bit is the 28th bit in the Device Capabilities register (0 indexed).
21pub const PCI_EXPRESS_DEVICE_CAPS_FLR_BIT_MASK: u32 = 1 << 28;
22
23/// Callback interface for handling Function Level Reset (FLR) events.
24pub trait FlrHandler: Send + Sync + Inspect {
25    /// Called when Function Level Reset is initiated.
26    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)]
108/// Configurable PCI Express capability.
109pub 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    /// Creates a new PCI Express capability with FLR support.
125    ///
126    /// # Arguments
127    /// * `typ` - The spec-defined device or port type.
128    /// * `flr_handler` - Optional handler to be called when FLR is initiated. This emulator will report that FLR is supported if flr_handler = Some(_)
129    pub fn new(typ: pci_express::DevicePortType, flr_handler: Option<Arc<dyn FlrHandler>>) -> Self {
130        // ARI Forwarding is only meaningful on downstream-facing ports (root port /
131        // switch downstream port) which turn Type 1 config requests into Type 0
132        // requests to the connected device. Advertising it as supported lets an
133        // ARI-aware guest enable ARI Forwarding so that endpoint functions numbered
134        // greater than 7 (e.g. SR-IOV VFs) enumerate correctly instead of being
135        // aliased under multiple device numbers. See PCIe Base Spec 7.0 §6.13.
136        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            // TODO: Advertising 32 GT/s is not automatically PCIe spec compliant. PCIe 7.0
151            // requires additional support, including 10-bit Tag Completer and the Secondary
152            // PCI Express, Data Link Feature (for downstream ports), Physical Layer 16.0 GT/s,
153            // and Physical Layer 32.0 GT/s Extended Capabilities.
154            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), // Support speeds up to PCIe Gen 5 (32.0 GT/s)
164            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        // Device Control (2 bytes) + Device Status (2 bytes)
172        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        // Slot Control (2 bytes) + Slot Status (2 bytes)
207        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        // Link Control (2 bytes) + Link Status (2 bytes)
295        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        // The PCIe spec requires Link Disable to be writable on downstream ports.
310        // Keep it read-only because this emulator intentionally does not disable
311        // downstream transaction forwarding when the bit is set.
312        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        // Link Control 2 (2 bytes) + Link Status 2 (2 bytes)
351        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    /// Enable hotplug support for this PCIe capability.
403    /// This configures the appropriate registers to support hotpluggable devices.
404    /// Panics if called on device types other than RootPort or DownstreamSwitchPort.
405    ///
406    /// # Arguments
407    /// * `slot_number` - The physical slot number to assign to this hotplug-capable port
408    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        // Enable slot implemented in PCIe capabilities when hotplug is enabled
417        self.pcie_capabilities = self.pcie_capabilities.with_slot_implemented(true);
418
419        // Enable hotplug capabilities in slot capabilities register.
420        //
421        // We advertise no_command_completed_support because our emulation
422        // applies Slot Control changes instantly (no hardware delay). This
423        // tells the guest's pciehp driver to skip waiting for command_completed
424        // after writing Slot Control (PCIe spec §7.5.3.9).
425        //
426        // Without this, a naive command_completed implementation that sets
427        // the bit on every Slot Control write creates an interrupt storm:
428        // the guest clears command_completed via RW1C (which is itself a
429        // Slot Control write), re-triggering command_completed in a loop.
430        // A correct implementation for ports with real delay would need to
431        // diff old vs new Slot Control values and only signal completion
432        // when control bits actually change, not on RW1C status clears.
433        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        // Enable Data Link Layer Link Active Reporting when hotplug is enabled
441        self.link_capabilities = self
442            .link_capabilities
443            .with_data_link_layer_link_active_reporting(true);
444
445        self
446    }
447
448    /// Enable TLP prefixing support for this PCIe capability.
449    ///
450    /// This configures the appropriate registers to indicate that the function supports
451    /// end-to-end TLP prefixes. We do not currently implement TLP prefixing in endpoint
452    /// DMA APIs but this still may be required for ports upstream of passthrough devices
453    /// that support TLP prefixing (ex. for guest controlled PASID with a virtual IOMMU).
454    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    /// Set the physical presence state used to derive slot and link status.
464    ///
465    /// # Arguments
466    /// * `present` - true if a device is present in the slot, false if the slot is empty
467    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    /// Set the RW1C changed bits in Slot Status to signal a hotplug event.
473    /// Call this only for runtime hotplug events, not build-time device attachment.
474    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    /// Atomically update presence detect state, link active state, and
492    /// changed bits for a hotplug event.
493    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    /// Returns whether the hot plug interrupt is enabled in Slot Control.
516    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    /// Returns whether ARI Forwarding is enabled in Device Control 2.
525    ///
526    /// When set on a downstream-facing port, the port no longer enforces the
527    /// requirement that the Device Number be 0 when turning a Type 1
528    /// configuration request into a Type 0 request, allowing the full 8-bit
529    /// ARI function number to reach the connected device. See PCIe Base Spec
530    /// 7.0 §6.13.
531    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    /// Returns a reference to the slot capabilities register.
540    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        // Implement the full PCI Express Capability structure (PCI Spec, Section 7.5.3):
556        // 0x00: PCIe Capabilities (2 bytes) + Next Pointer (1 byte) + Capability ID (1 byte)
557        // 0x04: Device Capabilities (4 bytes)
558        // 0x08: Device Control (2 bytes) + Device Status (2 bytes)
559        // 0x0C: Link Capabilities (4 bytes)
560        // 0x10: Link Control (2 bytes) + Link Status (2 bytes)
561        // 0x14: Slot Capabilities (4 bytes)
562        // 0x18: Slot Control (2 bytes) + Slot Status (2 bytes)
563        // 0x1C: Root Control (2 bytes) + Root Capabilities (2 bytes)
564        // 0x20: Root Status (4 bytes)
565        // 0x24: Device Capabilities 2 (4 bytes)
566        // 0x28: Device Control 2 (2 bytes) + Device Status 2 (2 bytes)
567        // 0x2C: Link Capabilities 2 (4 bytes)
568        // 0x30: Link Control 2 (2 bytes) + Link Status 2 (2 bytes)
569        // 0x34: Slot Capabilities 2 (4 bytes)
570        // 0x38: Slot Control 2 (2 bytes) + Slot Status 2 (2 bytes)
571        // Total: 60 bytes (0x3C)
572        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                // PCIe Capabilities Register (16 bits) + Next Pointer (8 bits) + Capability ID (8 bits)
581                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                // Device Control (2 bytes) + Device Status (2 bytes)
591                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                // Link Control (2 bytes) + Link Status (2 bytes)
596                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                // Slot Control (2 bytes) + Slot Status (2 bytes)
604                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                // Root Control (2 bytes) + Root Capabilities (2 bytes)
616                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                // Device Control 2 (2 bytes) + Device Status 2 (2 bytes)
629                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                // Link Control 2 (2 bytes) + Link Status 2 (2 bytes)
636                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                // PCIe Capabilities register is read-only
660                tracelimit::warn_ratelimited!(
661                    ?label,
662                    offset,
663                    ?val,
664                    "write to read-only pcie capabilities"
665                );
666            }
667            PciExpressCapabilityHeader::DEVICE_CAPS => {
668                // Device Capabilities register is read-only
669                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                // Link Capabilities register is read-only
681                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                // Slot Capabilities register is read-only
693                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                // Root Control (2 bytes) + Root Capabilities (2 bytes)
705                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                // Root Capabilities upper 16 bits are read-only
713            }
714            PciExpressCapabilityHeader::ROOT_STS => {
715                // Root Status is not modeled and remains hardwired to zero.
716            }
717            PciExpressCapabilityHeader::DEVICE_CAPS_2 => {
718                // Device Capabilities 2 register is read-only
719                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                // Device Control 2 (2 bytes) + Device Status 2 (2 bytes)
728                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                // Link Capabilities 2 register is read-only
738                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                // Slot Capabilities 2 register is read-only
750                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                // Slot Control 2 and Slot Status 2 are reserved and hardwired to zero.
759            }
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        // ARI Forwarding Supported (Device Capabilities 2, bit 5 / 0x20) must be
935        // advertised on downstream-facing ports and never on endpoints/upstream ports.
936        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        // Enable bit starts cleared.
955        assert!(!cap.ari_forwarding_enable());
956
957        // Guest sets ARI Forwarding Enable (Device Control 2, bit 5 / 0x20).
958        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        // Guest clears it again.
963        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        // Test PCIe Capabilities Register (offset 0x00)
996        let caps_val = read_cap_u32(&cap, 0x00);
997        assert_eq!(caps_val & 0xFF, 0x10); // Capability ID = 0x10
998        assert_eq!((caps_val >> 8) & 0xFF, 0x00); // Next Pointer = 0x00
999        assert_eq!((caps_val >> 16) & 0xFFFF, 0x0002); // PCIe Caps: Version 2, Device/Port Type 0
1000
1001        // Test Device Capabilities Register (offset 0x04)
1002        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        ); // FLR bit should be set
1007
1008        // Test the specification-defined Device Control reset value.
1009        let device_ctl_sts_val = read_cap_u32(&cap, 0x08);
1010        assert_eq!(device_ctl_sts_val, 0x2810);
1011
1012        // Test Link Control/Status Register (offset 0x10) - should have link status initialized
1013        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); // current_link_speed + negotiated_link_width
1016        assert_eq!(link_ctl_sts_val, (expected_link_status as u32) << 16); // Link status is in upper 16 bits
1017    }
1018
1019    #[test]
1020    fn test_pci_express_capability_read_root_port() {
1021        let cap = PciExpressCapability::new(DevicePortType::RootPort, None);
1022
1023        // Test PCIe Capabilities Register (offset 0x00)
1024        let caps_val = read_cap_u32(&cap, 0x00);
1025        assert_eq!(caps_val & 0xFF, 0x10); // Capability ID = 0x10
1026        assert_eq!((caps_val >> 8) & 0xFF, 0x00); // Next Pointer = 0x00
1027        assert_eq!((caps_val >> 16) & 0xFFFF, 0x0042); // PCIe Caps: Version 2, Device/Port Type 4
1028    }
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        // Test Device Capabilities Register (offset 0x04) - FLR should not be set
1050        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        // Try to write to read-only PCIe Capabilities Register (offset 0x00)
1073        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); // Should be unchanged
1076
1077        // Try to write to read-only Device Capabilities Register (offset 0x04)
1078        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); // Should be unchanged
1081    }
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        // Initial state should have FLR clear and the defined control defaults.
1090        let initial_ctl_sts = read_cap_u32(&cap, 0x08);
1091        assert_eq!(initial_ctl_sts & 0xFFFF, 0x2810);
1092
1093        // Test writing to Device Control Register (lower 16 bits of offset 0x08)
1094        // Set some control bits but not FLR initially
1095        write_cap_u32(&mut cap, 0x08, 0x0001); // Enable correctable error reporting (bit 0)
1096        let device_ctl_sts = read_cap_u32(&cap, 0x08);
1097        assert_eq!(device_ctl_sts & 0xFFFF, 0x0001); // Device Control should be set
1098        assert!(!flr_handler.was_flr_initiated()); // FLR should not be triggered
1099
1100        // Test FLR initiation (bit 15 of Device Control)
1101        flr_handler.reset();
1102        write_cap_u32(&mut cap, 0x08, 0x8001); // Set FLR bit (bit 15) and other control bits
1103        let device_ctl_sts_after_flr = read_cap_u32(&cap, 0x08);
1104        assert_eq!(device_ctl_sts_after_flr & 0xFFFF, 0x0001); // FLR bit should be cleared, others remain
1105        assert!(flr_handler.was_flr_initiated()); // FLR should be triggered
1106
1107        // Test that writing FLR bit when it's already been triggered behaves correctly
1108        flr_handler.reset();
1109        // After the previous FLR, device_control should have bit 0 set but FLR clear
1110        // So writing 0x8000 (only FLR bit) should trigger FLR again
1111        write_cap_u32(&mut cap, 0x08, 0x8000); // Set FLR bit only
1112        let device_ctl_sts_final = read_cap_u32(&cap, 0x08);
1113        assert_eq!(device_ctl_sts_final & 0xFFFF, 0x0000); // All bits should be cleared (FLR self-clears, bit 0 was overwritten)
1114        assert!(flr_handler.was_flr_initiated()); // Should trigger because FLR transitioned from 0 to 1
1115    }
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        // Writing to unhandled offset should not panic
1192        write_cap_u32(&mut cap, 0x10, 0xFFFFFFFF);
1193        // Should not crash and should not affect other registers
1194        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        // Set some state
1204        write_cap_u32(&mut cap, 0x08, 0x0001); // Set some device control bits
1205
1206        // Verify state is set
1207        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        // Reset the capability
1217        cap.reset();
1218
1219        // Guest-controlled and event state resets, while externally managed
1220        // physical state remains unchanged.
1221        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        // Test that extended registers return proper default values and don't crash
1236        // Link Capabilities should have default speed (Speed32_0GtS) and width (X16)
1237        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); // Link Capabilities
1240        // Link Control/Status should have Link Status with current_link_speed=5 and negotiated_link_width=16
1241        let expected_link_ctl_sts = (LinkSpeed::Speed32_0GtS.into_bits() as u16)
1242            | ((LinkWidth::X16.into_bits() as u16) << 4); // current_link_speed (bits 0-3) + negotiated_link_width (bits 4-9) = 5 + (16 << 4) = 5 + 256 = 261
1243        assert_eq!(
1244            read_cap_u32(&cap, 0x10),
1245            (expected_link_ctl_sts as u32) << 16
1246        ); // Link Control/Status (status in upper 16 bits)
1247        assert_eq!(read_cap_u32(&cap, 0x14), 0); // Slot Capabilities
1248        assert_eq!(read_cap_u32(&cap, 0x18), 0); // Slot Control/Status
1249        assert_eq!(read_cap_u32(&cap, 0x1C), 0); // Root Control/Capabilities
1250        assert_eq!(read_cap_u32(&cap, 0x20), 0); // Root Status
1251        assert_eq!(read_cap_u32(&cap, 0x24), 0); // Device Capabilities 2
1252        assert_eq!(read_cap_u32(&cap, 0x28), 0); // Device Control/Status 2
1253        // Link Capabilities 2 has supported_link_speeds_vector set to UpToGen5
1254        let expected_link_caps_2 = SupportedLinkSpeedsVector::UpToGen5.into_bits() << 1; // supported_link_speeds_vector at bits 1-7 = 31 << 1 = 62
1255        assert_eq!(read_cap_u32(&cap, 0x2C), expected_link_caps_2); // Link Capabilities 2
1256        // Link Control/Status 2 - Link Control 2 should have target_link_speed set to Speed32_0GtS (5)
1257        let expected_link_ctl_sts_2 = LinkSpeed::Speed32_0GtS.into_bits() as u16; // target_link_speed in lower 4 bits = 5
1258        assert_eq!(read_cap_u32(&cap, 0x30), expected_link_ctl_sts_2 as u32); // Link Control/Status 2
1259        assert_eq!(read_cap_u32(&cap, 0x34), 0); // Slot Capabilities 2
1260        assert_eq!(read_cap_u32(&cap, 0x38), 0); // Slot Control/Status 2
1261    }
1262
1263    #[test]
1264    fn test_pci_express_capability_length() {
1265        let cap = PciExpressCapability::new(DevicePortType::Endpoint, None);
1266        assert_eq!(cap.len(), 0x3C); // Should be 60 bytes (0x3C)
1267    }
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        // Test with RootPort (should work)
1278        let cap = PciExpressCapability::new(DevicePortType::RootPort, None);
1279        let cap_with_hotplug = cap.with_hotplug_support(1);
1280
1281        // Verify that the method doesn't crash and returns the capability
1282        assert_eq!(cap_with_hotplug.label(), "pci-express");
1283        assert_eq!(cap_with_hotplug.len(), 0x3C);
1284
1285        // Verify hotplug capabilities are set
1286        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        // Verify that slot_implemented is set in PCIe capabilities
1291        assert!(
1292            cap_with_hotplug.pcie_capabilities.slot_implemented(),
1293            "slot_implemented should be true when hotplug is enabled"
1294        );
1295
1296        // Test with DownstreamSwitchPort (should work)
1297        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        // Verify that slot_implemented is set for downstream switch port too
1308        assert!(
1309            cap2_with_hotplug.pcie_capabilities.slot_implemented(),
1310            "slot_implemented should be true when hotplug is enabled"
1311        );
1312
1313        // Test that non-hotplug capability doesn't have slot_implemented set
1314        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        // Create a root port capability with hotplug support but limited slot capabilities
1340        let mut cap = PciExpressCapability::new(DevicePortType::RootPort, None);
1341        cap = cap.with_hotplug_support(1);
1342
1343        // Modify slot capabilities to disable some features for testing
1344        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        // Try to write to slot control register with all bits set
1354        let slot_ctl_sts_offset = 0x18; // SLOT_CTL_STS offset
1355        let val_to_write = 0xFFFFFFFF; // All bits set in both control and status
1356
1357        write_cap_u32(&mut cap, slot_ctl_sts_offset, val_to_write);
1358
1359        // Read back the slot control register (lower 16 bits)
1360        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        // Verify that features not present in capabilities were not set in control register
1365        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        // Native hotplug and DLL active reporting are advertised.
1403        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        // Test that retrain_link always reads as 0 regardless of what is written
1414        let mut cap = PciExpressCapability::new(DevicePortType::RootPort, None);
1415
1416        let link_ctl_sts_offset = 0x10; // LINK_CTL_STS offset
1417
1418        // Write a value with retrain_link bit set (bit 5)
1419        let write_val = 0x0020; // retrain_link bit (bit 5) = 1
1420        write_cap_u32(&mut cap, link_ctl_sts_offset, write_val);
1421
1422        // Read back and verify retrain_link is always 0
1423        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        // Verify other bits can still be set (except retrain_link)
1432        let write_val_2 = 0x0001; // aspm_control bit 0 = 1
1433        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        // Test that Data Link Layer Link Active Reporting is enabled with hotplug
1467        let cap = PciExpressCapability::new(DevicePortType::RootPort, None);
1468        let cap_with_hotplug = cap.with_hotplug_support(1);
1469
1470        let link_caps_offset = 0x0C; // LINK_CAPS offset
1471        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        // Verify that Data Link Layer Link Active Reporting is enabled
1475        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        // Verify default speed and width are still correct
1481        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        // Test that non-hotplug capability doesn't have Data Link Layer Link Active Reporting
1493        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        // Test that Link Status register is read-only and cannot be modified by writes
1507        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; // LINK_CTL_STS offset
1512
1513        // Read initial values
1514        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        // Verify initial values are set
1518        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        // Try to write different values to Link Status (upper 16 bits) while also writing to Link Control
1535        let write_val = 0xFFFF0001; // Upper 16 bits all 1s (Link Status), lower 16 bits = 1 (Link Control)
1536        write_cap_u32(&mut cap, link_ctl_sts_offset, write_val);
1537
1538        // Read back and verify Link Status hasn't changed
1539        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        // Link Status should remain unchanged (read-only)
1544        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        // But Link Control should be modifiable
1562        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        // Create a root port capability with hotplug support
1572        let mut cap = PciExpressCapability::new(DevicePortType::RootPort, None);
1573        cap = cap.with_hotplug_support(1);
1574
1575        let slot_ctl_sts_offset = 0x18; // SLOT_CTL_STS offset
1576        cap.set_hotplug_state(true);
1577
1578        // Hotplug sets the two event latches this emulator implements.
1579        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        // Clear DLLSC while leaving PDC set.
1586        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        // Clear PDC. The read-only physical presence bit remains set.
1598        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        // Re-applying the same physical state is not a new hotplug event.
1609        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        // Target Link Speed is guest control state. Current Link Speed reports
1620        // negotiated hardware state and does not change until link retraining.
1621        let mut cap = PciExpressCapability::new(DevicePortType::RootPort, None);
1622
1623        let link_ctl_sts_2_offset = 0x30; // LINK_CTL_STS_2 offset
1624
1625        // Initially, target link speed should be Speed32_0GtS (5) and current link speed should match
1626        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        // Check that link status reflects this speed
1635        let link_ctl_sts_offset = 0x10; // LINK_CTL_STS offset
1636        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        // Test writing a valid speed (Speed16_0GtS = 4) that's less than max speed (Speed32_0GtS = 5)
1650        let valid_speed = LinkSpeed::Speed16_0GtS;
1651        write_cap_u32(&mut cap, link_ctl_sts_2_offset, valid_speed.into_bits());
1652
1653        // Verify target link speed was set correctly
1654        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        // Writing Target Link Speed alone does not initiate retraining.
1664        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        // Unsupported Target Link Speed encodings have undefined behavior. The
1674        // register preserves the guest value rather than inventing a clamp.
1675        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        // The unsupported target still does not alter negotiated status.
1688        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        // Verify that link width remains unchanged throughout
1698        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        // Test that slot numbers are properly set when enabling hotplug support
1713
1714        // Test with slot number 5
1715        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        // Test with slot number 0
1725        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        // Test with a larger slot number
1735        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        // Test that slot_implemented bit is correctly set in the PCIe Capabilities register
1748        // when hotplug support is enabled
1749
1750        // Test without hotplug - slot_implemented should be false
1751        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; // slot_implemented is bit 8 of PCIe capabilities
1755        assert_eq!(
1756            slot_implemented_bit, 0,
1757            "slot_implemented should be 0 when hotplug is not enabled"
1758        );
1759
1760        // Test with hotplug - slot_implemented should be true
1761        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; // slot_implemented is bit 8 of PCIe capabilities
1765        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        // Test setting presence detect state on a hotplug-capable port
1774        let cap = PciExpressCapability::new(DevicePortType::RootPort, None).with_hotplug_support(1);
1775
1776        // Initially, presence detect state should be 0 (no device present)
1777        let initial_slot_status = read_cap_u32(&cap, 0x18); // Slot Control + Slot Status
1778        let initial_presence_detect = (initial_slot_status >> 22) & 0x1; // presence_detect_state is bit 6 of slot status (upper 16 bits)
1779        assert_eq!(
1780            initial_presence_detect, 0,
1781            "Initial presence detect state should be 0"
1782        );
1783
1784        // Set device as present
1785        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        // Set device as not present
1794        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        // Create a capability with default state
1834        let mut cap = PciExpressCapability::new(DevicePortType::Endpoint, None);
1835
1836        // Save the default state
1837        let saved = cap.save().expect("save should succeed");
1838
1839        // Verify default state values
1840        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        // Link control 2 has default target_link_speed
1847        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        // Modify state by writing to registers
1858        // Write to Device Control (offset 0x08, lower 16 bits)
1859        write_cap_u32(&mut cap, 0x08, 0x0005); // Set some device control bits
1860
1861        // Write to Link Control (offset 0x10, lower 16 bits)
1862        write_cap_u32(&mut cap, 0x10, 0x0003); // Set ASPM control bits
1863
1864        // Write to Device Control 2 (offset 0x28, lower 16 bits)
1865        write_cap_u32(&mut cap, 0x28, 0x0020); // Enable advertised ARI forwarding
1866
1867        // Save the modified state
1868        let saved = cap.save().expect("save should succeed");
1869
1870        // Verify the saved state reflects the modifications
1871        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        // Modify various state registers
1883        write_cap_u32(&mut cap, 0x08, 0x000F); // Device Control
1884        write_cap_u32(&mut cap, 0x10, 0x0043); // Link Control
1885        write_cap_u32(&mut cap, 0x28, 0x0020); // Device Control 2
1886        write_cap_u32(&mut cap, 0x30, 0x0004); // Link Control 2 (target speed = 4)
1887
1888        // Save the state
1889        let saved = cap.save().expect("save should succeed");
1890
1891        // Create a new capability and restore the saved state
1892        let mut cap2 = PciExpressCapability::new(DevicePortType::RootPort, None);
1893        cap2.restore(saved).expect("restore should succeed");
1894
1895        // Verify restored state by reading registers
1896        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        // Set a real hardware-produced slot event latch.
1935        {
1936            let mut state = cap.state.lock();
1937            state
1938                .registers
1939                .slot_status_events
1940                .set_presence_detect_changed(true);
1941        }
1942
1943        // Save the state
1944        let saved = cap.save().expect("save should succeed");
1945
1946        // Verify status bits are in saved state
1947        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        // Restore into a port with different physical state. The snapshot's
1952        // source-side presence must not overwrite destination topology.
1953        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        // Read back and verify the event latch was restored.
1958        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        // Modify state
2005        write_cap_u32(&mut cap, 0x08, 0x00FF);
2006        write_cap_u32(&mut cap, 0x10, 0x00FF);
2007
2008        // Reset
2009        cap.reset();
2010
2011        // Save after reset
2012        let saved = cap.save().expect("save should succeed");
2013
2014        // Verify state is back to defaults
2015        assert_eq!(saved.device_control, 0x2810);
2016        assert_eq!(saved.link_control, 0);
2017        assert_eq!(saved.slot_status_events, 0);
2018    }
2019}