pci_core/
msi.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! Traits for working with MSI interrupts.
5
6use parking_lot::Mutex;
7use std::sync::Arc;
8use std::sync::Weak;
9use vmcore::interrupt::Interrupt;
10
11/// Trait implemented by targets capable of receiving MSI interrupts.
12pub trait MsiInterruptTarget: Send + Sync {
13    /// Creates a new interrupt object.
14    fn new_interrupt(&self) -> Box<dyn MsiControl>;
15}
16
17/// Trait modelling an individual MSI interrupt.
18pub trait MsiControl: Send {
19    /// Enables the interrupt, so that signaling the interrupt delivers an MSI
20    /// to the specified address/data pair.
21    fn enable(&mut self, address: u64, data: u32);
22
23    /// Disables the interrupt, allowing the backing object to release resources
24    /// associated with this MSI.
25    fn disable(&mut self);
26
27    /// Signals the interrupt.
28    ///
29    /// The caller must ensure that the interrupt is enabled with the same
30    /// address/data pair before calling this method. The address/data is
31    /// provided here redundantly for the convenience of the implementation.
32    fn signal(&mut self, address: u64, data: u32);
33
34    // FUTURE: add mechanisms to use an OS event object for signal. This is
35    // necessary to support sending interrupts across processes.
36    //
37    // This is complicated by differing requirements for the different backends,
38    // e.g. KVM supports taking whatever eventfd you want, while WHP wants to be
39    // the one to provide the event object.
40}
41
42impl<T: Send + FnMut(u64, u32)> MsiControl for T {
43    fn enable(&mut self, _address: u64, _data: u32) {}
44
45    fn disable(&mut self) {}
46
47    fn signal(&mut self, address: u64, data: u32) {
48        (*self)(address, data)
49    }
50}
51
52/// A set of message-signaled interrupts that have yet to be connected to a
53/// backing interrupt controller.
54pub struct MsiInterruptSet {
55    interrupts: Vec<Weak<Mutex<MsiInterruptState>>>,
56}
57
58impl MsiInterruptSet {
59    /// Creates a new empty set of message signaled interrupts.
60    pub fn new() -> Self {
61        Self {
62            interrupts: Vec::new(),
63        }
64    }
65
66    /// Returns the number of interrupts in the set.
67    pub fn len(&self) -> usize {
68        self.interrupts.len()
69    }
70
71    /// Connects the interrupts created with `builder()` to the given target
72    /// interrupt controller.
73    pub fn connect(self, target: &dyn MsiInterruptTarget) {
74        for interrupt in self.interrupts.into_iter().filter_map(|i| i.upgrade()) {
75            let mut control = target.new_interrupt();
76            let mut state = interrupt.lock();
77            if let Some((address, data)) = state.address_data {
78                control.enable(address, data);
79                if state.pending {
80                    control.signal(address, data);
81                    state.pending = false;
82                }
83            }
84            state.control = Some(control);
85        }
86    }
87}
88
89/// Trait for registering message-signaled interrupts for a device.
90pub trait RegisterMsi: Send {
91    /// Returns a new message-signaled interrupt for this device.
92    fn new_msi(&mut self) -> MsiInterrupt;
93}
94
95impl RegisterMsi for MsiInterruptSet {
96    fn new_msi(&mut self) -> MsiInterrupt {
97        let state = Arc::new(Mutex::new(MsiInterruptState {
98            pending: false,
99            address_data: None,
100            control: None,
101        }));
102        self.interrupts.push(Arc::downgrade(&state));
103        MsiInterrupt { state }
104    }
105}
106
107/// A message-signaled interrupt.
108pub struct MsiInterrupt {
109    state: Arc<Mutex<MsiInterruptState>>,
110}
111
112struct MsiInterruptState {
113    pending: bool,
114    address_data: Option<(u64, u32)>,
115    control: Option<Box<dyn MsiControl>>,
116}
117
118impl MsiInterrupt {
119    /// Enables the interrupt.
120    ///
121    /// If `set_pending`, or if the internal pending state is set, then delivers
122    /// the interrupt immediately.
123    pub fn enable(&mut self, address: u64, data: u32, set_pending: bool) {
124        let mut state = self.state.lock();
125        let state = &mut *state;
126        state.pending |= set_pending;
127        state.address_data = Some((address, data));
128        if let Some(control) = &mut state.control {
129            control.enable(address, data);
130            if state.pending {
131                control.signal(address, data);
132                state.pending = false;
133            }
134        }
135    }
136
137    /// Disables the interrupt.
138    ///
139    /// Interrupt deliveries while the interrupt is disabled will set an
140    /// internal pending state.
141    pub fn disable(&mut self) {
142        let mut state = self.state.lock();
143        state.address_data = None;
144        if let Some(control) = &mut state.control {
145            control.disable();
146        }
147    }
148
149    /// Clears any internal pending state and returns it.
150    pub fn drain_pending(&mut self) -> bool {
151        let mut state = self.state.lock();
152        std::mem::take(&mut state.pending)
153    }
154
155    /// Returns an object that can be used to deliver the interrupt.
156    pub fn interrupt(&mut self) -> Interrupt {
157        let state = self.state.clone();
158        Interrupt::from_fn(move || {
159            let mut state = state.lock();
160            let state = &mut *state;
161            if let Some((control, (address, data))) = state.control.as_mut().zip(state.address_data)
162            {
163                control.signal(address, data);
164            } else {
165                state.pending = true;
166            }
167        })
168    }
169}