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::{
10    LinkSpeed, LinkWidth, PciExpressCapabilityHeader, SupportedLinkSpeedsVector,
11};
12use inspect::Inspect;
13use parking_lot::Mutex;
14use std::sync::Arc;
15
16/// FLR bit is the 28th bit in the Device Capabilities register (0 indexed).
17pub const PCI_EXPRESS_DEVICE_CAPS_FLR_BIT_MASK: u32 = 1 << 28;
18
19/// Callback interface for handling Function Level Reset (FLR) events.
20pub trait FlrHandler: Send + Sync + Inspect {
21    /// Called when Function Level Reset is initiated.
22    fn initiate_flr(&self);
23}
24
25#[derive(Debug, Inspect)]
26struct PciExpressState {
27    device_control: pci_express::DeviceControl,
28    device_status: pci_express::DeviceStatus,
29    link_control: pci_express::LinkControl,
30    link_status: pci_express::LinkStatus,
31    slot_control: pci_express::SlotControl,
32    slot_status: pci_express::SlotStatus,
33    root_control: pci_express::RootControl,
34    root_status: pci_express::RootStatus,
35    device_control_2: pci_express::DeviceControl2,
36    device_status_2: pci_express::DeviceStatus2,
37    link_control_2: pci_express::LinkControl2,
38    link_status_2: pci_express::LinkStatus2,
39    slot_control_2: pci_express::SlotControl2,
40    slot_status_2: pci_express::SlotStatus2,
41}
42
43impl PciExpressState {
44    fn new() -> Self {
45        Self {
46            device_control: pci_express::DeviceControl::new(),
47            device_status: pci_express::DeviceStatus::new(),
48            link_control: pci_express::LinkControl::new(),
49            link_status: pci_express::LinkStatus::new()
50                .with_current_link_speed(LinkSpeed::Speed32_0GtS.into_bits() as u16)
51                .with_negotiated_link_width(LinkWidth::X16.into_bits() as u16),
52            slot_control: pci_express::SlotControl::new(),
53            slot_status: pci_express::SlotStatus::new(),
54            root_control: pci_express::RootControl::new(),
55            root_status: pci_express::RootStatus::new(),
56            device_control_2: pci_express::DeviceControl2::new(),
57            device_status_2: pci_express::DeviceStatus2::new(),
58            link_control_2: pci_express::LinkControl2::new()
59                .with_target_link_speed(LinkSpeed::Speed32_0GtS.into_bits() as u16),
60            link_status_2: pci_express::LinkStatus2::new(),
61            slot_control_2: pci_express::SlotControl2::new(),
62            slot_status_2: pci_express::SlotStatus2::new(),
63        }
64    }
65}
66
67#[derive(Inspect)]
68/// Configurable PCI Express capability.
69pub struct PciExpressCapability {
70    pcie_capabilities: pci_express::PciExpressCapabilities,
71    device_capabilities: pci_express::DeviceCapabilities,
72    link_capabilities: pci_express::LinkCapabilities,
73    slot_capabilities: pci_express::SlotCapabilities,
74    root_capabilities: pci_express::RootCapabilities,
75    device_capabilities_2: pci_express::DeviceCapabilities2,
76    link_capabilities_2: pci_express::LinkCapabilities2,
77    slot_capabilities_2: pci_express::SlotCapabilities2,
78    state: Arc<Mutex<PciExpressState>>,
79    #[inspect(skip)]
80    flr_handler: Option<Arc<dyn FlrHandler>>,
81}
82
83impl PciExpressCapability {
84    /// Creates a new PCI Express capability with FLR support.
85    ///
86    /// # Arguments
87    /// * `typ` - The spec-defined device or port type.
88    /// * `flr_handler` - Optional handler to be called when FLR is initiated. This emulator will report that FLR is supported if flr_handler = Some(_)
89    pub fn new(typ: pci_express::DevicePortType, flr_handler: Option<Arc<dyn FlrHandler>>) -> Self {
90        Self {
91            pcie_capabilities: pci_express::PciExpressCapabilities::new()
92                .with_capability_version(2)
93                .with_device_port_type(typ),
94            device_capabilities: pci_express::DeviceCapabilities::new()
95                .with_function_level_reset(flr_handler.is_some()),
96            link_capabilities: pci_express::LinkCapabilities::new()
97                .with_max_link_speed(LinkSpeed::Speed32_0GtS.into_bits()) // PCIe 32.0 GT/s speed
98                .with_max_link_width(LinkWidth::X16.into_bits()), // x16 link width
99            slot_capabilities: pci_express::SlotCapabilities::new(),
100            root_capabilities: pci_express::RootCapabilities::new(),
101            device_capabilities_2: pci_express::DeviceCapabilities2::new(),
102            link_capabilities_2: pci_express::LinkCapabilities2::new()
103                .with_supported_link_speeds_vector(SupportedLinkSpeedsVector::UpToGen5.into_bits()), // Support speeds up to PCIe Gen 5 (32.0 GT/s)
104            slot_capabilities_2: pci_express::SlotCapabilities2::new(),
105            state: Arc::new(Mutex::new(PciExpressState::new())),
106            flr_handler,
107        }
108    }
109
110    fn handle_device_control_status_write(&mut self, val: u32) {
111        // Device Control (2 bytes) + Device Status (2 bytes)
112        let new_control = pci_express::DeviceControl::from_bits(val as u16);
113        let mut state = self.state.lock();
114
115        // Check if FLR was initiated
116        let old_flr = state.device_control.initiate_function_level_reset();
117        let new_flr = new_control.initiate_function_level_reset();
118
119        // DEVNOTE: It is "safe" to drop a new FLR request if there is still a previous
120        // FLR request in progress. The PCIe spec indicates that such behavior is undefined,
121        // so we choose to ignore the new FLR request.
122        if new_flr && !old_flr {
123            if let Some(handler) = &self.flr_handler {
124                handler.initiate_flr();
125            }
126        }
127
128        // Update the control register but clear the FLR bit as it's self-clearing
129        state.device_control = new_control.with_initiate_function_level_reset(false);
130
131        // Handle Device Status - most bits are write-1-to-clear
132        let new_status = pci_express::DeviceStatus::from_bits((val >> 16) as u16);
133        let mut current_status = state.device_status;
134
135        // Clear bits that were written as 1 (write-1-to-clear semantics)
136        if new_status.correctable_error_detected() {
137            current_status.set_correctable_error_detected(false);
138        }
139        if new_status.non_fatal_error_detected() {
140            current_status.set_non_fatal_error_detected(false);
141        }
142        if new_status.fatal_error_detected() {
143            current_status.set_fatal_error_detected(false);
144        }
145        if new_status.unsupported_request_detected() {
146            current_status.set_unsupported_request_detected(false);
147        }
148
149        state.device_status = current_status;
150    }
151
152    fn handle_slot_control_status_write(&mut self, val: u32) {
153        // Slot Control (2 bytes) + Slot Status (2 bytes)
154        let new_slot_control = pci_express::SlotControl::from_bits(val as u16);
155        let mut state = self.state.lock();
156
157        // Mask slot control bits based on slot capabilities
158        // Only allow writes to bits that correspond to capabilities that are present
159        let mut masked_control = new_slot_control;
160
161        // If attention button is not present, attention button enable should be read-only (hardwired to 0)
162        if !self.slot_capabilities.attention_button_present() {
163            masked_control.set_attention_button_pressed_enable(false);
164        }
165
166        // If power controller is not present, power controller control should be read-only (hardwired to 0)
167        if !self.slot_capabilities.power_controller_present() {
168            masked_control.set_power_controller_control(false);
169        }
170
171        // If MRL sensor is not present, MRL sensor changed enable should be read-only (hardwired to 0)
172        if !self.slot_capabilities.mrl_sensor_present() {
173            masked_control.set_mrl_sensor_changed_enable(false);
174        }
175
176        // If attention indicator is not present, attention indicator control should be read-only (hardwired to 00b)
177        if !self.slot_capabilities.attention_indicator_present() {
178            masked_control.set_attention_indicator_control(0);
179        }
180
181        // If power indicator is not present, power indicator control should be read-only (hardwired to 00b)
182        if !self.slot_capabilities.power_indicator_present() {
183            masked_control.set_power_indicator_control(0);
184        }
185
186        // If hotplug is not capable, hotplug interrupt enable should be read-only (hardwired to 0)
187        if !self.slot_capabilities.hot_plug_capable() {
188            masked_control.set_hot_plug_interrupt_enable(false);
189        }
190
191        // If electromechanical interlock is not present, interlock control should be read-only (hardwired to 0)
192        if !self.slot_capabilities.electromechanical_interlock_present() {
193            masked_control.set_electromechanical_interlock_control(false);
194        }
195
196        // If no command completed support, command completed interrupt enable should be read-only (hardwired to 0)
197        if self.slot_capabilities.no_command_completed_support() {
198            masked_control.set_command_completed_interrupt_enable(false);
199        }
200
201        state.slot_control = masked_control;
202
203        // Slot Status upper 16 bits - handle RW1C and RO bits properly
204        let new_slot_status = pci_express::SlotStatus::from_bits((val >> 16) as u16);
205        let mut current_slot_status = state.slot_status;
206
207        // RW1C bits: writing 1 clears the bit, writing 0 leaves it unchanged
208        // Clear bits where a 1 was written (RW1C behavior)
209        if new_slot_status.attention_button_pressed() {
210            current_slot_status.set_attention_button_pressed(false);
211        }
212        if new_slot_status.power_fault_detected() {
213            current_slot_status.set_power_fault_detected(false);
214        }
215        if new_slot_status.mrl_sensor_changed() {
216            current_slot_status.set_mrl_sensor_changed(false);
217        }
218        if new_slot_status.presence_detect_changed() {
219            current_slot_status.set_presence_detect_changed(false);
220        }
221        if new_slot_status.command_completed() {
222            current_slot_status.set_command_completed(false);
223        }
224        if new_slot_status.data_link_layer_state_changed() {
225            current_slot_status.set_data_link_layer_state_changed(false);
226        }
227
228        // RO bits (mrl_sensor_state, presence_detect_state, electromechanical_interlock_status)
229        // are not modified - they remain as they were
230
231        state.slot_status = current_slot_status;
232    }
233
234    fn handle_link_control_status_write(&mut self, val: u32) {
235        // Link Control (2 bytes) + Link Status (2 bytes)
236        let new_link_control = pci_express::LinkControl::from_bits(val as u16);
237        let mut state = self.state.lock();
238
239        // Apply the new link control but ensure retrain_link always reads as 0
240        let mut masked_control = new_link_control;
241        masked_control.set_retrain_link(false); // retrain_link always reads as 0
242
243        state.link_control = masked_control;
244        // Link Status upper 16 bits - read-only, ignore any writes
245    }
246
247    fn handle_link_control_2_write(&mut self, val: u32) {
248        // Link Control 2 (2 bytes) + Link Status 2 (2 bytes)
249        let new_link_control_2 = pci_express::LinkControl2::from_bits(val as u16);
250        let mut state = self.state.lock();
251
252        // Validate that target_link_speed doesn't exceed max_link_speed from Link Capabilities
253        let max_speed = self.link_capabilities.max_link_speed();
254        let requested_speed = new_link_control_2.target_link_speed();
255
256        // Clamp the target link speed to not exceed the maximum supported speed
257        let actual_speed = if requested_speed > max_speed as u16 {
258            max_speed as u16
259        } else {
260            requested_speed
261        };
262
263        // Update Link Control 2 with the validated speed
264        state.link_control_2 = new_link_control_2.with_target_link_speed(actual_speed);
265
266        // Update Link Status to reflect the target link speed as current link speed
267        // This simulates the link retraining and speed negotiation completing immediately
268        state.link_status = state.link_status.with_current_link_speed(actual_speed);
269
270        // Link Status 2 upper 16 bits - mostly read-only, so we don't modify it
271    }
272
273    /// Enable hotplug support for this PCIe capability.
274    /// This configures the appropriate registers to support hotpluggable devices.
275    /// Panics if called on device types other than RootPort or DownstreamSwitchPort.
276    ///
277    /// # Arguments
278    /// * `slot_number` - The physical slot number to assign to this hotplug-capable port
279    pub fn with_hotplug_support(mut self, slot_number: u32) -> Self {
280        use pci_express::DevicePortType;
281
282        // Validate that hotplug is only enabled for appropriate port types
283        let port_type = self.pcie_capabilities.device_port_type();
284        match port_type {
285            DevicePortType::RootPort | DevicePortType::DownstreamSwitchPort => {
286                // Valid port types for hotplug support
287            }
288            DevicePortType::Endpoint | DevicePortType::UpstreamSwitchPort => {
289                panic!(
290                    "Hotplug support is not valid for device port type {:?}. \
291                     Only RootPort and DownstreamSwitchPort support hotplug.",
292                    port_type
293                );
294            }
295        }
296
297        // Enable slot implemented in PCIe capabilities when hotplug is enabled
298        self.pcie_capabilities = self.pcie_capabilities.with_slot_implemented(true);
299
300        // Enable hotplug capabilities in slot capabilities register.
301        //
302        // We advertise no_command_completed_support because our emulation
303        // applies Slot Control changes instantly (no hardware delay). This
304        // tells the guest's pciehp driver to skip waiting for command_completed
305        // after writing Slot Control (PCIe spec ยง7.5.3.9).
306        //
307        // Without this, a naive command_completed implementation that sets
308        // the bit on every Slot Control write creates an interrupt storm:
309        // the guest clears command_completed via RW1C (which is itself a
310        // Slot Control write), re-triggering command_completed in a loop.
311        // A correct implementation for ports with real delay would need to
312        // diff old vs new Slot Control values and only signal completion
313        // when control bits actually change, not on RW1C status clears.
314        self.slot_capabilities = self
315            .slot_capabilities
316            .with_hot_plug_surprise(true)
317            .with_hot_plug_capable(true)
318            .with_no_command_completed_support(true)
319            .with_physical_slot_number(slot_number);
320
321        // Enable Data Link Layer Link Active Reporting when hotplug is enabled
322        self.link_capabilities = self
323            .link_capabilities
324            .with_data_link_layer_link_active_reporting(true);
325
326        self
327    }
328
329    /// Set the presence detect state for the slot.
330    /// This method only has effect if the slot is implemented (slot_implemented = true).
331    /// If slot is not implemented, the call is silently ignored, as the spec says
332    /// "If this register is implemented but the Slot Implemented bit is Clear,
333    /// the field behavior of this entire register with the exception of the DLLSC bit is undefined."
334    ///
335    /// # Arguments
336    /// * `present` - true if a device is present in the slot, false if the slot is empty
337    pub fn set_presence_detect_state(&self, present: bool) {
338        if !self.pcie_capabilities.slot_implemented() {
339            // Silently ignore if slot is not implemented
340            return;
341        }
342
343        let mut state = self.state.lock();
344        state.slot_status =
345            state
346                .slot_status
347                .with_presence_detect_state(if present { 1 } else { 0 });
348
349        // Update Data Link Layer Link Active in Link Status to match presence.
350        // The pciehp driver checks this (via DLLLA) when LLActRep is advertised.
351        state.link_status = state.link_status.with_data_link_layer_link_active(present);
352    }
353
354    /// Set the RW1C changed bits in Slot Status to signal a hotplug event.
355    /// Call this only for runtime hotplug events, not build-time device attachment.
356    pub fn set_hotplug_changed_bits(&self) {
357        let mut state = self.state.lock();
358        state.slot_status.set_presence_detect_changed(true);
359        state.slot_status.set_data_link_layer_state_changed(true);
360    }
361
362    /// Atomically update presence detect state, link active state, and
363    /// changed bits for a hotplug event.
364    pub fn set_hotplug_state(&self, present: bool) {
365        if !self.pcie_capabilities.slot_implemented() {
366            return;
367        }
368
369        let mut state = self.state.lock();
370        state.slot_status =
371            state
372                .slot_status
373                .with_presence_detect_state(if present { 1 } else { 0 });
374        state.link_status = state.link_status.with_data_link_layer_link_active(present);
375
376        // Update link speed/width to reflect link state. When a device is
377        // removed, the link goes down and these fields reset to 0. When a
378        // device is added, the link trains and reports its negotiated speed.
379        if present {
380            state.link_status = state
381                .link_status
382                .with_current_link_speed(LinkSpeed::Speed32_0GtS.into_bits() as u16)
383                .with_negotiated_link_width(LinkWidth::X16.into_bits() as u16);
384        } else {
385            state.link_status = state
386                .link_status
387                .with_current_link_speed(0)
388                .with_negotiated_link_width(0);
389        }
390
391        state.slot_status.set_presence_detect_changed(true);
392        state.slot_status.set_data_link_layer_state_changed(true);
393    }
394
395    /// Returns whether the hot plug interrupt is enabled in Slot Control.
396    pub fn hot_plug_interrupt_enabled(&self) -> bool {
397        self.state.lock().slot_control.hot_plug_interrupt_enable()
398    }
399
400    /// Returns a reference to the slot capabilities register.
401    pub fn slot_capabilities(&self) -> &pci_express::SlotCapabilities {
402        &self.slot_capabilities
403    }
404}
405
406impl PciCapability for PciExpressCapability {
407    fn label(&self) -> &str {
408        "pci-express"
409    }
410
411    fn capability_id(&self) -> CapabilityId {
412        CapabilityId::PCI_EXPRESS
413    }
414
415    fn len(&self) -> usize {
416        // Implement the full PCI Express Capability structure (PCI Spec, Section 7.5.3):
417        // 0x00: PCIe Capabilities (2 bytes) + Next Pointer (1 byte) + Capability ID (1 byte)
418        // 0x04: Device Capabilities (4 bytes)
419        // 0x08: Device Control (2 bytes) + Device Status (2 bytes)
420        // 0x0C: Link Capabilities (4 bytes)
421        // 0x10: Link Control (2 bytes) + Link Status (2 bytes)
422        // 0x14: Slot Capabilities (4 bytes)
423        // 0x18: Slot Control (2 bytes) + Slot Status (2 bytes)
424        // 0x1C: Root Control (2 bytes) + Root Capabilities (2 bytes)
425        // 0x20: Root Status (4 bytes)
426        // 0x24: Device Capabilities 2 (4 bytes)
427        // 0x28: Device Control 2 (2 bytes) + Device Status 2 (2 bytes)
428        // 0x2C: Link Capabilities 2 (4 bytes)
429        // 0x30: Link Control 2 (2 bytes) + Link Status 2 (2 bytes)
430        // 0x34: Slot Capabilities 2 (4 bytes)
431        // 0x38: Slot Control 2 (2 bytes) + Slot Status 2 (2 bytes)
432        // Total: 60 bytes (0x3C)
433        0x3C
434    }
435
436    fn read_u32(&self, offset: u16) -> u32 {
437        let label = self.label();
438        match PciExpressCapabilityHeader(offset) {
439            PciExpressCapabilityHeader::PCIE_CAPS => {
440                // PCIe Capabilities Register (16 bits) + Next Pointer (8 bits) + Capability ID (8 bits)
441                (self.pcie_capabilities.into_bits() as u32) << 16
442                    | CapabilityId::PCI_EXPRESS.0 as u32
443            }
444            PciExpressCapabilityHeader::DEVICE_CAPS => self.device_capabilities.into_bits(),
445            PciExpressCapabilityHeader::DEVICE_CTL_STS => {
446                let state = self.state.lock();
447                let device_control = state.device_control.into_bits() as u32;
448                let device_status = state.device_status.into_bits() as u32;
449                device_control | (device_status << 16)
450            }
451            PciExpressCapabilityHeader::LINK_CAPS => self.link_capabilities.into_bits(),
452            PciExpressCapabilityHeader::LINK_CTL_STS => {
453                // Link Control (2 bytes) + Link Status (2 bytes)
454                let state = self.state.lock();
455                state.link_control.into_bits() as u32
456                    | ((state.link_status.into_bits() as u32) << 16)
457            }
458            PciExpressCapabilityHeader::SLOT_CAPS => self.slot_capabilities.into_bits(),
459            PciExpressCapabilityHeader::SLOT_CTL_STS => {
460                // Slot Control (2 bytes) + Slot Status (2 bytes)
461                let state = self.state.lock();
462                state.slot_control.into_bits() as u32
463                    | ((state.slot_status.into_bits() as u32) << 16)
464            }
465            PciExpressCapabilityHeader::ROOT_CTL_CAPS => {
466                // Root Control (2 bytes) + Root Capabilities (2 bytes)
467                let state = self.state.lock();
468                state.root_control.into_bits() as u32
469                    | ((self.root_capabilities.into_bits() as u32) << 16)
470            }
471            PciExpressCapabilityHeader::ROOT_STS => {
472                // Root Status (4 bytes)
473                let state = self.state.lock();
474                state.root_status.into_bits()
475            }
476            PciExpressCapabilityHeader::DEVICE_CAPS_2 => self.device_capabilities_2.into_bits(),
477            PciExpressCapabilityHeader::DEVICE_CTL_STS_2 => {
478                // Device Control 2 (2 bytes) + Device Status 2 (2 bytes)
479                let state = self.state.lock();
480                state.device_control_2.into_bits() as u32
481                    | ((state.device_status_2.into_bits() as u32) << 16)
482            }
483            PciExpressCapabilityHeader::LINK_CAPS_2 => self.link_capabilities_2.into_bits(),
484            PciExpressCapabilityHeader::LINK_CTL_STS_2 => {
485                // Link Control 2 (2 bytes) + Link Status 2 (2 bytes)
486                let state = self.state.lock();
487                state.link_control_2.into_bits() as u32
488                    | ((state.link_status_2.into_bits() as u32) << 16)
489            }
490            PciExpressCapabilityHeader::SLOT_CAPS_2 => self.slot_capabilities_2.into_bits(),
491            PciExpressCapabilityHeader::SLOT_CTL_STS_2 => {
492                // Slot Control 2 (2 bytes) + Slot Status 2 (2 bytes)
493                let state = self.state.lock();
494                state.slot_control_2.into_bits() as u32
495                    | ((state.slot_status_2.into_bits() as u32) << 16)
496            }
497            _ => {
498                tracelimit::warn_ratelimited!(
499                    ?label,
500                    offset,
501                    "unhandled pci express capability read"
502                );
503                0
504            }
505        }
506    }
507
508    fn write_u32(&mut self, offset: u16, val: u32) {
509        let label = self.label();
510        match PciExpressCapabilityHeader(offset) {
511            PciExpressCapabilityHeader::PCIE_CAPS => {
512                // PCIe Capabilities register is read-only
513                tracelimit::warn_ratelimited!(
514                    ?label,
515                    offset,
516                    val,
517                    "write to read-only pcie capabilities"
518                );
519            }
520            PciExpressCapabilityHeader::DEVICE_CAPS => {
521                // Device Capabilities register is read-only
522                tracelimit::warn_ratelimited!(
523                    ?label,
524                    offset,
525                    val,
526                    "write to read-only device capabilities"
527                );
528            }
529            PciExpressCapabilityHeader::DEVICE_CTL_STS => {
530                self.handle_device_control_status_write(val);
531            }
532            PciExpressCapabilityHeader::LINK_CAPS => {
533                // Link Capabilities register is read-only
534                tracelimit::warn_ratelimited!(
535                    ?label,
536                    offset,
537                    val,
538                    "write to read-only link capabilities"
539                );
540            }
541            PciExpressCapabilityHeader::LINK_CTL_STS => {
542                self.handle_link_control_status_write(val);
543            }
544            PciExpressCapabilityHeader::SLOT_CAPS => {
545                // Slot Capabilities register is read-only
546                tracelimit::warn_ratelimited!(
547                    ?label,
548                    offset,
549                    val,
550                    "write to read-only slot capabilities"
551                );
552            }
553            PciExpressCapabilityHeader::SLOT_CTL_STS => {
554                self.handle_slot_control_status_write(val);
555            }
556            PciExpressCapabilityHeader::ROOT_CTL_CAPS => {
557                // Root Control (2 bytes) + Root Capabilities (2 bytes)
558                let mut state = self.state.lock();
559                state.root_control = pci_express::RootControl::from_bits(val as u16);
560                // Root Capabilities upper 16 bits are read-only
561            }
562            PciExpressCapabilityHeader::ROOT_STS => {
563                // Root Status (4 bytes) - many bits are write-1-to-clear
564                let mut state = self.state.lock();
565                // For simplicity, we'll allow basic writes for now
566                state.root_status = pci_express::RootStatus::from_bits(val);
567            }
568            PciExpressCapabilityHeader::DEVICE_CAPS_2 => {
569                // Device Capabilities 2 register is read-only
570                tracelimit::warn_ratelimited!(
571                    ?label,
572                    offset,
573                    val,
574                    "write to read-only device capabilities 2"
575                );
576            }
577            PciExpressCapabilityHeader::DEVICE_CTL_STS_2 => {
578                // Device Control 2 (2 bytes) + Device Status 2 (2 bytes)
579                let mut state = self.state.lock();
580                state.device_control_2 = pci_express::DeviceControl2::from_bits(val as u16);
581                // Device Status 2 upper 16 bits - mostly read-only or write-1-to-clear
582                state.device_status_2 = pci_express::DeviceStatus2::from_bits((val >> 16) as u16);
583            }
584            PciExpressCapabilityHeader::LINK_CAPS_2 => {
585                // Link Capabilities 2 register is read-only
586                tracelimit::warn_ratelimited!(
587                    ?label,
588                    offset,
589                    val,
590                    "write to read-only link capabilities 2"
591                );
592            }
593            PciExpressCapabilityHeader::LINK_CTL_STS_2 => {
594                self.handle_link_control_2_write(val);
595            }
596            PciExpressCapabilityHeader::SLOT_CAPS_2 => {
597                // Slot Capabilities 2 register is read-only
598                tracelimit::warn_ratelimited!(
599                    ?label,
600                    offset,
601                    val,
602                    "write to read-only slot capabilities 2"
603                );
604            }
605            PciExpressCapabilityHeader::SLOT_CTL_STS_2 => {
606                // Slot Control 2 (2 bytes) + Slot Status 2 (2 bytes)
607                let mut state = self.state.lock();
608                state.slot_control_2 = pci_express::SlotControl2::from_bits(val as u16);
609                // Slot Status 2 upper 16 bits - mostly read-only or write-1-to-clear
610                state.slot_status_2 = pci_express::SlotStatus2::from_bits((val >> 16) as u16);
611            }
612            _ => {
613                tracelimit::warn_ratelimited!(
614                    ?label,
615                    offset,
616                    val,
617                    "unhandled pci express capability write"
618                );
619            }
620        }
621    }
622
623    fn reset(&mut self) {
624        let mut state = self.state.lock();
625        *state = PciExpressState::new();
626    }
627
628    fn as_pci_express(&self) -> Option<&PciExpressCapability> {
629        Some(self)
630    }
631
632    fn as_pci_express_mut(&mut self) -> Option<&mut PciExpressCapability> {
633        Some(self)
634    }
635}
636
637mod save_restore {
638    use super::*;
639    use vmcore::save_restore::RestoreError;
640    use vmcore::save_restore::SaveError;
641    use vmcore::save_restore::SaveRestore;
642
643    mod state {
644        use mesh::payload::Protobuf;
645        use vmcore::save_restore::SavedStateRoot;
646
647        #[derive(Protobuf, SavedStateRoot)]
648        #[mesh(package = "pci.capabilities.pci_express")]
649        pub struct SavedState {
650            #[mesh(1)]
651            pub device_control: u16,
652            #[mesh(2)]
653            pub device_status: u16,
654            #[mesh(3)]
655            pub link_control: u16,
656            #[mesh(4)]
657            pub link_status: u16,
658            #[mesh(5)]
659            pub slot_control: u16,
660            #[mesh(6)]
661            pub slot_status: u16,
662            #[mesh(7)]
663            pub root_control: u16,
664            #[mesh(8)]
665            pub root_status: u32,
666            #[mesh(9)]
667            pub device_control_2: u16,
668            #[mesh(10)]
669            pub device_status_2: u16,
670            #[mesh(11)]
671            pub link_control_2: u16,
672            #[mesh(12)]
673            pub link_status_2: u16,
674            #[mesh(13)]
675            pub slot_control_2: u16,
676            #[mesh(14)]
677            pub slot_status_2: u16,
678        }
679    }
680
681    impl SaveRestore for PciExpressCapability {
682        type SavedState = state::SavedState;
683
684        fn save(&mut self) -> Result<Self::SavedState, SaveError> {
685            let state = self.state.lock();
686            Ok(state::SavedState {
687                device_control: state.device_control.into_bits(),
688                device_status: state.device_status.into_bits(),
689                link_control: state.link_control.into_bits(),
690                link_status: state.link_status.into_bits(),
691                slot_control: state.slot_control.into_bits(),
692                slot_status: state.slot_status.into_bits(),
693                root_control: state.root_control.into_bits(),
694                root_status: state.root_status.into_bits(),
695                device_control_2: state.device_control_2.into_bits(),
696                device_status_2: state.device_status_2.into_bits(),
697                link_control_2: state.link_control_2.into_bits(),
698                link_status_2: state.link_status_2.into_bits(),
699                slot_control_2: state.slot_control_2.into_bits(),
700                slot_status_2: state.slot_status_2.into_bits(),
701            })
702        }
703
704        fn restore(&mut self, saved: Self::SavedState) -> Result<(), RestoreError> {
705            let mut state = self.state.lock();
706            state.device_control = pci_express::DeviceControl::from_bits(saved.device_control);
707            state.device_status = pci_express::DeviceStatus::from_bits(saved.device_status);
708            state.link_control = pci_express::LinkControl::from_bits(saved.link_control);
709            state.link_status = pci_express::LinkStatus::from_bits(saved.link_status);
710            state.slot_control = pci_express::SlotControl::from_bits(saved.slot_control);
711            state.slot_status = pci_express::SlotStatus::from_bits(saved.slot_status);
712            state.root_control = pci_express::RootControl::from_bits(saved.root_control);
713            state.root_status = pci_express::RootStatus::from_bits(saved.root_status);
714            state.device_control_2 = pci_express::DeviceControl2::from_bits(saved.device_control_2);
715            state.device_status_2 = pci_express::DeviceStatus2::from_bits(saved.device_status_2);
716            state.link_control_2 = pci_express::LinkControl2::from_bits(saved.link_control_2);
717            state.link_status_2 = pci_express::LinkStatus2::from_bits(saved.link_status_2);
718            state.slot_control_2 = pci_express::SlotControl2::from_bits(saved.slot_control_2);
719            state.slot_status_2 = pci_express::SlotStatus2::from_bits(saved.slot_status_2);
720            Ok(())
721        }
722    }
723}
724
725#[cfg(test)]
726mod tests {
727    use super::*;
728    use crate::spec::caps::pci_express::DevicePortType;
729    use std::sync::atomic::{AtomicBool, Ordering};
730
731    #[derive(Debug)]
732    struct TestFlrHandler {
733        flr_initiated: AtomicBool,
734    }
735
736    impl TestFlrHandler {
737        fn new() -> Arc<Self> {
738            Arc::new(Self {
739                flr_initiated: AtomicBool::new(false),
740            })
741        }
742
743        fn was_flr_initiated(&self) -> bool {
744            self.flr_initiated.load(Ordering::Acquire)
745        }
746
747        fn reset(&self) {
748            self.flr_initiated.store(false, Ordering::Release);
749        }
750    }
751
752    impl FlrHandler for TestFlrHandler {
753        fn initiate_flr(&self) {
754            self.flr_initiated.store(true, Ordering::Release);
755        }
756    }
757
758    impl Inspect for TestFlrHandler {
759        fn inspect(&self, req: inspect::Request<'_>) {
760            req.respond()
761                .field("flr_initiated", self.flr_initiated.load(Ordering::Acquire));
762        }
763    }
764
765    #[test]
766    fn test_pci_express_capability_read_u32_endpoint() {
767        let flr_handler = TestFlrHandler::new();
768        let cap = PciExpressCapability::new(DevicePortType::Endpoint, Some(flr_handler));
769
770        // Test PCIe Capabilities Register (offset 0x00)
771        let caps_val = cap.read_u32(0x00);
772        assert_eq!(caps_val & 0xFF, 0x10); // Capability ID = 0x10
773        assert_eq!((caps_val >> 8) & 0xFF, 0x00); // Next Pointer = 0x00
774        assert_eq!((caps_val >> 16) & 0xFFFF, 0x0002); // PCIe Caps: Version 2, Device/Port Type 0
775
776        // Test Device Capabilities Register (offset 0x04)
777        let device_caps_val = cap.read_u32(0x04);
778        assert_eq!(
779            device_caps_val & PCI_EXPRESS_DEVICE_CAPS_FLR_BIT_MASK,
780            PCI_EXPRESS_DEVICE_CAPS_FLR_BIT_MASK
781        ); // FLR bit should be set
782
783        // Test Device Control/Status Register (offset 0x08) - should be zero initially
784        let device_ctl_sts_val = cap.read_u32(0x08);
785        assert_eq!(device_ctl_sts_val, 0); // Both control and status should be 0
786
787        // Test Link Control/Status Register (offset 0x10) - should have link status initialized
788        let link_ctl_sts_val = cap.read_u32(0x10);
789        let expected_link_status = (LinkSpeed::Speed32_0GtS.into_bits() as u16)
790            | ((LinkWidth::X16.into_bits() as u16) << 4); // current_link_speed + negotiated_link_width
791        assert_eq!(link_ctl_sts_val, (expected_link_status as u32) << 16); // Link status is in upper 16 bits
792    }
793
794    #[test]
795    fn test_pci_express_capability_read_u32_root_port() {
796        let cap = PciExpressCapability::new(DevicePortType::RootPort, None);
797
798        // Test PCIe Capabilities Register (offset 0x00)
799        let caps_val = cap.read_u32(0x00);
800        assert_eq!(caps_val & 0xFF, 0x10); // Capability ID = 0x10
801        assert_eq!((caps_val >> 8) & 0xFF, 0x00); // Next Pointer = 0x00
802        assert_eq!((caps_val >> 16) & 0xFFFF, 0x0042); // PCIe Caps: Version 2, Device/Port Type 4
803    }
804
805    #[test]
806    fn test_pci_express_capability_read_u32_no_flr() {
807        let cap = PciExpressCapability::new(DevicePortType::Endpoint, None);
808
809        // Test Device Capabilities Register (offset 0x04) - FLR should not be set
810        let device_caps_val = cap.read_u32(0x04);
811        assert_eq!(device_caps_val & PCI_EXPRESS_DEVICE_CAPS_FLR_BIT_MASK, 0);
812    }
813
814    #[test]
815    fn test_pci_express_capability_write_u32_readonly_registers() {
816        let mut cap = PciExpressCapability::new(DevicePortType::Endpoint, None);
817
818        // Try to write to read-only PCIe Capabilities Register (offset 0x00)
819        let original_caps = cap.read_u32(0x00);
820        cap.write_u32(0x00, 0xFFFFFFFF);
821        assert_eq!(cap.read_u32(0x00), original_caps); // Should be unchanged
822
823        // Try to write to read-only Device Capabilities Register (offset 0x04)
824        let original_device_caps = cap.read_u32(0x04);
825        cap.write_u32(0x04, 0xFFFFFFFF);
826        assert_eq!(cap.read_u32(0x04), original_device_caps); // Should be unchanged
827    }
828
829    #[test]
830    fn test_pci_express_capability_write_u32_device_control() {
831        let flr_handler = TestFlrHandler::new();
832        let mut cap =
833            PciExpressCapability::new(DevicePortType::Endpoint, Some(flr_handler.clone()));
834
835        // Initial state should have FLR bit clear
836        let initial_ctl_sts = cap.read_u32(0x08);
837        assert_eq!(initial_ctl_sts & 0xFFFF, 0); // Device Control should be 0
838
839        // Test writing to Device Control Register (lower 16 bits of offset 0x08)
840        // Set some control bits but not FLR initially
841        cap.write_u32(0x08, 0x0001); // Enable correctable error reporting (bit 0)
842        let device_ctl_sts = cap.read_u32(0x08);
843        assert_eq!(device_ctl_sts & 0xFFFF, 0x0001); // Device Control should be set
844        assert!(!flr_handler.was_flr_initiated()); // FLR should not be triggered
845
846        // Test FLR initiation (bit 15 of Device Control)
847        flr_handler.reset();
848        cap.write_u32(0x08, 0x8001); // Set FLR bit (bit 15) and other control bits
849        let device_ctl_sts_after_flr = cap.read_u32(0x08);
850        assert_eq!(device_ctl_sts_after_flr & 0xFFFF, 0x0001); // FLR bit should be cleared, others remain
851        assert!(flr_handler.was_flr_initiated()); // FLR should be triggered
852
853        // Test that writing FLR bit when it's already been triggered behaves correctly
854        flr_handler.reset();
855        // After the previous FLR, device_control should have bit 0 set but FLR clear
856        // So writing 0x8000 (only FLR bit) should trigger FLR again
857        cap.write_u32(0x08, 0x8000); // Set FLR bit only
858        let device_ctl_sts_final = cap.read_u32(0x08);
859        assert_eq!(device_ctl_sts_final & 0xFFFF, 0x0000); // All bits should be cleared (FLR self-clears, bit 0 was overwritten)
860        assert!(flr_handler.was_flr_initiated()); // Should trigger because FLR transitioned from 0 to 1
861    }
862
863    #[test]
864    fn test_pci_express_capability_write_u32_device_status() {
865        let mut cap = PciExpressCapability::new(DevicePortType::Endpoint, None);
866
867        // Manually set some status bits to test write-1-to-clear behavior
868        {
869            let mut state = cap.state.lock();
870            state.device_status.set_correctable_error_detected(true);
871            state.device_status.set_non_fatal_error_detected(true);
872            state.device_status.set_fatal_error_detected(true);
873            state.device_status.set_unsupported_request_detected(true);
874        }
875
876        // Check that status bits are set
877        let device_ctl_sts = cap.read_u32(0x08);
878        let status_bits = (device_ctl_sts >> 16) & 0xFFFF;
879        assert_ne!(status_bits & 0x0F, 0); // Some status bits should be set
880
881        // Write 1 to clear correctable error bit (bit 0 of status)
882        cap.write_u32(0x08, 0x00010000); // Write 1 to bit 16 (correctable error in upper 16 bits)
883        let device_ctl_sts_after = cap.read_u32(0x08);
884        let status_bits_after = (device_ctl_sts_after >> 16) & 0xFFFF;
885        assert_eq!(status_bits_after & 0x01, 0); // Correctable error bit should be cleared
886        assert_ne!(status_bits_after & 0x0E, 0); // Other error bits should still be set
887
888        // Clear all remaining error bits
889        cap.write_u32(0x08, 0x000E0000); // Write 1 to bits 17-19 (other error bits)
890        let final_status = (cap.read_u32(0x08) >> 16) & 0xFFFF;
891        assert_eq!(final_status & 0x0F, 0); // All error bits should be cleared
892    }
893
894    #[test]
895    fn test_pci_express_capability_write_u32_unhandled_offset() {
896        let mut cap = PciExpressCapability::new(DevicePortType::Endpoint, None);
897
898        // Writing to unhandled offset should not panic
899        cap.write_u32(0x10, 0xFFFFFFFF);
900        // Should not crash and should not affect other registers
901        assert_eq!(cap.read_u32(0x08), 0); // Device Control/Status should still be 0
902    }
903
904    #[test]
905    fn test_pci_express_capability_reset() {
906        let flr_handler = TestFlrHandler::new();
907        let mut cap =
908            PciExpressCapability::new(DevicePortType::Endpoint, Some(flr_handler.clone()));
909
910        // Set some state
911        cap.write_u32(0x08, 0x0001); // Set some device control bits
912
913        // Manually set some status bits
914        {
915            let mut state = cap.state.lock();
916            state.device_status.set_correctable_error_detected(true);
917        }
918
919        // Verify state is set
920        let device_ctl_sts = cap.read_u32(0x08);
921        assert_ne!(device_ctl_sts, 0);
922
923        // Reset the capability
924        cap.reset();
925
926        // Verify state is cleared
927        let device_ctl_sts_after_reset = cap.read_u32(0x08);
928        assert_eq!(device_ctl_sts_after_reset, 0);
929    }
930
931    #[test]
932    fn test_pci_express_capability_extended_registers() {
933        let cap = PciExpressCapability::new(DevicePortType::Endpoint, None);
934
935        // Test that extended registers return proper default values and don't crash
936        // Link Capabilities should have default speed (Speed32_0GtS) and width (X16)
937        let expected_link_caps =
938            LinkSpeed::Speed32_0GtS.into_bits() | (LinkWidth::X16.into_bits() << 4); // speed + (width << 4) = 5 + (16 << 4) = 5 + 256 = 261
939        assert_eq!(cap.read_u32(0x0C), expected_link_caps); // Link Capabilities
940        // Link Control/Status should have Link Status with current_link_speed=5 and negotiated_link_width=16
941        let expected_link_ctl_sts = (LinkSpeed::Speed32_0GtS.into_bits() as u16)
942            | ((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
943        assert_eq!(cap.read_u32(0x10), (expected_link_ctl_sts as u32) << 16); // Link Control/Status (status in upper 16 bits)
944        assert_eq!(cap.read_u32(0x14), 0); // Slot Capabilities
945        assert_eq!(cap.read_u32(0x18), 0); // Slot Control/Status
946        assert_eq!(cap.read_u32(0x1C), 0); // Root Control/Capabilities
947        assert_eq!(cap.read_u32(0x20), 0); // Root Status
948        assert_eq!(cap.read_u32(0x24), 0); // Device Capabilities 2
949        assert_eq!(cap.read_u32(0x28), 0); // Device Control/Status 2
950        // Link Capabilities 2 has supported_link_speeds_vector set to UpToGen5
951        let expected_link_caps_2 = SupportedLinkSpeedsVector::UpToGen5.into_bits() << 1; // supported_link_speeds_vector at bits 1-7 = 31 << 1 = 62
952        assert_eq!(cap.read_u32(0x2C), expected_link_caps_2); // Link Capabilities 2
953        // Link Control/Status 2 - Link Control 2 should have target_link_speed set to Speed32_0GtS (5)
954        let expected_link_ctl_sts_2 = LinkSpeed::Speed32_0GtS.into_bits() as u16; // target_link_speed in lower 4 bits = 5
955        assert_eq!(cap.read_u32(0x30), expected_link_ctl_sts_2 as u32); // Link Control/Status 2
956        assert_eq!(cap.read_u32(0x34), 0); // Slot Capabilities 2
957        assert_eq!(cap.read_u32(0x38), 0); // Slot Control/Status 2
958    }
959
960    #[test]
961    fn test_pci_express_capability_length() {
962        let cap = PciExpressCapability::new(DevicePortType::Endpoint, None);
963        assert_eq!(cap.len(), 0x3C); // Should be 60 bytes (0x3C)
964    }
965
966    #[test]
967    fn test_pci_express_capability_label() {
968        let cap = PciExpressCapability::new(DevicePortType::Endpoint, None);
969        assert_eq!(cap.label(), "pci-express");
970    }
971
972    #[test]
973    fn test_pci_express_capability_with_hotplug_support() {
974        // Test with RootPort (should work)
975        let cap = PciExpressCapability::new(DevicePortType::RootPort, None);
976        let cap_with_hotplug = cap.with_hotplug_support(1);
977
978        // Verify that the method doesn't crash and returns the capability
979        assert_eq!(cap_with_hotplug.label(), "pci-express");
980        assert_eq!(cap_with_hotplug.len(), 0x3C);
981
982        // Verify hotplug capabilities are set
983        assert!(cap_with_hotplug.slot_capabilities.hot_plug_surprise());
984        assert!(cap_with_hotplug.slot_capabilities.hot_plug_capable());
985        assert_eq!(cap_with_hotplug.slot_capabilities.physical_slot_number(), 1);
986
987        // Verify that slot_implemented is set in PCIe capabilities
988        assert!(
989            cap_with_hotplug.pcie_capabilities.slot_implemented(),
990            "slot_implemented should be true when hotplug is enabled"
991        );
992
993        // Test with DownstreamSwitchPort (should work)
994        let cap2 = PciExpressCapability::new(DevicePortType::DownstreamSwitchPort, None);
995        let cap2_with_hotplug = cap2.with_hotplug_support(2);
996
997        assert!(cap2_with_hotplug.slot_capabilities.hot_plug_surprise());
998        assert!(cap2_with_hotplug.slot_capabilities.hot_plug_capable());
999        assert_eq!(
1000            cap2_with_hotplug.slot_capabilities.physical_slot_number(),
1001            2
1002        );
1003
1004        // Verify that slot_implemented is set for downstream switch port too
1005        assert!(
1006            cap2_with_hotplug.pcie_capabilities.slot_implemented(),
1007            "slot_implemented should be true when hotplug is enabled"
1008        );
1009
1010        // Test that non-hotplug capability doesn't have slot_implemented set
1011        let cap_no_hotplug = PciExpressCapability::new(DevicePortType::RootPort, None);
1012        assert!(
1013            !cap_no_hotplug.pcie_capabilities.slot_implemented(),
1014            "slot_implemented should be false when hotplug is not enabled"
1015        );
1016    }
1017
1018    #[test]
1019    #[should_panic(expected = "Hotplug support is not valid for device port type Endpoint")]
1020    fn test_pci_express_capability_with_hotplug_support_endpoint_panics() {
1021        let cap = PciExpressCapability::new(DevicePortType::Endpoint, None);
1022        cap.with_hotplug_support(1);
1023    }
1024
1025    #[test]
1026    #[should_panic(
1027        expected = "Hotplug support is not valid for device port type UpstreamSwitchPort"
1028    )]
1029    fn test_pci_express_capability_with_hotplug_support_upstream_panics() {
1030        let cap = PciExpressCapability::new(DevicePortType::UpstreamSwitchPort, None);
1031        cap.with_hotplug_support(1);
1032    }
1033
1034    #[test]
1035    fn test_slot_control_write_protection() {
1036        // Create a root port capability with hotplug support but limited slot capabilities
1037        let mut cap = PciExpressCapability::new(DevicePortType::RootPort, None);
1038        cap = cap.with_hotplug_support(1);
1039
1040        // Modify slot capabilities to disable some features for testing
1041        cap.slot_capabilities.set_attention_button_present(false);
1042        cap.slot_capabilities.set_power_controller_present(false);
1043        cap.slot_capabilities.set_mrl_sensor_present(false);
1044        cap.slot_capabilities.set_attention_indicator_present(false);
1045        cap.slot_capabilities.set_power_indicator_present(false);
1046        cap.slot_capabilities
1047            .set_electromechanical_interlock_present(false);
1048        cap.slot_capabilities.set_no_command_completed_support(true);
1049
1050        // Try to write to slot control register with all bits set
1051        let slot_ctl_sts_offset = 0x18; // SLOT_CTL_STS offset
1052        let val_to_write = 0xFFFFFFFF; // All bits set in both control and status
1053
1054        cap.write_u32(slot_ctl_sts_offset, val_to_write);
1055
1056        // Read back the slot control register (lower 16 bits)
1057        let read_back = cap.read_u32(slot_ctl_sts_offset);
1058        let slot_control_value = read_back as u16;
1059        let slot_control = pci_express::SlotControl::from_bits(slot_control_value);
1060
1061        // Verify that features not present in capabilities were not set in control register
1062        assert!(
1063            !slot_control.attention_button_pressed_enable(),
1064            "Attention button enable should be 0 when capability not present"
1065        );
1066        assert!(
1067            !slot_control.power_controller_control(),
1068            "Power controller control should be 0 when capability not present"
1069        );
1070        assert!(
1071            !slot_control.mrl_sensor_changed_enable(),
1072            "MRL sensor changed enable should be 0 when capability not present"
1073        );
1074        assert_eq!(
1075            slot_control.attention_indicator_control(),
1076            0,
1077            "Attention indicator control should be 0 when capability not present"
1078        );
1079        assert_eq!(
1080            slot_control.power_indicator_control(),
1081            0,
1082            "Power indicator control should be 0 when capability not present"
1083        );
1084        assert!(
1085            !slot_control.electromechanical_interlock_control(),
1086            "Electromechanical interlock control should be 0 when capability not present"
1087        );
1088        assert!(
1089            !slot_control.command_completed_interrupt_enable(),
1090            "Command completed interrupt enable should be 0 when no command completed support"
1091        );
1092
1093        // However, hotplug interrupt enable should be settable since hotplug is capable
1094        assert!(
1095            slot_control.hot_plug_interrupt_enable(),
1096            "Hotplug interrupt enable should be settable when hotplug capable"
1097        );
1098    }
1099
1100    #[test]
1101    fn test_link_control_retrain_link_behavior() {
1102        // Test that retrain_link always reads as 0 regardless of what is written
1103        let mut cap = PciExpressCapability::new(DevicePortType::RootPort, None);
1104
1105        let link_ctl_sts_offset = 0x10; // LINK_CTL_STS offset
1106
1107        // Write a value with retrain_link bit set (bit 5)
1108        let write_val = 0x0020; // retrain_link bit (bit 5) = 1
1109        cap.write_u32(link_ctl_sts_offset, write_val);
1110
1111        // Read back and verify retrain_link is always 0
1112        let read_back = cap.read_u32(link_ctl_sts_offset);
1113        let link_control = pci_express::LinkControl::from_bits(read_back as u16);
1114
1115        assert!(
1116            !link_control.retrain_link(),
1117            "retrain_link should always read as 0"
1118        );
1119
1120        // Verify other bits can still be set (except retrain_link)
1121        let write_val_2 = 0x0001; // aspm_control bit 0 = 1
1122        cap.write_u32(link_ctl_sts_offset, write_val_2);
1123
1124        let read_back_2 = cap.read_u32(link_ctl_sts_offset);
1125        let link_control_2 = pci_express::LinkControl::from_bits(read_back_2 as u16);
1126
1127        assert_eq!(
1128            link_control_2.aspm_control(),
1129            1,
1130            "Other control bits should be settable"
1131        );
1132        assert!(
1133            !link_control_2.retrain_link(),
1134            "retrain_link should still read as 0"
1135        );
1136    }
1137
1138    #[test]
1139    fn test_hotplug_link_capabilities() {
1140        // Test that Data Link Layer Link Active Reporting is enabled with hotplug
1141        let cap = PciExpressCapability::new(DevicePortType::RootPort, None);
1142        let cap_with_hotplug = cap.with_hotplug_support(1);
1143
1144        let link_caps_offset = 0x0C; // LINK_CAPS offset
1145        let link_caps = cap_with_hotplug.read_u32(link_caps_offset);
1146        let link_capabilities = pci_express::LinkCapabilities::from_bits(link_caps);
1147
1148        // Verify that Data Link Layer Link Active Reporting is enabled
1149        assert!(
1150            link_capabilities.data_link_layer_link_active_reporting(),
1151            "Data Link Layer Link Active Reporting should be enabled for hotplug"
1152        );
1153
1154        // Verify default speed and width are still correct
1155        assert_eq!(
1156            link_capabilities.max_link_speed(),
1157            LinkSpeed::Speed32_0GtS.into_bits(),
1158            "Max link speed should be Speed32_0GtS (PCIe 32.0 GT/s)"
1159        );
1160        assert_eq!(
1161            link_capabilities.max_link_width(),
1162            LinkWidth::X16.into_bits(),
1163            "Max link width should be X16 (x16)"
1164        );
1165
1166        // Test that non-hotplug capability doesn't have Data Link Layer Link Active Reporting
1167        let cap_no_hotplug = PciExpressCapability::new(DevicePortType::RootPort, None);
1168        let link_caps_no_hotplug = cap_no_hotplug.read_u32(link_caps_offset);
1169        let link_capabilities_no_hotplug =
1170            pci_express::LinkCapabilities::from_bits(link_caps_no_hotplug);
1171
1172        assert!(
1173            !link_capabilities_no_hotplug.data_link_layer_link_active_reporting(),
1174            "Data Link Layer Link Active Reporting should be disabled without hotplug"
1175        );
1176    }
1177
1178    #[test]
1179    fn test_link_status_read_only() {
1180        // Test that Link Status register is read-only and cannot be modified by writes
1181        let mut cap = PciExpressCapability::new(DevicePortType::RootPort, None);
1182
1183        let link_ctl_sts_offset = 0x10; // LINK_CTL_STS offset
1184
1185        // Set some initial link status values (this would normally be done by hardware)
1186        {
1187            let mut state = cap.state.lock();
1188            state.link_status.set_current_link_speed(0b0001); // Set initial speed
1189            state.link_status.set_negotiated_link_width(0b000001); // Set initial width
1190            state.link_status.set_link_training(true); // Set link training active
1191            state.link_status.set_data_link_layer_link_active(true); // Set DLL active
1192        }
1193
1194        // Read initial values
1195        let initial_read = cap.read_u32(link_ctl_sts_offset);
1196        let initial_link_status = pci_express::LinkStatus::from_bits((initial_read >> 16) as u16);
1197
1198        // Verify initial values are set
1199        assert_eq!(
1200            initial_link_status.current_link_speed(),
1201            0b0001,
1202            "Initial link speed should be set"
1203        );
1204        assert_eq!(
1205            initial_link_status.negotiated_link_width(),
1206            0b000001,
1207            "Initial link width should be set"
1208        );
1209        assert!(
1210            initial_link_status.link_training(),
1211            "Initial link training should be active"
1212        );
1213        assert!(
1214            initial_link_status.data_link_layer_link_active(),
1215            "Initial DLL should be active"
1216        );
1217
1218        // Try to write different values to Link Status (upper 16 bits) while also writing to Link Control
1219        let write_val = 0xFFFF0001; // Upper 16 bits all 1s (Link Status), lower 16 bits = 1 (Link Control)
1220        cap.write_u32(link_ctl_sts_offset, write_val);
1221
1222        // Read back and verify Link Status hasn't changed
1223        let after_write = cap.read_u32(link_ctl_sts_offset);
1224        let final_link_status = pci_express::LinkStatus::from_bits((after_write >> 16) as u16);
1225        let final_link_control = pci_express::LinkControl::from_bits(after_write as u16);
1226
1227        // Link Status should remain unchanged (read-only)
1228        assert_eq!(
1229            final_link_status.current_link_speed(),
1230            initial_link_status.current_link_speed(),
1231            "Link Status current_link_speed should be read-only"
1232        );
1233        assert_eq!(
1234            final_link_status.negotiated_link_width(),
1235            initial_link_status.negotiated_link_width(),
1236            "Link Status negotiated_link_width should be read-only"
1237        );
1238        assert_eq!(
1239            final_link_status.link_training(),
1240            initial_link_status.link_training(),
1241            "Link Status link_training should be read-only"
1242        );
1243        assert_eq!(
1244            final_link_status.data_link_layer_link_active(),
1245            initial_link_status.data_link_layer_link_active(),
1246            "Link Status data_link_layer_link_active should be read-only"
1247        );
1248
1249        // But Link Control should be modifiable
1250        assert_eq!(
1251            final_link_control.aspm_control(),
1252            1,
1253            "Link Control should be writable"
1254        );
1255    }
1256
1257    #[test]
1258    fn test_slot_status_rw1c_behavior() {
1259        // Create a root port capability with hotplug support
1260        let mut cap = PciExpressCapability::new(DevicePortType::RootPort, None);
1261        cap = cap.with_hotplug_support(1);
1262
1263        let slot_ctl_sts_offset = 0x18; // SLOT_CTL_STS offset
1264
1265        // First, simulate setting some status bits (this would normally be done by hardware)
1266        {
1267            let mut state = cap.state.lock();
1268            state.slot_status.set_attention_button_pressed(true);
1269            state.slot_status.set_power_fault_detected(true);
1270            state.slot_status.set_mrl_sensor_changed(true);
1271            state.slot_status.set_presence_detect_changed(true);
1272            state.slot_status.set_command_completed(true);
1273            state.slot_status.set_data_link_layer_state_changed(true);
1274            // Set some RO bits too
1275            state.slot_status.set_mrl_sensor_state(1);
1276            state.slot_status.set_presence_detect_state(1);
1277            state.slot_status.set_electromechanical_interlock_status(1);
1278        }
1279
1280        // Read the initial status to verify all bits are set
1281        let initial_read = cap.read_u32(slot_ctl_sts_offset);
1282        let initial_status = pci_express::SlotStatus::from_bits((initial_read >> 16) as u16);
1283        assert!(
1284            initial_status.attention_button_pressed(),
1285            "Initial attention button pressed should be set"
1286        );
1287        assert!(
1288            initial_status.power_fault_detected(),
1289            "Initial power fault detected should be set"
1290        );
1291        assert!(
1292            initial_status.mrl_sensor_changed(),
1293            "Initial MRL sensor changed should be set"
1294        );
1295        assert!(
1296            initial_status.presence_detect_changed(),
1297            "Initial presence detect changed should be set"
1298        );
1299        assert!(
1300            initial_status.command_completed(),
1301            "Initial command completed should be set"
1302        );
1303        assert!(
1304            initial_status.data_link_layer_state_changed(),
1305            "Initial data link layer state changed should be set"
1306        );
1307        assert_eq!(
1308            initial_status.mrl_sensor_state(),
1309            1,
1310            "Initial MRL sensor state should be set"
1311        );
1312        assert_eq!(
1313            initial_status.presence_detect_state(),
1314            1,
1315            "Initial presence detect state should be set"
1316        );
1317        assert_eq!(
1318            initial_status.electromechanical_interlock_status(),
1319            1,
1320            "Initial electromechanical interlock status should be set"
1321        );
1322
1323        // Write 1 to clear specific RW1C bits (upper 16 bits contain status)
1324        // Write 1s only to some RW1C bits to test selective clearing
1325        // Bit positions: attention_button_pressed(0), command_completed(4), data_link_layer_state_changed(8)
1326        let write_val = (0b0000_0001_0001_0001_u16 as u32) << 16; // Clear bits 0, 4, and 8
1327        cap.write_u32(slot_ctl_sts_offset, write_val);
1328
1329        // Read back and verify RW1C behavior
1330        let after_write = cap.read_u32(slot_ctl_sts_offset);
1331        let final_status = pci_express::SlotStatus::from_bits((after_write >> 16) as u16);
1332
1333        // RW1C bits that were written with 1 should be cleared
1334        assert!(
1335            !final_status.attention_button_pressed(),
1336            "Attention button pressed should be cleared after write-1"
1337        );
1338        assert!(
1339            !final_status.command_completed(),
1340            "Command completed should be cleared after write-1"
1341        );
1342        assert!(
1343            !final_status.data_link_layer_state_changed(),
1344            "Data link layer state changed should be cleared after write-1"
1345        );
1346
1347        // RW1C bits that were written with 0 should remain unchanged
1348        assert!(
1349            final_status.power_fault_detected(),
1350            "Power fault detected should remain set (write-0)"
1351        );
1352        assert!(
1353            final_status.mrl_sensor_changed(),
1354            "MRL sensor changed should remain set (write-0)"
1355        );
1356        assert!(
1357            final_status.presence_detect_changed(),
1358            "Presence detect changed should remain set (write-0)"
1359        );
1360
1361        // RO bits should remain unchanged regardless of what was written
1362        assert_eq!(
1363            final_status.mrl_sensor_state(),
1364            1,
1365            "MRL sensor state should remain unchanged (RO)"
1366        );
1367        assert_eq!(
1368            final_status.presence_detect_state(),
1369            1,
1370            "Presence detect state should remain unchanged (RO)"
1371        );
1372        assert_eq!(
1373            final_status.electromechanical_interlock_status(),
1374            1,
1375            "Electromechanical interlock status should remain unchanged (RO)"
1376        );
1377    }
1378
1379    #[test]
1380    fn test_link_control_2_target_speed_validation() {
1381        // Test that target link speed is validated against max link speed and reflected in link status
1382        let mut cap = PciExpressCapability::new(DevicePortType::RootPort, None);
1383
1384        let link_ctl_sts_2_offset = 0x30; // LINK_CTL_STS_2 offset
1385
1386        // Initially, target link speed should be Speed32_0GtS (5) and current link speed should match
1387        let initial_read = cap.read_u32(link_ctl_sts_2_offset);
1388        let initial_link_control_2 = pci_express::LinkControl2::from_bits(initial_read as u16);
1389        assert_eq!(
1390            initial_link_control_2.target_link_speed(),
1391            LinkSpeed::Speed32_0GtS.into_bits() as u16,
1392            "Initial target link speed should be Speed32_0GtS"
1393        );
1394
1395        // Check that link status reflects this speed
1396        let link_ctl_sts_offset = 0x10; // LINK_CTL_STS offset
1397        let link_ctl_sts = cap.read_u32(link_ctl_sts_offset);
1398        let link_status = pci_express::LinkStatus::from_bits((link_ctl_sts >> 16) as u16);
1399        assert_eq!(
1400            link_status.current_link_speed(),
1401            LinkSpeed::Speed32_0GtS.into_bits() as u16,
1402            "Initial current link speed should match target speed"
1403        );
1404        assert_eq!(
1405            link_status.negotiated_link_width(),
1406            LinkWidth::X16.into_bits() as u16,
1407            "Initial negotiated link width should be X16"
1408        );
1409
1410        // Test writing a valid speed (Speed16_0GtS = 4) that's less than max speed (Speed32_0GtS = 5)
1411        let valid_speed = LinkSpeed::Speed16_0GtS.into_bits() as u16; // 4
1412        cap.write_u32(link_ctl_sts_2_offset, valid_speed as u32);
1413
1414        // Verify target link speed was set correctly
1415        let after_valid_write = cap.read_u32(link_ctl_sts_2_offset);
1416        let link_control_2_after_valid =
1417            pci_express::LinkControl2::from_bits(after_valid_write as u16);
1418        assert_eq!(
1419            link_control_2_after_valid.target_link_speed(),
1420            valid_speed,
1421            "Target link speed should be set to requested valid speed"
1422        );
1423
1424        // Verify current link speed was updated in link status
1425        let link_ctl_sts_after_valid = cap.read_u32(link_ctl_sts_offset);
1426        let link_status_after_valid =
1427            pci_express::LinkStatus::from_bits((link_ctl_sts_after_valid >> 16) as u16);
1428        assert_eq!(
1429            link_status_after_valid.current_link_speed(),
1430            valid_speed,
1431            "Current link speed should be updated to match target speed"
1432        );
1433
1434        // Test writing an invalid speed (Speed64_0GtS = 6) that exceeds max speed (Speed32_0GtS = 5)
1435        let invalid_speed = LinkSpeed::Speed64_0GtS.into_bits() as u16; // 6
1436        cap.write_u32(link_ctl_sts_2_offset, invalid_speed as u32);
1437
1438        // Verify target link speed was clamped to max speed
1439        let after_invalid_write = cap.read_u32(link_ctl_sts_2_offset);
1440        let link_control_2_after_invalid =
1441            pci_express::LinkControl2::from_bits(after_invalid_write as u16);
1442        let max_speed = LinkSpeed::Speed32_0GtS.into_bits() as u16; // 5
1443        assert_eq!(
1444            link_control_2_after_invalid.target_link_speed(),
1445            max_speed,
1446            "Target link speed should be clamped to max supported speed"
1447        );
1448
1449        // Verify current link speed was updated to the clamped value
1450        let link_ctl_sts_after_invalid = cap.read_u32(link_ctl_sts_offset);
1451        let link_status_after_invalid =
1452            pci_express::LinkStatus::from_bits((link_ctl_sts_after_invalid >> 16) as u16);
1453        assert_eq!(
1454            link_status_after_invalid.current_link_speed(),
1455            max_speed,
1456            "Current link speed should be updated to clamped max speed"
1457        );
1458
1459        // Verify that link width remains unchanged throughout
1460        assert_eq!(
1461            link_status_after_valid.negotiated_link_width(),
1462            LinkWidth::X16.into_bits() as u16,
1463            "Negotiated link width should remain unchanged"
1464        );
1465        assert_eq!(
1466            link_status_after_invalid.negotiated_link_width(),
1467            LinkWidth::X16.into_bits() as u16,
1468            "Negotiated link width should remain unchanged"
1469        );
1470    }
1471
1472    #[test]
1473    fn test_with_hotplug_support_slot_number() {
1474        // Test that slot numbers are properly set when enabling hotplug support
1475
1476        // Test with slot number 5
1477        let cap1 = PciExpressCapability::new(DevicePortType::RootPort, None);
1478        let cap1_with_hotplug = cap1.with_hotplug_support(5);
1479
1480        assert!(cap1_with_hotplug.slot_capabilities.hot_plug_capable());
1481        assert_eq!(
1482            cap1_with_hotplug.slot_capabilities.physical_slot_number(),
1483            5
1484        );
1485
1486        // Test with slot number 0
1487        let cap2 = PciExpressCapability::new(DevicePortType::DownstreamSwitchPort, None);
1488        let cap2_with_hotplug = cap2.with_hotplug_support(0);
1489
1490        assert!(cap2_with_hotplug.slot_capabilities.hot_plug_capable());
1491        assert_eq!(
1492            cap2_with_hotplug.slot_capabilities.physical_slot_number(),
1493            0
1494        );
1495
1496        // Test with a larger slot number
1497        let cap3 = PciExpressCapability::new(DevicePortType::RootPort, None);
1498        let cap3_with_hotplug = cap3.with_hotplug_support(255);
1499
1500        assert!(cap3_with_hotplug.slot_capabilities.hot_plug_capable());
1501        assert_eq!(
1502            cap3_with_hotplug.slot_capabilities.physical_slot_number(),
1503            255
1504        );
1505    }
1506
1507    #[test]
1508    fn test_slot_implemented_flag_in_pcie_capabilities_register() {
1509        // Test that slot_implemented bit is correctly set in the PCIe Capabilities register
1510        // when hotplug support is enabled
1511
1512        // Test without hotplug - slot_implemented should be false
1513        let cap_no_hotplug = PciExpressCapability::new(DevicePortType::RootPort, None);
1514        let caps_val_no_hotplug = cap_no_hotplug.read_u32(0x00);
1515        let pcie_caps_no_hotplug = (caps_val_no_hotplug >> 16) as u16;
1516        let slot_implemented_bit = (pcie_caps_no_hotplug >> 8) & 0x1; // slot_implemented is bit 8 of PCIe capabilities
1517        assert_eq!(
1518            slot_implemented_bit, 0,
1519            "slot_implemented should be 0 when hotplug is not enabled"
1520        );
1521
1522        // Test with hotplug - slot_implemented should be true
1523        let cap_with_hotplug = cap_no_hotplug.with_hotplug_support(1);
1524        let caps_val_with_hotplug = cap_with_hotplug.read_u32(0x00);
1525        let pcie_caps_with_hotplug = (caps_val_with_hotplug >> 16) as u16;
1526        let slot_implemented_bit_hotplug = (pcie_caps_with_hotplug >> 8) & 0x1; // slot_implemented is bit 8 of PCIe capabilities
1527        assert_eq!(
1528            slot_implemented_bit_hotplug, 1,
1529            "slot_implemented should be 1 when hotplug is enabled"
1530        );
1531    }
1532
1533    #[test]
1534    fn test_set_presence_detect_state() {
1535        // Test setting presence detect state on a hotplug-capable port
1536        let cap = PciExpressCapability::new(DevicePortType::RootPort, None).with_hotplug_support(1);
1537
1538        // Initially, presence detect state should be 0 (no device present)
1539        let initial_slot_status = cap.read_u32(0x18); // Slot Control + Slot Status
1540        let initial_presence_detect = (initial_slot_status >> 22) & 0x1; // presence_detect_state is bit 6 of slot status (upper 16 bits)
1541        assert_eq!(
1542            initial_presence_detect, 0,
1543            "Initial presence detect state should be 0"
1544        );
1545
1546        // Set device as present
1547        cap.set_presence_detect_state(true);
1548        let present_slot_status = cap.read_u32(0x18);
1549        let present_presence_detect = (present_slot_status >> 22) & 0x1;
1550        assert_eq!(
1551            present_presence_detect, 1,
1552            "Presence detect state should be 1 when device is present"
1553        );
1554
1555        // Set device as not present
1556        cap.set_presence_detect_state(false);
1557        let absent_slot_status = cap.read_u32(0x18);
1558        let absent_presence_detect = (absent_slot_status >> 22) & 0x1;
1559        assert_eq!(
1560            absent_presence_detect, 0,
1561            "Presence detect state should be 0 when device is not present"
1562        );
1563    }
1564
1565    #[test]
1566    fn test_set_presence_detect_state_without_slot_implemented() {
1567        // Test that setting presence detect state is silently ignored when slot is not implemented
1568        let cap = PciExpressCapability::new(DevicePortType::RootPort, None);
1569
1570        // Should not panic and should be silently ignored
1571        cap.set_presence_detect_state(true);
1572        cap.set_presence_detect_state(false);
1573    }
1574
1575    #[test]
1576    fn test_save_restore_default_state() {
1577        use vmcore::save_restore::SaveRestore;
1578
1579        // Create a capability with default state
1580        let mut cap = PciExpressCapability::new(DevicePortType::Endpoint, None);
1581
1582        // Save the default state
1583        let saved = cap.save().expect("save should succeed");
1584
1585        // Verify default state values
1586        assert_eq!(saved.device_control, 0);
1587        assert_eq!(saved.device_status, 0);
1588        assert_eq!(saved.link_control, 0);
1589        // Link status has default values for speed and width
1590        let expected_link_status = (LinkSpeed::Speed32_0GtS.into_bits() as u16)
1591            | ((LinkWidth::X16.into_bits() as u16) << 4);
1592        assert_eq!(saved.link_status, expected_link_status);
1593        assert_eq!(saved.slot_control, 0);
1594        assert_eq!(saved.slot_status, 0);
1595        assert_eq!(saved.root_control, 0);
1596        assert_eq!(saved.root_status, 0);
1597        assert_eq!(saved.device_control_2, 0);
1598        assert_eq!(saved.device_status_2, 0);
1599        // Link control 2 has default target_link_speed
1600        let expected_link_control_2 = LinkSpeed::Speed32_0GtS.into_bits() as u16;
1601        assert_eq!(saved.link_control_2, expected_link_control_2);
1602        assert_eq!(saved.link_status_2, 0);
1603        assert_eq!(saved.slot_control_2, 0);
1604        assert_eq!(saved.slot_status_2, 0);
1605    }
1606
1607    #[test]
1608    fn test_save_restore_modified_state() {
1609        use vmcore::save_restore::SaveRestore;
1610
1611        let mut cap = PciExpressCapability::new(DevicePortType::Endpoint, None);
1612
1613        // Modify state by writing to registers
1614        // Write to Device Control (offset 0x08, lower 16 bits)
1615        cap.write_u32(0x08, 0x0005); // Set some device control bits
1616
1617        // Write to Link Control (offset 0x10, lower 16 bits)
1618        cap.write_u32(0x10, 0x0003); // Set ASPM control bits
1619
1620        // Write to Device Control 2 (offset 0x28, lower 16 bits)
1621        cap.write_u32(0x28, 0x0010); // Set some device control 2 bits
1622
1623        // Save the modified state
1624        let saved = cap.save().expect("save should succeed");
1625
1626        // Verify the saved state reflects the modifications
1627        assert_eq!(saved.device_control, 0x0005);
1628        assert_eq!(saved.link_control, 0x0003);
1629        assert_eq!(saved.device_control_2, 0x0010);
1630    }
1631
1632    #[test]
1633    fn test_save_restore_roundtrip() {
1634        use vmcore::save_restore::SaveRestore;
1635
1636        let mut cap = PciExpressCapability::new(DevicePortType::RootPort, None);
1637
1638        // Modify various state registers
1639        cap.write_u32(0x08, 0x000F); // Device Control
1640        cap.write_u32(0x10, 0x0007); // Link Control
1641        cap.write_u32(0x28, 0x0020); // Device Control 2
1642        cap.write_u32(0x30, 0x0004); // Link Control 2 (target speed = 4)
1643
1644        // Save the state
1645        let saved = cap.save().expect("save should succeed");
1646
1647        // Create a new capability and restore the saved state
1648        let mut cap2 = PciExpressCapability::new(DevicePortType::RootPort, None);
1649        cap2.restore(saved).expect("restore should succeed");
1650
1651        // Verify restored state by reading registers
1652        let device_ctl_sts = cap2.read_u32(0x08);
1653        assert_eq!(
1654            device_ctl_sts & 0xFFFF,
1655            0x000F,
1656            "Device control should be restored"
1657        );
1658
1659        let link_ctl_sts = cap2.read_u32(0x10);
1660        assert_eq!(
1661            link_ctl_sts & 0xFFFF,
1662            0x0007,
1663            "Link control should be restored"
1664        );
1665
1666        let device_ctl_sts_2 = cap2.read_u32(0x28);
1667        assert_eq!(
1668            device_ctl_sts_2 & 0xFFFF,
1669            0x0020,
1670            "Device control 2 should be restored"
1671        );
1672
1673        let link_ctl_sts_2 = cap2.read_u32(0x30);
1674        assert_eq!(
1675            link_ctl_sts_2 & 0xFFFF,
1676            0x0004,
1677            "Link control 2 should be restored"
1678        );
1679    }
1680
1681    #[test]
1682    fn test_save_restore_with_status_bits() {
1683        use vmcore::save_restore::SaveRestore;
1684
1685        let mut cap = PciExpressCapability::new(DevicePortType::RootPort, None);
1686        cap = cap.with_hotplug_support(1);
1687
1688        // Manually set some status bits that would normally be set by hardware
1689        {
1690            let mut state = cap.state.lock();
1691            state.device_status.set_correctable_error_detected(true);
1692            state.device_status.set_non_fatal_error_detected(true);
1693            state.slot_status.set_presence_detect_changed(true);
1694            state.slot_status.set_presence_detect_state(1);
1695        }
1696
1697        // Save the state
1698        let saved = cap.save().expect("save should succeed");
1699
1700        // Verify status bits are in saved state
1701        let saved_device_status = pci_express::DeviceStatus::from_bits(saved.device_status);
1702        let saved_slot_status = pci_express::SlotStatus::from_bits(saved.slot_status);
1703        assert!(saved_device_status.correctable_error_detected());
1704        assert!(saved_device_status.non_fatal_error_detected());
1705        assert!(saved_slot_status.presence_detect_changed());
1706        assert_eq!(saved_slot_status.presence_detect_state(), 1);
1707
1708        // Restore to a new capability and verify
1709        let mut cap2 = PciExpressCapability::new(DevicePortType::RootPort, None);
1710        cap2 = cap2.with_hotplug_support(1);
1711        cap2.restore(saved).expect("restore should succeed");
1712
1713        // Read back and verify status bits were restored
1714        let device_ctl_sts = cap2.read_u32(0x08);
1715        let restored_device_status =
1716            pci_express::DeviceStatus::from_bits((device_ctl_sts >> 16) as u16);
1717        assert!(
1718            restored_device_status.correctable_error_detected(),
1719            "Device status should be restored"
1720        );
1721        assert!(
1722            restored_device_status.non_fatal_error_detected(),
1723            "Device status should be restored"
1724        );
1725
1726        let slot_ctl_sts = cap2.read_u32(0x18);
1727        let restored_slot_status = pci_express::SlotStatus::from_bits((slot_ctl_sts >> 16) as u16);
1728        assert!(
1729            restored_slot_status.presence_detect_changed(),
1730            "Slot status should be restored"
1731        );
1732        assert_eq!(
1733            restored_slot_status.presence_detect_state(),
1734            1,
1735            "Presence detect state should be restored"
1736        );
1737    }
1738
1739    #[test]
1740    fn test_save_restore_all_fields() {
1741        use vmcore::save_restore::SaveRestore;
1742
1743        let mut cap = PciExpressCapability::new(DevicePortType::RootPort, None);
1744
1745        // Set all state fields to non-zero values
1746        {
1747            let mut state = cap.state.lock();
1748            state.device_control = pci_express::DeviceControl::from_bits(0x1111);
1749            state.device_status = pci_express::DeviceStatus::from_bits(0x2222);
1750            state.link_control = pci_express::LinkControl::from_bits(0x3333);
1751            state.link_status = pci_express::LinkStatus::from_bits(0x4444);
1752            state.slot_control = pci_express::SlotControl::from_bits(0x5555);
1753            state.slot_status = pci_express::SlotStatus::from_bits(0x6666);
1754            state.root_control = pci_express::RootControl::from_bits(0x7777);
1755            state.root_status = pci_express::RootStatus::from_bits(0x88888888);
1756            state.device_control_2 = pci_express::DeviceControl2::from_bits(0x9999);
1757            state.device_status_2 = pci_express::DeviceStatus2::from_bits(0xAAAA);
1758            state.link_control_2 = pci_express::LinkControl2::from_bits(0xBBBB);
1759            state.link_status_2 = pci_express::LinkStatus2::from_bits(0xCCCC);
1760            state.slot_control_2 = pci_express::SlotControl2::from_bits(0xDDDD);
1761            state.slot_status_2 = pci_express::SlotStatus2::from_bits(0xEEEE);
1762        }
1763
1764        // Save the state
1765        let saved = cap.save().expect("save should succeed");
1766
1767        // Verify all fields in saved state
1768        assert_eq!(saved.device_control, 0x1111);
1769        assert_eq!(saved.device_status, 0x2222);
1770        assert_eq!(saved.link_control, 0x3333);
1771        assert_eq!(saved.link_status, 0x4444);
1772        assert_eq!(saved.slot_control, 0x5555);
1773        assert_eq!(saved.slot_status, 0x6666);
1774        assert_eq!(saved.root_control, 0x7777);
1775        assert_eq!(saved.root_status, 0x88888888);
1776        assert_eq!(saved.device_control_2, 0x9999);
1777        assert_eq!(saved.device_status_2, 0xAAAA);
1778        assert_eq!(saved.link_control_2, 0xBBBB);
1779        assert_eq!(saved.link_status_2, 0xCCCC);
1780        assert_eq!(saved.slot_control_2, 0xDDDD);
1781        assert_eq!(saved.slot_status_2, 0xEEEE);
1782
1783        // Restore to a new capability
1784        let mut cap2 = PciExpressCapability::new(DevicePortType::RootPort, None);
1785        cap2.restore(saved).expect("restore should succeed");
1786
1787        // Save again and verify it matches
1788        let saved2 = cap2.save().expect("second save should succeed");
1789        assert_eq!(saved2.device_control, 0x1111);
1790        assert_eq!(saved2.device_status, 0x2222);
1791        assert_eq!(saved2.link_control, 0x3333);
1792        assert_eq!(saved2.link_status, 0x4444);
1793        assert_eq!(saved2.slot_control, 0x5555);
1794        assert_eq!(saved2.slot_status, 0x6666);
1795        assert_eq!(saved2.root_control, 0x7777);
1796        assert_eq!(saved2.root_status, 0x88888888);
1797        assert_eq!(saved2.device_control_2, 0x9999);
1798        assert_eq!(saved2.device_status_2, 0xAAAA);
1799        assert_eq!(saved2.link_control_2, 0xBBBB);
1800        assert_eq!(saved2.link_status_2, 0xCCCC);
1801        assert_eq!(saved2.slot_control_2, 0xDDDD);
1802        assert_eq!(saved2.slot_status_2, 0xEEEE);
1803    }
1804
1805    #[test]
1806    fn test_save_after_reset() {
1807        use vmcore::save_restore::SaveRestore;
1808
1809        let mut cap = PciExpressCapability::new(DevicePortType::Endpoint, None);
1810
1811        // Modify state
1812        cap.write_u32(0x08, 0x00FF);
1813        cap.write_u32(0x10, 0x00FF);
1814
1815        // Reset
1816        cap.reset();
1817
1818        // Save after reset
1819        let saved = cap.save().expect("save should succeed");
1820
1821        // Verify state is back to defaults
1822        assert_eq!(saved.device_control, 0);
1823        assert_eq!(saved.device_status, 0);
1824        assert_eq!(saved.link_control, 0);
1825        // Link status has default speed and width
1826        let expected_link_status = (LinkSpeed::Speed32_0GtS.into_bits() as u16)
1827            | ((LinkWidth::X16.into_bits() as u16) << 4);
1828        assert_eq!(saved.link_status, expected_link_status);
1829    }
1830}