1use 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
14pub const PCI_EXPRESS_DEVICE_CAPS_FLR_BIT_MASK: u32 = 1 << 28;
16
17pub trait FlrHandler: Send + Sync + Inspect {
19 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}
28
29impl PciExpressState {
30 fn new() -> Self {
31 Self {
32 device_control: pci_express::DeviceControl::new(),
33 device_status: pci_express::DeviceStatus::new(),
34 }
35 }
36}
37
38#[derive(Inspect)]
39pub struct PciExpressCapability {
41 pcie_capabilites: pci_express::PciExpressCapabilities,
42 device_capabilities: pci_express::DeviceCapabilities,
43 state: Arc<Mutex<PciExpressState>>,
44 #[inspect(skip)]
45 flr_handler: Option<Arc<dyn FlrHandler>>,
46}
47
48impl PciExpressCapability {
49 pub fn new(typ: pci_express::DevicePortType, flr_handler: Option<Arc<dyn FlrHandler>>) -> Self {
55 Self {
56 pcie_capabilites: pci_express::PciExpressCapabilities::new()
57 .with_capability_version(2)
58 .with_device_port_type(typ),
59 device_capabilities: pci_express::DeviceCapabilities::new()
60 .with_function_level_reset(flr_handler.is_some()),
61 state: Arc::new(Mutex::new(PciExpressState::new())),
62 flr_handler,
63 }
64 }
65
66 fn handle_device_control_write(&mut self, new_control: pci_express::DeviceControl) {
67 let mut state = self.state.lock();
68
69 let old_flr = state.device_control.initiate_function_level_reset();
71 let new_flr = new_control.initiate_function_level_reset();
72
73 if new_flr && !old_flr {
77 if let Some(handler) = &self.flr_handler {
78 handler.initiate_flr();
79 }
80 }
81
82 state.device_control = new_control.with_initiate_function_level_reset(false);
84 }
85}
86
87impl PciCapability for PciExpressCapability {
88 fn label(&self) -> &str {
89 "pci-express"
90 }
91
92 fn len(&self) -> usize {
93 0x0C
99 }
100
101 fn read_u32(&self, offset: u16) -> u32 {
102 let label = self.label();
103 match PciExpressCapabilityHeader(offset) {
104 PciExpressCapabilityHeader::PCIE_CAPS => {
105 (self.pcie_capabilites.into_bits() as u32) << 16
107 | CapabilityId::PCI_EXPRESS.0 as u32
108 }
109 PciExpressCapabilityHeader::DEVICE_CAPS => self.device_capabilities.into_bits(),
110 PciExpressCapabilityHeader::DEVICE_CTL_STS => {
111 let state = self.state.lock();
112 let device_control = state.device_control.into_bits() as u32;
113 let device_status = state.device_status.into_bits() as u32;
114 device_control | (device_status << 16)
115 }
116 _ => {
117 tracelimit::warn_ratelimited!(
118 ?label,
119 offset,
120 "unhandled pci express capability read"
121 );
122 0
123 }
124 }
125 }
126
127 fn write_u32(&mut self, offset: u16, val: u32) {
128 let label = self.label();
129 match PciExpressCapabilityHeader(offset) {
130 PciExpressCapabilityHeader::PCIE_CAPS => {
131 tracelimit::warn_ratelimited!(
133 ?label,
134 offset,
135 val,
136 "write to read-only pcie capabilities"
137 );
138 }
139 PciExpressCapabilityHeader::DEVICE_CAPS => {
140 tracelimit::warn_ratelimited!(
142 ?label,
143 offset,
144 val,
145 "write to read-only device capabilities"
146 );
147 }
148 PciExpressCapabilityHeader::DEVICE_CTL_STS => {
149 let new_control = pci_express::DeviceControl::from_bits(val as u16);
152 self.handle_device_control_write(new_control);
153
154 let new_status = pci_express::DeviceStatus::from_bits((val >> 16) as u16);
156 let mut state = self.state.lock();
157 let mut current_status = state.device_status;
158
159 if new_status.correctable_error_detected() {
161 current_status.set_correctable_error_detected(false);
162 }
163 if new_status.non_fatal_error_detected() {
164 current_status.set_non_fatal_error_detected(false);
165 }
166 if new_status.fatal_error_detected() {
167 current_status.set_fatal_error_detected(false);
168 }
169 if new_status.unsupported_request_detected() {
170 current_status.set_unsupported_request_detected(false);
171 }
172
173 state.device_status = current_status;
174 }
175 _ => {
176 tracelimit::warn_ratelimited!(
177 ?label,
178 offset,
179 val,
180 "unhandled pci express capability write"
181 );
182 }
183 }
184 }
185
186 fn reset(&mut self) {
187 let mut state = self.state.lock();
188 *state = PciExpressState::new();
189 }
190}
191
192mod save_restore {
193 use super::*;
194 use vmcore::save_restore::RestoreError;
195 use vmcore::save_restore::SaveError;
196 use vmcore::save_restore::SaveRestore;
197
198 mod state {
199 use mesh::payload::Protobuf;
200 use vmcore::save_restore::SavedStateRoot;
201
202 #[derive(Protobuf, SavedStateRoot)]
203 #[mesh(package = "pci.capabilities.pci_express")]
204 pub struct SavedState {
205 #[mesh(1)]
206 pub device_control: u16,
207 #[mesh(2)]
208 pub device_status: u16,
209 #[mesh(3)]
210 pub flr_handler: u16,
211 }
212 }
213
214 impl SaveRestore for PciExpressCapability {
215 type SavedState = state::SavedState;
216
217 fn save(&mut self) -> Result<Self::SavedState, SaveError> {
218 Err(SaveError::NotSupported)
219 }
220
221 fn restore(&mut self, _: Self::SavedState) -> Result<(), RestoreError> {
222 Err(RestoreError::SavedStateNotSupported)
223 }
224 }
225}
226
227#[cfg(test)]
228mod tests {
229 use super::*;
230 use crate::spec::caps::pci_express::DevicePortType;
231 use std::sync::atomic::{AtomicBool, Ordering};
232
233 #[derive(Debug)]
234 struct TestFlrHandler {
235 flr_initiated: AtomicBool,
236 }
237
238 impl TestFlrHandler {
239 fn new() -> Arc<Self> {
240 Arc::new(Self {
241 flr_initiated: AtomicBool::new(false),
242 })
243 }
244
245 fn was_flr_initiated(&self) -> bool {
246 self.flr_initiated.load(Ordering::Acquire)
247 }
248
249 fn reset(&self) {
250 self.flr_initiated.store(false, Ordering::Release);
251 }
252 }
253
254 impl FlrHandler for TestFlrHandler {
255 fn initiate_flr(&self) {
256 self.flr_initiated.store(true, Ordering::Release);
257 }
258 }
259
260 impl Inspect for TestFlrHandler {
261 fn inspect(&self, req: inspect::Request<'_>) {
262 req.respond()
263 .field("flr_initiated", self.flr_initiated.load(Ordering::Acquire));
264 }
265 }
266
267 #[test]
268 fn test_pci_express_capability_read_u32_endpoint() {
269 let flr_handler = TestFlrHandler::new();
270 let cap = PciExpressCapability::new(DevicePortType::Endpoint, Some(flr_handler));
271
272 let caps_val = cap.read_u32(0x00);
274 assert_eq!(caps_val & 0xFF, 0x10); assert_eq!((caps_val >> 8) & 0xFF, 0x00); assert_eq!((caps_val >> 16) & 0xFFFF, 0x0002); let device_caps_val = cap.read_u32(0x04);
280 assert_eq!(
281 device_caps_val & PCI_EXPRESS_DEVICE_CAPS_FLR_BIT_MASK,
282 PCI_EXPRESS_DEVICE_CAPS_FLR_BIT_MASK
283 ); let device_ctl_sts_val = cap.read_u32(0x08);
287 assert_eq!(device_ctl_sts_val, 0); let unhandled_val = cap.read_u32(0x10);
291 assert_eq!(unhandled_val, 0);
292 }
293
294 #[test]
295 fn test_pci_express_capability_read_u32_root_port() {
296 let cap = PciExpressCapability::new(DevicePortType::RootPort, None);
297
298 let caps_val = cap.read_u32(0x00);
300 assert_eq!(caps_val & 0xFF, 0x10); assert_eq!((caps_val >> 8) & 0xFF, 0x00); assert_eq!((caps_val >> 16) & 0xFFFF, 0x0042); }
304
305 #[test]
306 fn test_pci_express_capability_read_u32_no_flr() {
307 let cap = PciExpressCapability::new(DevicePortType::Endpoint, None);
308
309 let device_caps_val = cap.read_u32(0x04);
311 assert_eq!(device_caps_val & PCI_EXPRESS_DEVICE_CAPS_FLR_BIT_MASK, 0);
312 }
313
314 #[test]
315 fn test_pci_express_capability_write_u32_readonly_registers() {
316 let mut cap = PciExpressCapability::new(DevicePortType::Endpoint, None);
317
318 let original_caps = cap.read_u32(0x00);
320 cap.write_u32(0x00, 0xFFFFFFFF);
321 assert_eq!(cap.read_u32(0x00), original_caps); let original_device_caps = cap.read_u32(0x04);
325 cap.write_u32(0x04, 0xFFFFFFFF);
326 assert_eq!(cap.read_u32(0x04), original_device_caps); }
328
329 #[test]
330 fn test_pci_express_capability_write_u32_device_control() {
331 let flr_handler = TestFlrHandler::new();
332 let mut cap =
333 PciExpressCapability::new(DevicePortType::Endpoint, Some(flr_handler.clone()));
334
335 let initial_ctl_sts = cap.read_u32(0x08);
337 assert_eq!(initial_ctl_sts & 0xFFFF, 0); cap.write_u32(0x08, 0x0001); let device_ctl_sts = cap.read_u32(0x08);
343 assert_eq!(device_ctl_sts & 0xFFFF, 0x0001); assert!(!flr_handler.was_flr_initiated()); flr_handler.reset();
348 cap.write_u32(0x08, 0x8001); let device_ctl_sts_after_flr = cap.read_u32(0x08);
350 assert_eq!(device_ctl_sts_after_flr & 0xFFFF, 0x0001); assert!(flr_handler.was_flr_initiated()); flr_handler.reset();
355 cap.write_u32(0x08, 0x8000); let device_ctl_sts_final = cap.read_u32(0x08);
359 assert_eq!(device_ctl_sts_final & 0xFFFF, 0x0000); assert!(flr_handler.was_flr_initiated()); }
362
363 #[test]
364 fn test_pci_express_capability_write_u32_device_status() {
365 let mut cap = PciExpressCapability::new(DevicePortType::Endpoint, None);
366
367 {
369 let mut state = cap.state.lock();
370 state.device_status.set_correctable_error_detected(true);
371 state.device_status.set_non_fatal_error_detected(true);
372 state.device_status.set_fatal_error_detected(true);
373 state.device_status.set_unsupported_request_detected(true);
374 }
375
376 let device_ctl_sts = cap.read_u32(0x08);
378 let status_bits = (device_ctl_sts >> 16) & 0xFFFF;
379 assert_ne!(status_bits & 0x0F, 0); cap.write_u32(0x08, 0x00010000); let device_ctl_sts_after = cap.read_u32(0x08);
384 let status_bits_after = (device_ctl_sts_after >> 16) & 0xFFFF;
385 assert_eq!(status_bits_after & 0x01, 0); assert_ne!(status_bits_after & 0x0E, 0); cap.write_u32(0x08, 0x000E0000); let final_status = (cap.read_u32(0x08) >> 16) & 0xFFFF;
391 assert_eq!(final_status & 0x0F, 0); }
393
394 #[test]
395 fn test_pci_express_capability_write_u32_unhandled_offset() {
396 let mut cap = PciExpressCapability::new(DevicePortType::Endpoint, None);
397
398 cap.write_u32(0x10, 0xFFFFFFFF);
400 assert_eq!(cap.read_u32(0x08), 0); }
403
404 #[test]
405 fn test_pci_express_capability_reset() {
406 let flr_handler = TestFlrHandler::new();
407 let mut cap =
408 PciExpressCapability::new(DevicePortType::Endpoint, Some(flr_handler.clone()));
409
410 cap.write_u32(0x08, 0x0001); {
415 let mut state = cap.state.lock();
416 state.device_status.set_correctable_error_detected(true);
417 }
418
419 let device_ctl_sts = cap.read_u32(0x08);
421 assert_ne!(device_ctl_sts, 0);
422
423 cap.reset();
425
426 let device_ctl_sts_after_reset = cap.read_u32(0x08);
428 assert_eq!(device_ctl_sts_after_reset, 0);
429 }
430
431 #[test]
432 fn test_pci_express_capability_length() {
433 let cap = PciExpressCapability::new(DevicePortType::Endpoint, None);
434 assert_eq!(cap.len(), 0x0C); }
436
437 #[test]
438 fn test_pci_express_capability_label() {
439 let cap = PciExpressCapability::new(DevicePortType::Endpoint, None);
440 assert_eq!(cap.label(), "pci-express");
441 }
442}