1#![cfg_attr(windows, allow(dead_code))]
6
7use base::error;
8use base::AsRawDescriptor;
9use base::Event;
10use base::RawDescriptor;
11use base::Tube;
12use bit_field::*;
13use vm_control::VmIrqRequest;
14use vm_control::VmIrqResponse;
15use zerocopy::FromBytes;
16use zerocopy::Immutable;
17use zerocopy::IntoBytes;
18use zerocopy::KnownLayout;
19
20use crate::pci::pci_configuration::PciCapConfig;
21use crate::pci::pci_configuration::PciCapConfigWriteResult;
22use crate::pci::PciCapability;
23use crate::pci::PciCapabilityID;
24
25pub const PCI_MSI_NEXT_POINTER: u32 = 0x1; pub const PCI_MSI_FLAGS: u32 = 0x2; const PCI_MSI_FLAGS_ENABLE: u16 = 0x0001; pub const PCI_MSI_FLAGS_64BIT: u16 = 0x0080; pub const PCI_MSI_FLAGS_MASKBIT: u16 = 0x0100; const PCI_MSI_ADDRESS_LO: u32 = 0x4; const PCI_MSI_ADDRESS_HI: u32 = 0x8; const PCI_MSI_DATA_32: u32 = 0x8; const PCI_MSI_DATA_64: u32 = 0xC; const MSI_LENGTH_32BIT_WITHOUT_MASK: u32 = 0xA;
38const MSI_LENGTH_32BIT_WITH_MASK: u32 = 0x14;
39const MSI_LENGTH_64BIT_WITHOUT_MASK: u32 = 0xE;
40const MSI_LENGTH_64BIT_WITH_MASK: u32 = 0x18;
41
42pub enum MsiStatus {
43 Enabled,
44 Disabled,
45 NothingToDo,
46}
47
48pub struct MsiConfig {
50 is_64bit: bool,
51 mask_cap: bool,
52 ctrl: u16,
53 address: u64,
54 data: u16,
55 vm_socket_irq: Tube,
56 irqfd: Option<Event>,
57 gsi: Option<u32>,
58 device_id: u32,
59 device_name: String,
60 pci_address: Option<resources::PciAddress>,
61}
62
63impl MsiConfig {
64 pub fn new(
65 is_64bit: bool,
66 mask_cap: bool,
67 vm_socket_irq: Tube,
68 device_id: u32,
69 device_name: String,
70 ) -> Self {
71 let mut ctrl: u16 = 0;
72 if is_64bit {
73 ctrl |= PCI_MSI_FLAGS_64BIT;
74 }
75 if mask_cap {
76 ctrl |= PCI_MSI_FLAGS_MASKBIT;
77 }
78 MsiConfig {
79 is_64bit,
80 mask_cap,
81 ctrl,
82 address: 0,
83 data: 0,
84 vm_socket_irq,
85 irqfd: None,
86 gsi: None,
87 device_id,
88 device_name,
89 pci_address: None,
90 }
91 }
92
93 pub fn set_pci_address(&mut self, pci_address: resources::PciAddress) {
95 self.pci_address = Some(pci_address);
96 }
97
98 fn len(&self) -> u32 {
99 match (self.is_64bit, self.mask_cap) {
100 (true, true) => MSI_LENGTH_64BIT_WITH_MASK,
101 (true, false) => MSI_LENGTH_64BIT_WITHOUT_MASK,
102 (false, true) => MSI_LENGTH_32BIT_WITH_MASK,
103 (false, false) => MSI_LENGTH_32BIT_WITHOUT_MASK,
104 }
105 }
106
107 pub fn is_msi_reg(&self, offset: u32, index: u64, len: usize) -> bool {
108 let msi_len = self.len();
109 index >= offset as u64
110 && index + len as u64 <= (offset + msi_len) as u64
111 && len as u32 <= msi_len
112 }
113
114 pub fn read_msi_capability(&self, offset: u32, data: u32) -> u32 {
115 if offset == 0 {
116 (self.ctrl as u32) << 16 | (data & u16::MAX as u32)
117 } else {
118 data
119 }
120 }
121
122 pub fn write_msi_capability(&mut self, offset: u32, data: &[u8]) -> MsiStatus {
123 let len = data.len();
124 let mut ret = MsiStatus::NothingToDo;
125 let old_address = self.address;
126 let old_data = self.data;
127
128 if len == 2 && offset == PCI_MSI_FLAGS {
130 let was_enabled = self.is_msi_enabled();
131 let value: [u8; 2] = [data[0], data[1]];
132 self.ctrl = u16::from_le_bytes(value);
133 let is_enabled = self.is_msi_enabled();
134 if !was_enabled && is_enabled {
135 self.enable();
136 ret = MsiStatus::Enabled;
137 } else if was_enabled && !is_enabled {
138 ret = MsiStatus::Disabled;
139 }
140 } else if len == 4 && offset == PCI_MSI_ADDRESS_LO && !self.is_64bit {
141 let value: [u8; 8] = [data[0], data[1], data[2], data[3], 0, 0, 0, 0];
143 self.address = u64::from_le_bytes(value);
144 } else if len == 4 && offset == PCI_MSI_ADDRESS_LO && self.is_64bit {
145 let value: [u8; 8] = [data[0], data[1], data[2], data[3], 0, 0, 0, 0];
147 self.address &= !0xffffffff;
148 self.address |= u64::from_le_bytes(value);
149 } else if len == 4 && offset == PCI_MSI_ADDRESS_HI && self.is_64bit {
150 let value: [u8; 8] = [0, 0, 0, 0, data[0], data[1], data[2], data[3]];
152 self.address &= 0xffffffff;
153 self.address |= u64::from_le_bytes(value);
154 } else if len == 8 && offset == PCI_MSI_ADDRESS_LO && self.is_64bit {
155 let value: [u8; 8] = [
157 data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7],
158 ];
159 self.address = u64::from_le_bytes(value);
160 } else if len == 2
161 && ((offset == PCI_MSI_DATA_32 && !self.is_64bit)
162 || (offset == PCI_MSI_DATA_64 && self.is_64bit))
163 {
164 let value: [u8; 2] = [data[0], data[1]];
166 self.data = u16::from_le_bytes(value);
167 }
168
169 if self.is_msi_enabled() && (old_address != self.address || old_data != self.data) {
170 self.add_msi_route();
171 }
172
173 ret
174 }
175
176 pub fn is_msi_enabled(&self) -> bool {
177 self.ctrl & PCI_MSI_FLAGS_ENABLE == PCI_MSI_FLAGS_ENABLE
178 }
179
180 fn add_msi_route(&self) {
181 let gsi = match self.gsi {
182 Some(g) => g,
183 None => {
184 error!("Add msi route but gsi is none");
185 return;
186 }
187 };
188 #[allow(unused_variables)]
191 let pci_address = self
192 .pci_address
193 .expect("MsixConfig: must call set_pci_address before config writes");
194 if let Err(e) = self.vm_socket_irq.send(&VmIrqRequest::AddMsiRoute {
195 gsi,
196 msi_address: self.address,
197 msi_data: self.data.into(),
198 #[cfg(target_arch = "aarch64")]
199 pci_address,
200 }) {
201 error!("failed to send AddMsiRoute request at {:?}", e);
202 return;
203 }
204 match self.vm_socket_irq.recv() {
205 Ok(VmIrqResponse::Err(e)) => error!("failed to call AddMsiRoute request {:?}", e),
206 Ok(_) => {}
207 Err(e) => error!("failed to receive AddMsiRoute response {:?}", e),
208 }
209 }
210
211 fn allocate_one_msi(&mut self) {
212 let irqfd = match self.irqfd.take() {
213 Some(e) => e,
214 None => match Event::new() {
215 Ok(e) => e,
216 Err(e) => {
217 error!("failed to create event: {:?}", e);
218 return;
219 }
220 },
221 };
222
223 let request = VmIrqRequest::AllocateOneMsi {
224 irqfd,
225 device_id: self.device_id,
226 queue_id: 0,
227 device_name: self.device_name.clone(),
228 };
229 let request_result = self.vm_socket_irq.send(&request);
230
231 self.irqfd = match request {
233 VmIrqRequest::AllocateOneMsi { irqfd, .. } => Some(irqfd),
234 _ => unreachable!(),
235 };
236
237 if let Err(e) = request_result {
238 error!("failed to send AllocateOneMsi request: {:?}", e);
239 return;
240 }
241
242 match self.vm_socket_irq.recv() {
243 Ok(VmIrqResponse::AllocateOneMsi { gsi }) => self.gsi = Some(gsi),
244 _ => error!("failed to receive AllocateOneMsi Response"),
245 }
246 }
247
248 fn enable(&mut self) {
249 if self.gsi.is_none() || self.irqfd.is_none() {
250 self.allocate_one_msi();
251 }
252
253 self.add_msi_route();
254 }
255
256 pub fn get_irqfd(&self) -> Option<&Event> {
257 self.irqfd.as_ref()
258 }
259
260 pub fn destroy(&mut self) {
261 if let Some(gsi) = self.gsi {
262 if let Some(irqfd) = self.irqfd.take() {
263 let request = VmIrqRequest::ReleaseOneIrq { gsi, irqfd };
264 if self.vm_socket_irq.send(&request).is_ok() {
265 let _ = self.vm_socket_irq.recv::<VmIrqResponse>();
266 }
267 }
268 }
269 }
270
271 pub fn get_msi_socket(&self) -> RawDescriptor {
273 self.vm_socket_irq.as_raw_descriptor()
274 }
275
276 pub fn trigger(&self) {
277 if let Some(irqfd) = self.irqfd.as_ref() {
278 irqfd.signal().unwrap();
279 }
280 }
281}
282
283#[bitfield]
284#[derive(Copy, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)]
285pub struct MsiCtrl {
286 enable: B1,
287 multi_msg_capable: B3,
288 multi_msg_enable: B3,
289 is_64bit: B1,
290 per_vector_masking: B1,
291 extended_msg_data_capable: B1,
292 extended_msg_data_enable: B1,
293 reserved: B5,
294}
295
296#[allow(dead_code)]
297#[repr(C)]
298#[derive(Clone, Copy, FromBytes, Immutable, IntoBytes, KnownLayout)]
299pub struct MsiCap {
301 _cap_vndr: u8,
303 _cap_next: u8,
304 msg_ctl: MsiCtrl,
306 msg_addr: u32,
308 msi_vary: [u8; 16],
310}
311
312impl PciCapability for MsiCap {
313 fn bytes(&self) -> &[u8] {
314 self.as_bytes()
315 }
316
317 fn id(&self) -> PciCapabilityID {
318 PciCapabilityID::MessageSignalledInterrupts
319 }
320
321 fn writable_bits(&self) -> Vec<u32> {
322 match (
324 self.msg_ctl.get_is_64bit(),
325 self.msg_ctl.get_per_vector_masking(),
326 ) {
327 (0, 0) => vec![0x0471_0000, 0xffff_fffc, 0xffff_ffff],
328 (0, 1) => vec![0x0471_0000, 0xffff_fffc, 0xffff_ffff, 0xffff_ffff],
329 (1, 0) => vec![
330 0x0471_0000,
331 0xffff_fffc,
332 0xffff_ffff,
333 0xffff_ffff,
334 0x0000_0000,
335 ],
336 (1, 1) => vec![
337 0x0471_0000,
338 0xffff_fffc,
339 0xffff_ffff,
340 0xffff_ffff,
341 0xffff_ffff,
342 0x0000_0000,
343 ],
344 (_, _) => Vec::new(),
345 }
346 }
347}
348
349impl MsiCap {
350 pub fn new(is_64bit: bool, mask_cap: bool) -> Self {
351 let mut msg_ctl = MsiCtrl::new();
352 if is_64bit {
353 msg_ctl.set_is_64bit(1);
354 }
355 if mask_cap {
356 msg_ctl.set_per_vector_masking(1);
357 }
358 MsiCap {
359 _cap_vndr: 0,
360 _cap_next: 0,
361 msg_ctl,
362 msg_addr: 0,
363 msi_vary: [0; 16],
364 }
365 }
366}
367
368const MSI_CONFIG_READ_MASK: [u32; MSI_LENGTH_64BIT_WITH_MASK as usize / 4] =
369 [0xffff_0000, 0, 0, 0, 0, 0];
370
371impl PciCapConfig for MsiConfig {
372 fn read_mask(&self) -> &'static [u32] {
373 let num_regs = self.len().div_ceil(4);
374 &MSI_CONFIG_READ_MASK[0..(num_regs as usize)]
375 }
376
377 fn read_reg(&self, reg_idx: usize) -> u32 {
378 self.read_msi_capability(reg_idx as u32 * 4, 0)
379 }
380
381 fn write_reg(
382 &mut self,
383 reg_idx: usize,
384 offset: u64,
385 data: &[u8],
386 ) -> Option<Box<dyn PciCapConfigWriteResult>> {
387 let offset = reg_idx as u32 * 4 + offset as u32;
388 self.write_msi_capability(offset, data);
389 None
390 }
391}