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::PciExpressCapabilityHeader;
10use inspect::Inspect;
11use parking_lot::Mutex;
12use std::sync::Arc;
13
14/// FLR bit is the 28th bit in the Device Capabilities register (0 indexed).
15pub const PCI_EXPRESS_DEVICE_CAPS_FLR_BIT_MASK: u32 = 1 << 28;
16
17/// Callback interface for handling Function Level Reset (FLR) events.
18pub trait FlrHandler: Send + Sync + Inspect {
19    /// Called when Function Level Reset is initiated.
20    fn initiate_flr(&self);
21}
22
23#[derive(Debug, Inspect)]
24struct PciExpressState {
25    device_control: pci_express::DeviceControl,
26    device_status: pci_express::DeviceStatus,
27    link_control: pci_express::LinkControl,
28    link_status: pci_express::LinkStatus,
29    slot_control: pci_express::SlotControl,
30    slot_status: pci_express::SlotStatus,
31    root_control: pci_express::RootControl,
32    root_status: pci_express::RootStatus,
33    device_control_2: pci_express::DeviceControl2,
34    device_status_2: pci_express::DeviceStatus2,
35    link_control_2: pci_express::LinkControl2,
36    link_status_2: pci_express::LinkStatus2,
37    slot_control_2: pci_express::SlotControl2,
38    slot_status_2: pci_express::SlotStatus2,
39}
40
41impl PciExpressState {
42    fn new() -> Self {
43        Self {
44            device_control: pci_express::DeviceControl::new(),
45            device_status: pci_express::DeviceStatus::new(),
46            link_control: pci_express::LinkControl::new(),
47            link_status: pci_express::LinkStatus::new(),
48            slot_control: pci_express::SlotControl::new(),
49            slot_status: pci_express::SlotStatus::new(),
50            root_control: pci_express::RootControl::new(),
51            root_status: pci_express::RootStatus::new(),
52            device_control_2: pci_express::DeviceControl2::new(),
53            device_status_2: pci_express::DeviceStatus2::new(),
54            link_control_2: pci_express::LinkControl2::new(),
55            link_status_2: pci_express::LinkStatus2::new(),
56            slot_control_2: pci_express::SlotControl2::new(),
57            slot_status_2: pci_express::SlotStatus2::new(),
58        }
59    }
60}
61
62#[derive(Inspect)]
63/// Configurable PCI Express capability.
64pub struct PciExpressCapability {
65    pcie_capabilities: pci_express::PciExpressCapabilities,
66    device_capabilities: pci_express::DeviceCapabilities,
67    link_capabilities: pci_express::LinkCapabilities,
68    slot_capabilities: pci_express::SlotCapabilities,
69    root_capabilities: pci_express::RootCapabilities,
70    device_capabilities_2: pci_express::DeviceCapabilities2,
71    link_capabilities_2: pci_express::LinkCapabilities2,
72    slot_capabilities_2: pci_express::SlotCapabilities2,
73    state: Arc<Mutex<PciExpressState>>,
74    #[inspect(skip)]
75    flr_handler: Option<Arc<dyn FlrHandler>>,
76}
77
78impl PciExpressCapability {
79    /// Creates a new PCI Express capability with FLR support.
80    ///
81    /// # Arguments
82    /// * `typ` - The spec-defined device or port type.
83    /// * `flr_handler` - Optional handler to be called when FLR is initiated. This emulator will report that FLR is supported if flr_handler = Some(_)
84    pub fn new(typ: pci_express::DevicePortType, flr_handler: Option<Arc<dyn FlrHandler>>) -> Self {
85        Self {
86            pcie_capabilities: pci_express::PciExpressCapabilities::new()
87                .with_capability_version(2)
88                .with_device_port_type(typ),
89            device_capabilities: pci_express::DeviceCapabilities::new()
90                .with_function_level_reset(flr_handler.is_some()),
91            link_capabilities: pci_express::LinkCapabilities::new(),
92            slot_capabilities: pci_express::SlotCapabilities::new(),
93            root_capabilities: pci_express::RootCapabilities::new(),
94            device_capabilities_2: pci_express::DeviceCapabilities2::new(),
95            link_capabilities_2: pci_express::LinkCapabilities2::new(),
96            slot_capabilities_2: pci_express::SlotCapabilities2::new(),
97            state: Arc::new(Mutex::new(PciExpressState::new())),
98            flr_handler,
99        }
100    }
101
102    fn handle_device_control_write(&mut self, new_control: pci_express::DeviceControl) {
103        let mut state = self.state.lock();
104
105        // Check if FLR was initiated
106        let old_flr = state.device_control.initiate_function_level_reset();
107        let new_flr = new_control.initiate_function_level_reset();
108
109        // DEVNOTE: It is "safe" to drop a new FLR request if there is still a previous
110        // FLR request in progress. The PCIe spec indicates that such behavior is undefined,
111        // so we choose to ignore the new FLR request.
112        if new_flr && !old_flr {
113            if let Some(handler) = &self.flr_handler {
114                handler.initiate_flr();
115            }
116        }
117
118        // Update the control register but clear the FLR bit as it's self-clearing
119        state.device_control = new_control.with_initiate_function_level_reset(false);
120    }
121}
122
123impl PciCapability for PciExpressCapability {
124    fn label(&self) -> &str {
125        "pci-express"
126    }
127
128    fn len(&self) -> usize {
129        // Implement the full PCI Express Capability structure (PCI Spec, Section 7.5.3):
130        // 0x00: PCIe Capabilities (2 bytes) + Next Pointer (1 byte) + Capability ID (1 byte)
131        // 0x04: Device Capabilities (4 bytes)
132        // 0x08: Device Control (2 bytes) + Device Status (2 bytes)
133        // 0x0C: Link Capabilities (4 bytes)
134        // 0x10: Link Control (2 bytes) + Link Status (2 bytes)
135        // 0x14: Slot Capabilities (4 bytes)
136        // 0x18: Slot Control (2 bytes) + Slot Status (2 bytes)
137        // 0x1C: Root Control (2 bytes) + Root Capabilities (2 bytes)
138        // 0x20: Root Status (4 bytes)
139        // 0x24: Device Capabilities 2 (4 bytes)
140        // 0x28: Device Control 2 (2 bytes) + Device Status 2 (2 bytes)
141        // 0x2C: Link Capabilities 2 (4 bytes)
142        // 0x30: Link Control 2 (2 bytes) + Link Status 2 (2 bytes)
143        // 0x34: Slot Capabilities 2 (4 bytes)
144        // 0x38: Slot Control 2 (2 bytes) + Slot Status 2 (2 bytes)
145        // Total: 60 bytes (0x3C)
146        0x3C
147    }
148
149    fn read_u32(&self, offset: u16) -> u32 {
150        let label = self.label();
151        match PciExpressCapabilityHeader(offset) {
152            PciExpressCapabilityHeader::PCIE_CAPS => {
153                // PCIe Capabilities Register (16 bits) + Next Pointer (8 bits) + Capability ID (8 bits)
154                (self.pcie_capabilities.into_bits() as u32) << 16
155                    | CapabilityId::PCI_EXPRESS.0 as u32
156            }
157            PciExpressCapabilityHeader::DEVICE_CAPS => self.device_capabilities.into_bits(),
158            PciExpressCapabilityHeader::DEVICE_CTL_STS => {
159                let state = self.state.lock();
160                let device_control = state.device_control.into_bits() as u32;
161                let device_status = state.device_status.into_bits() as u32;
162                device_control | (device_status << 16)
163            }
164            PciExpressCapabilityHeader::LINK_CAPS => self.link_capabilities.into_bits(),
165            PciExpressCapabilityHeader::LINK_CTL_STS => {
166                // Link Control (2 bytes) + Link Status (2 bytes)
167                let state = self.state.lock();
168                state.link_control.into_bits() as u32
169                    | ((state.link_status.into_bits() as u32) << 16)
170            }
171            PciExpressCapabilityHeader::SLOT_CAPS => self.slot_capabilities.into_bits(),
172            PciExpressCapabilityHeader::SLOT_CTL_STS => {
173                // Slot Control (2 bytes) + Slot Status (2 bytes)
174                let state = self.state.lock();
175                state.slot_control.into_bits() as u32
176                    | ((state.slot_status.into_bits() as u32) << 16)
177            }
178            PciExpressCapabilityHeader::ROOT_CTL_CAPS => {
179                // Root Control (2 bytes) + Root Capabilities (2 bytes)
180                let state = self.state.lock();
181                state.root_control.into_bits() as u32
182                    | ((self.root_capabilities.into_bits() as u32) << 16)
183            }
184            PciExpressCapabilityHeader::ROOT_STS => {
185                // Root Status (4 bytes)
186                let state = self.state.lock();
187                state.root_status.into_bits()
188            }
189            PciExpressCapabilityHeader::DEVICE_CAPS_2 => self.device_capabilities_2.into_bits(),
190            PciExpressCapabilityHeader::DEVICE_CTL_STS_2 => {
191                // Device Control 2 (2 bytes) + Device Status 2 (2 bytes)
192                let state = self.state.lock();
193                state.device_control_2.into_bits() as u32
194                    | ((state.device_status_2.into_bits() as u32) << 16)
195            }
196            PciExpressCapabilityHeader::LINK_CAPS_2 => self.link_capabilities_2.into_bits(),
197            PciExpressCapabilityHeader::LINK_CTL_STS_2 => {
198                // Link Control 2 (2 bytes) + Link Status 2 (2 bytes)
199                let state = self.state.lock();
200                state.link_control_2.into_bits() as u32
201                    | ((state.link_status_2.into_bits() as u32) << 16)
202            }
203            PciExpressCapabilityHeader::SLOT_CAPS_2 => self.slot_capabilities_2.into_bits(),
204            PciExpressCapabilityHeader::SLOT_CTL_STS_2 => {
205                // Slot Control 2 (2 bytes) + Slot Status 2 (2 bytes)
206                let state = self.state.lock();
207                state.slot_control_2.into_bits() as u32
208                    | ((state.slot_status_2.into_bits() as u32) << 16)
209            }
210            _ => {
211                tracelimit::warn_ratelimited!(
212                    ?label,
213                    offset,
214                    "unhandled pci express capability read"
215                );
216                0
217            }
218        }
219    }
220
221    fn write_u32(&mut self, offset: u16, val: u32) {
222        let label = self.label();
223        match PciExpressCapabilityHeader(offset) {
224            PciExpressCapabilityHeader::PCIE_CAPS => {
225                // PCIe Capabilities register is read-only
226                tracelimit::warn_ratelimited!(
227                    ?label,
228                    offset,
229                    val,
230                    "write to read-only pcie capabilities"
231                );
232            }
233            PciExpressCapabilityHeader::DEVICE_CAPS => {
234                // Device Capabilities register is read-only
235                tracelimit::warn_ratelimited!(
236                    ?label,
237                    offset,
238                    val,
239                    "write to read-only device capabilities"
240                );
241            }
242            PciExpressCapabilityHeader::DEVICE_CTL_STS => {
243                // Lower 16 bits are Device Control (read-write)
244                // Upper 16 bits are Device Status (read-write, but some bits are read-only)
245                let new_control = pci_express::DeviceControl::from_bits(val as u16);
246                self.handle_device_control_write(new_control);
247
248                // Handle Device Status - most bits are write-1-to-clear
249                let new_status = pci_express::DeviceStatus::from_bits((val >> 16) as u16);
250                let mut state = self.state.lock();
251                let mut current_status = state.device_status;
252
253                // Clear bits that were written as 1 (write-1-to-clear semantics)
254                if new_status.correctable_error_detected() {
255                    current_status.set_correctable_error_detected(false);
256                }
257                if new_status.non_fatal_error_detected() {
258                    current_status.set_non_fatal_error_detected(false);
259                }
260                if new_status.fatal_error_detected() {
261                    current_status.set_fatal_error_detected(false);
262                }
263                if new_status.unsupported_request_detected() {
264                    current_status.set_unsupported_request_detected(false);
265                }
266
267                state.device_status = current_status;
268            }
269            PciExpressCapabilityHeader::LINK_CAPS => {
270                // Link Capabilities register is read-only
271                tracelimit::warn_ratelimited!(
272                    ?label,
273                    offset,
274                    val,
275                    "write to read-only link capabilities"
276                );
277            }
278            PciExpressCapabilityHeader::LINK_CTL_STS => {
279                // Link Control (2 bytes) + Link Status (2 bytes)
280                let mut state = self.state.lock();
281                state.link_control = pci_express::LinkControl::from_bits(val as u16);
282                // Link Status upper 16 bits - many bits are write-1-to-clear or read-only
283                // For simplicity, we'll treat it as read-only for now
284            }
285            PciExpressCapabilityHeader::SLOT_CAPS => {
286                // Slot Capabilities register is read-only
287                tracelimit::warn_ratelimited!(
288                    ?label,
289                    offset,
290                    val,
291                    "write to read-only slot capabilities"
292                );
293            }
294            PciExpressCapabilityHeader::SLOT_CTL_STS => {
295                // Slot Control (2 bytes) + Slot Status (2 bytes)
296                let mut state = self.state.lock();
297                state.slot_control = pci_express::SlotControl::from_bits(val as u16);
298                // Slot Status upper 16 bits - many bits are write-1-to-clear
299                // For simplicity, we'll allow basic writes for now
300                state.slot_status = pci_express::SlotStatus::from_bits((val >> 16) as u16);
301            }
302            PciExpressCapabilityHeader::ROOT_CTL_CAPS => {
303                // Root Control (2 bytes) + Root Capabilities (2 bytes)
304                let mut state = self.state.lock();
305                state.root_control = pci_express::RootControl::from_bits(val as u16);
306                // Root Capabilities upper 16 bits are read-only
307            }
308            PciExpressCapabilityHeader::ROOT_STS => {
309                // Root Status (4 bytes) - many bits are write-1-to-clear
310                let mut state = self.state.lock();
311                // For simplicity, we'll allow basic writes for now
312                state.root_status = pci_express::RootStatus::from_bits(val);
313            }
314            PciExpressCapabilityHeader::DEVICE_CAPS_2 => {
315                // Device Capabilities 2 register is read-only
316                tracelimit::warn_ratelimited!(
317                    ?label,
318                    offset,
319                    val,
320                    "write to read-only device capabilities 2"
321                );
322            }
323            PciExpressCapabilityHeader::DEVICE_CTL_STS_2 => {
324                // Device Control 2 (2 bytes) + Device Status 2 (2 bytes)
325                let mut state = self.state.lock();
326                state.device_control_2 = pci_express::DeviceControl2::from_bits(val as u16);
327                // Device Status 2 upper 16 bits - mostly read-only or write-1-to-clear
328                state.device_status_2 = pci_express::DeviceStatus2::from_bits((val >> 16) as u16);
329            }
330            PciExpressCapabilityHeader::LINK_CAPS_2 => {
331                // Link Capabilities 2 register is read-only
332                tracelimit::warn_ratelimited!(
333                    ?label,
334                    offset,
335                    val,
336                    "write to read-only link capabilities 2"
337                );
338            }
339            PciExpressCapabilityHeader::LINK_CTL_STS_2 => {
340                // Link Control 2 (2 bytes) + Link Status 2 (2 bytes)
341                let mut state = self.state.lock();
342                state.link_control_2 = pci_express::LinkControl2::from_bits(val as u16);
343                // Link Status 2 upper 16 bits - mostly read-only
344            }
345            PciExpressCapabilityHeader::SLOT_CAPS_2 => {
346                // Slot Capabilities 2 register is read-only
347                tracelimit::warn_ratelimited!(
348                    ?label,
349                    offset,
350                    val,
351                    "write to read-only slot capabilities 2"
352                );
353            }
354            PciExpressCapabilityHeader::SLOT_CTL_STS_2 => {
355                // Slot Control 2 (2 bytes) + Slot Status 2 (2 bytes)
356                let mut state = self.state.lock();
357                state.slot_control_2 = pci_express::SlotControl2::from_bits(val as u16);
358                // Slot Status 2 upper 16 bits - mostly read-only or write-1-to-clear
359                state.slot_status_2 = pci_express::SlotStatus2::from_bits((val >> 16) as u16);
360            }
361            _ => {
362                tracelimit::warn_ratelimited!(
363                    ?label,
364                    offset,
365                    val,
366                    "unhandled pci express capability write"
367                );
368            }
369        }
370    }
371
372    fn reset(&mut self) {
373        let mut state = self.state.lock();
374        *state = PciExpressState::new();
375    }
376}
377
378mod save_restore {
379    use super::*;
380    use vmcore::save_restore::RestoreError;
381    use vmcore::save_restore::SaveError;
382    use vmcore::save_restore::SaveRestore;
383
384    mod state {
385        use mesh::payload::Protobuf;
386        use vmcore::save_restore::SavedStateRoot;
387
388        #[derive(Protobuf, SavedStateRoot)]
389        #[mesh(package = "pci.capabilities.pci_express")]
390        pub struct SavedState {
391            #[mesh(1)]
392            pub device_control: u16,
393            #[mesh(2)]
394            pub device_status: u16,
395            #[mesh(3)]
396            pub flr_handler: u16,
397        }
398    }
399
400    impl SaveRestore for PciExpressCapability {
401        type SavedState = state::SavedState;
402
403        fn save(&mut self) -> Result<Self::SavedState, SaveError> {
404            Err(SaveError::NotSupported)
405        }
406
407        fn restore(&mut self, _: Self::SavedState) -> Result<(), RestoreError> {
408            Err(RestoreError::SavedStateNotSupported)
409        }
410    }
411}
412
413#[cfg(test)]
414mod tests {
415    use super::*;
416    use crate::spec::caps::pci_express::DevicePortType;
417    use std::sync::atomic::{AtomicBool, Ordering};
418
419    #[derive(Debug)]
420    struct TestFlrHandler {
421        flr_initiated: AtomicBool,
422    }
423
424    impl TestFlrHandler {
425        fn new() -> Arc<Self> {
426            Arc::new(Self {
427                flr_initiated: AtomicBool::new(false),
428            })
429        }
430
431        fn was_flr_initiated(&self) -> bool {
432            self.flr_initiated.load(Ordering::Acquire)
433        }
434
435        fn reset(&self) {
436            self.flr_initiated.store(false, Ordering::Release);
437        }
438    }
439
440    impl FlrHandler for TestFlrHandler {
441        fn initiate_flr(&self) {
442            self.flr_initiated.store(true, Ordering::Release);
443        }
444    }
445
446    impl Inspect for TestFlrHandler {
447        fn inspect(&self, req: inspect::Request<'_>) {
448            req.respond()
449                .field("flr_initiated", self.flr_initiated.load(Ordering::Acquire));
450        }
451    }
452
453    #[test]
454    fn test_pci_express_capability_read_u32_endpoint() {
455        let flr_handler = TestFlrHandler::new();
456        let cap = PciExpressCapability::new(DevicePortType::Endpoint, Some(flr_handler));
457
458        // Test PCIe Capabilities Register (offset 0x00)
459        let caps_val = cap.read_u32(0x00);
460        assert_eq!(caps_val & 0xFF, 0x10); // Capability ID = 0x10
461        assert_eq!((caps_val >> 8) & 0xFF, 0x00); // Next Pointer = 0x00
462        assert_eq!((caps_val >> 16) & 0xFFFF, 0x0002); // PCIe Caps: Version 2, Device/Port Type 0
463
464        // Test Device Capabilities Register (offset 0x04)
465        let device_caps_val = cap.read_u32(0x04);
466        assert_eq!(
467            device_caps_val & PCI_EXPRESS_DEVICE_CAPS_FLR_BIT_MASK,
468            PCI_EXPRESS_DEVICE_CAPS_FLR_BIT_MASK
469        ); // FLR bit should be set
470
471        // Test Device Control/Status Register (offset 0x08) - should be zero initially
472        let device_ctl_sts_val = cap.read_u32(0x08);
473        assert_eq!(device_ctl_sts_val, 0); // Both control and status should be 0
474
475        // Test unhandled offset - should return 0 and not panic
476        let unhandled_val = cap.read_u32(0x10);
477        assert_eq!(unhandled_val, 0);
478    }
479
480    #[test]
481    fn test_pci_express_capability_read_u32_root_port() {
482        let cap = PciExpressCapability::new(DevicePortType::RootPort, None);
483
484        // Test PCIe Capabilities Register (offset 0x00)
485        let caps_val = cap.read_u32(0x00);
486        assert_eq!(caps_val & 0xFF, 0x10); // Capability ID = 0x10
487        assert_eq!((caps_val >> 8) & 0xFF, 0x00); // Next Pointer = 0x00
488        assert_eq!((caps_val >> 16) & 0xFFFF, 0x0042); // PCIe Caps: Version 2, Device/Port Type 4
489    }
490
491    #[test]
492    fn test_pci_express_capability_read_u32_no_flr() {
493        let cap = PciExpressCapability::new(DevicePortType::Endpoint, None);
494
495        // Test Device Capabilities Register (offset 0x04) - FLR should not be set
496        let device_caps_val = cap.read_u32(0x04);
497        assert_eq!(device_caps_val & PCI_EXPRESS_DEVICE_CAPS_FLR_BIT_MASK, 0);
498    }
499
500    #[test]
501    fn test_pci_express_capability_write_u32_readonly_registers() {
502        let mut cap = PciExpressCapability::new(DevicePortType::Endpoint, None);
503
504        // Try to write to read-only PCIe Capabilities Register (offset 0x00)
505        let original_caps = cap.read_u32(0x00);
506        cap.write_u32(0x00, 0xFFFFFFFF);
507        assert_eq!(cap.read_u32(0x00), original_caps); // Should be unchanged
508
509        // Try to write to read-only Device Capabilities Register (offset 0x04)
510        let original_device_caps = cap.read_u32(0x04);
511        cap.write_u32(0x04, 0xFFFFFFFF);
512        assert_eq!(cap.read_u32(0x04), original_device_caps); // Should be unchanged
513    }
514
515    #[test]
516    fn test_pci_express_capability_write_u32_device_control() {
517        let flr_handler = TestFlrHandler::new();
518        let mut cap =
519            PciExpressCapability::new(DevicePortType::Endpoint, Some(flr_handler.clone()));
520
521        // Initial state should have FLR bit clear
522        let initial_ctl_sts = cap.read_u32(0x08);
523        assert_eq!(initial_ctl_sts & 0xFFFF, 0); // Device Control should be 0
524
525        // Test writing to Device Control Register (lower 16 bits of offset 0x08)
526        // Set some control bits but not FLR initially
527        cap.write_u32(0x08, 0x0001); // Enable correctable error reporting (bit 0)
528        let device_ctl_sts = cap.read_u32(0x08);
529        assert_eq!(device_ctl_sts & 0xFFFF, 0x0001); // Device Control should be set
530        assert!(!flr_handler.was_flr_initiated()); // FLR should not be triggered
531
532        // Test FLR initiation (bit 15 of Device Control)
533        flr_handler.reset();
534        cap.write_u32(0x08, 0x8001); // Set FLR bit (bit 15) and other control bits
535        let device_ctl_sts_after_flr = cap.read_u32(0x08);
536        assert_eq!(device_ctl_sts_after_flr & 0xFFFF, 0x0001); // FLR bit should be cleared, others remain
537        assert!(flr_handler.was_flr_initiated()); // FLR should be triggered
538
539        // Test that writing FLR bit when it's already been triggered behaves correctly
540        flr_handler.reset();
541        // After the previous FLR, device_control should have bit 0 set but FLR clear
542        // So writing 0x8000 (only FLR bit) should trigger FLR again
543        cap.write_u32(0x08, 0x8000); // Set FLR bit only
544        let device_ctl_sts_final = cap.read_u32(0x08);
545        assert_eq!(device_ctl_sts_final & 0xFFFF, 0x0000); // All bits should be cleared (FLR self-clears, bit 0 was overwritten)
546        assert!(flr_handler.was_flr_initiated()); // Should trigger because FLR transitioned from 0 to 1
547    }
548
549    #[test]
550    fn test_pci_express_capability_write_u32_device_status() {
551        let mut cap = PciExpressCapability::new(DevicePortType::Endpoint, None);
552
553        // Manually set some status bits to test write-1-to-clear behavior
554        {
555            let mut state = cap.state.lock();
556            state.device_status.set_correctable_error_detected(true);
557            state.device_status.set_non_fatal_error_detected(true);
558            state.device_status.set_fatal_error_detected(true);
559            state.device_status.set_unsupported_request_detected(true);
560        }
561
562        // Check that status bits are set
563        let device_ctl_sts = cap.read_u32(0x08);
564        let status_bits = (device_ctl_sts >> 16) & 0xFFFF;
565        assert_ne!(status_bits & 0x0F, 0); // Some status bits should be set
566
567        // Write 1 to clear correctable error bit (bit 0 of status)
568        cap.write_u32(0x08, 0x00010000); // Write 1 to bit 16 (correctable error in upper 16 bits)
569        let device_ctl_sts_after = cap.read_u32(0x08);
570        let status_bits_after = (device_ctl_sts_after >> 16) & 0xFFFF;
571        assert_eq!(status_bits_after & 0x01, 0); // Correctable error bit should be cleared
572        assert_ne!(status_bits_after & 0x0E, 0); // Other error bits should still be set
573
574        // Clear all remaining error bits
575        cap.write_u32(0x08, 0x000E0000); // Write 1 to bits 17-19 (other error bits)
576        let final_status = (cap.read_u32(0x08) >> 16) & 0xFFFF;
577        assert_eq!(final_status & 0x0F, 0); // All error bits should be cleared
578    }
579
580    #[test]
581    fn test_pci_express_capability_write_u32_unhandled_offset() {
582        let mut cap = PciExpressCapability::new(DevicePortType::Endpoint, None);
583
584        // Writing to unhandled offset should not panic
585        cap.write_u32(0x10, 0xFFFFFFFF);
586        // Should not crash and should not affect other registers
587        assert_eq!(cap.read_u32(0x08), 0); // Device Control/Status should still be 0
588    }
589
590    #[test]
591    fn test_pci_express_capability_reset() {
592        let flr_handler = TestFlrHandler::new();
593        let mut cap =
594            PciExpressCapability::new(DevicePortType::Endpoint, Some(flr_handler.clone()));
595
596        // Set some state
597        cap.write_u32(0x08, 0x0001); // Set some device control bits
598
599        // Manually set some status bits
600        {
601            let mut state = cap.state.lock();
602            state.device_status.set_correctable_error_detected(true);
603        }
604
605        // Verify state is set
606        let device_ctl_sts = cap.read_u32(0x08);
607        assert_ne!(device_ctl_sts, 0);
608
609        // Reset the capability
610        cap.reset();
611
612        // Verify state is cleared
613        let device_ctl_sts_after_reset = cap.read_u32(0x08);
614        assert_eq!(device_ctl_sts_after_reset, 0);
615    }
616
617    #[test]
618    fn test_pci_express_capability_extended_registers() {
619        let cap = PciExpressCapability::new(DevicePortType::Endpoint, None);
620
621        // Test that extended registers return 0 by default and don't crash
622        assert_eq!(cap.read_u32(0x0C), 0); // Link Capabilities
623        assert_eq!(cap.read_u32(0x10), 0); // Link Control/Status
624        assert_eq!(cap.read_u32(0x14), 0); // Slot Capabilities
625        assert_eq!(cap.read_u32(0x18), 0); // Slot Control/Status
626        assert_eq!(cap.read_u32(0x1C), 0); // Root Control/Capabilities
627        assert_eq!(cap.read_u32(0x20), 0); // Root Status
628        assert_eq!(cap.read_u32(0x24), 0); // Device Capabilities 2
629        assert_eq!(cap.read_u32(0x28), 0); // Device Control/Status 2
630        assert_eq!(cap.read_u32(0x2C), 0); // Link Capabilities 2
631        assert_eq!(cap.read_u32(0x30), 0); // Link Control/Status 2
632        assert_eq!(cap.read_u32(0x34), 0); // Slot Capabilities 2
633        assert_eq!(cap.read_u32(0x38), 0); // Slot Control/Status 2
634    }
635
636    #[test]
637    fn test_pci_express_capability_length() {
638        let cap = PciExpressCapability::new(DevicePortType::Endpoint, None);
639        assert_eq!(cap.len(), 0x3C); // Should be 60 bytes (0x3C)
640    }
641
642    #[test]
643    fn test_pci_express_capability_label() {
644        let cap = PciExpressCapability::new(DevicePortType::Endpoint, None);
645        assert_eq!(cap.label(), "pci-express");
646    }
647}