1use inspect::Inspect;
7use parking_lot::Mutex;
8use std::sync::Arc;
9use std::sync::Weak;
10use vmcore::interrupt::Interrupt;
11
12pub trait MsiInterruptTarget: Send + Sync {
14 fn new_interrupt(&self) -> Box<dyn MsiControl>;
16}
17
18pub trait MsiControl: Send {
20 fn enable(&mut self, address: u64, data: u32);
23
24 fn disable(&mut self);
27
28 fn signal(&mut self, address: u64, data: u32);
34
35 }
42
43impl<T: Send + FnMut(u64, u32)> MsiControl for T {
44 fn enable(&mut self, _address: u64, _data: u32) {}
45
46 fn disable(&mut self) {}
47
48 fn signal(&mut self, address: u64, data: u32) {
49 (*self)(address, data)
50 }
51}
52
53pub struct MsiInterruptSet {
56 interrupts: Vec<Weak<Mutex<MsiInterruptState>>>,
57}
58
59impl MsiInterruptSet {
60 pub fn new() -> Self {
62 Self {
63 interrupts: Vec::new(),
64 }
65 }
66
67 pub fn len(&self) -> usize {
69 self.interrupts.len()
70 }
71
72 pub fn connect(self, target: &dyn MsiInterruptTarget) {
75 for interrupt in self.interrupts.into_iter().filter_map(|i| i.upgrade()) {
76 let mut control = target.new_interrupt();
77 let mut state = interrupt.lock();
78 if let Some((address, data)) = state.address_data {
79 control.enable(address, data);
80 if state.pending {
81 control.signal(address, data);
82 state.pending = false;
83 }
84 }
85 state.control = Some(control);
86 }
87 }
88}
89
90pub trait RegisterMsi: Send {
92 fn new_msi(&mut self) -> MsiInterrupt;
94}
95
96impl RegisterMsi for MsiInterruptSet {
97 fn new_msi(&mut self) -> MsiInterrupt {
98 let state = Arc::new(Mutex::new(MsiInterruptState {
99 pending: false,
100 address_data: None,
101 control: None,
102 }));
103 self.interrupts.push(Arc::downgrade(&state));
104 MsiInterrupt { state }
105 }
106}
107
108#[derive(Debug, Inspect)]
110pub struct MsiInterrupt {
111 state: Arc<Mutex<MsiInterruptState>>,
112}
113
114#[derive(Inspect)]
115struct MsiInterruptState {
116 pending: bool,
117 #[inspect(with = "inspect_address_data")]
118 address_data: Option<(u64, u32)>,
119 #[inspect(skip)]
120 control: Option<Box<dyn MsiControl>>,
121}
122
123fn inspect_address_data(address_data: &Option<(u64, u32)>) -> String {
124 match address_data {
125 Some((address, data)) => format!("address: {:#x}, data: {:#x}", address, data),
126 None => "None".to_string(),
127 }
128}
129
130impl std::fmt::Debug for MsiInterruptState {
131 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
132 f.debug_struct("MsiInterruptState")
133 .field("pending", &self.pending)
134 .field("address_data", &self.address_data)
135 .field("control", &"<MsiControl>")
136 .finish()
137 }
138}
139
140impl MsiInterrupt {
141 pub fn enable(&mut self, address: u64, data: u32, set_pending: bool) {
146 let mut state = self.state.lock();
147 let state = &mut *state;
148 state.pending |= set_pending;
149 state.address_data = Some((address, data));
150 if let Some(control) = &mut state.control {
151 control.enable(address, data);
152 if state.pending {
153 control.signal(address, data);
154 state.pending = false;
155 }
156 }
157 }
158
159 pub fn disable(&mut self) {
164 let mut state = self.state.lock();
165 state.address_data = None;
166 if let Some(control) = &mut state.control {
167 control.disable();
168 }
169 }
170
171 pub fn drain_pending(&mut self) -> bool {
173 let mut state = self.state.lock();
174 std::mem::take(&mut state.pending)
175 }
176
177 pub fn interrupt(&mut self) -> Interrupt {
179 let state = self.state.clone();
180 Interrupt::from_fn(move || {
181 let mut state = state.lock();
182 let state = &mut *state;
183 if let Some((control, (address, data))) = state.control.as_mut().zip(state.address_data)
184 {
185 control.signal(address, data);
186 } else {
187 state.pending = true;
188 }
189 })
190 }
191}