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