pci_core/test_helpers/
mod.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! Mock types for unit-testing various PCI behaviors.
5
6use crate::msi::SignalMsi;
7use parking_lot::Mutex;
8use std::collections::VecDeque;
9use std::sync::Arc;
10
11/// A test-only interrupt controller that simply stashes incoming interrupt
12/// requests in a FIFO queue. Implements [`SignalMsi`].
13#[derive(Debug, Clone)]
14pub struct TestPciInterruptController {
15    inner: Arc<TestPciInterruptControllerInner>,
16}
17
18#[derive(Debug)]
19struct TestPciInterruptControllerInner {
20    // TODO: also support INTx interrupts
21    msi_requests: Mutex<VecDeque<(u64, u32)>>, // (addr, data)
22}
23
24impl TestPciInterruptController {
25    /// Return a new test PCI interrupt controller
26    pub fn new() -> Self {
27        Self {
28            inner: Arc::new(TestPciInterruptControllerInner {
29                msi_requests: Mutex::new(VecDeque::new()),
30            }),
31        }
32    }
33
34    /// Fetch the first (addr, data) MSI-X interrupt in the FIFO interrupt queue
35    pub fn get_next_interrupt(&self) -> Option<(u64, u32)> {
36        self.inner.msi_requests.lock().pop_front()
37    }
38
39    /// Returns an `Arc<dyn SignalMsi>` to this controller.
40    pub fn signal_msi(&self) -> Arc<dyn SignalMsi> {
41        self.inner.clone()
42    }
43}
44
45impl SignalMsi for TestPciInterruptControllerInner {
46    fn signal_msi(&self, rid: u32, address: u64, data: u32) {
47        assert_eq!(rid, 0);
48        self.msi_requests.lock().push_back((address, data));
49    }
50}