xref: /aosp_15_r20/external/crosvm/devices/src/pci/msi.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2022 The ChromiumOS Authors
2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file.
4*bb4ee6a4SAndroid Build Coastguard Worker 
5*bb4ee6a4SAndroid Build Coastguard Worker #![cfg_attr(windows, allow(dead_code))]
6*bb4ee6a4SAndroid Build Coastguard Worker 
7*bb4ee6a4SAndroid Build Coastguard Worker use base::error;
8*bb4ee6a4SAndroid Build Coastguard Worker use base::AsRawDescriptor;
9*bb4ee6a4SAndroid Build Coastguard Worker use base::Event;
10*bb4ee6a4SAndroid Build Coastguard Worker use base::RawDescriptor;
11*bb4ee6a4SAndroid Build Coastguard Worker use base::Tube;
12*bb4ee6a4SAndroid Build Coastguard Worker use bit_field::*;
13*bb4ee6a4SAndroid Build Coastguard Worker use vm_control::VmIrqRequest;
14*bb4ee6a4SAndroid Build Coastguard Worker use vm_control::VmIrqResponse;
15*bb4ee6a4SAndroid Build Coastguard Worker use zerocopy::AsBytes;
16*bb4ee6a4SAndroid Build Coastguard Worker use zerocopy::FromBytes;
17*bb4ee6a4SAndroid Build Coastguard Worker use zerocopy::FromZeroes;
18*bb4ee6a4SAndroid Build Coastguard Worker 
19*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::pci_configuration::PciCapConfig;
20*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::pci_configuration::PciCapConfigWriteResult;
21*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::PciCapability;
22*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::PciCapabilityID;
23*bb4ee6a4SAndroid Build Coastguard Worker 
24*bb4ee6a4SAndroid Build Coastguard Worker // MSI registers
25*bb4ee6a4SAndroid Build Coastguard Worker pub const PCI_MSI_NEXT_POINTER: u32 = 0x1; // Next cap pointer
26*bb4ee6a4SAndroid Build Coastguard Worker pub const PCI_MSI_FLAGS: u32 = 0x2; // Message Control
27*bb4ee6a4SAndroid Build Coastguard Worker const PCI_MSI_FLAGS_ENABLE: u16 = 0x0001; // MSI feature enabled
28*bb4ee6a4SAndroid Build Coastguard Worker pub const PCI_MSI_FLAGS_64BIT: u16 = 0x0080; // 64-bit addresses allowed
29*bb4ee6a4SAndroid Build Coastguard Worker pub const PCI_MSI_FLAGS_MASKBIT: u16 = 0x0100; // Per-vector masking capable
30*bb4ee6a4SAndroid Build Coastguard Worker const PCI_MSI_ADDRESS_LO: u32 = 0x4; // MSI address lower 32 bits
31*bb4ee6a4SAndroid Build Coastguard Worker const PCI_MSI_ADDRESS_HI: u32 = 0x8; // MSI address upper 32 bits (if 64 bit allowed)
32*bb4ee6a4SAndroid Build Coastguard Worker const PCI_MSI_DATA_32: u32 = 0x8; // 16 bits of data for 32-bit message address
33*bb4ee6a4SAndroid Build Coastguard Worker const PCI_MSI_DATA_64: u32 = 0xC; // 16 bits of date for 64-bit message address
34*bb4ee6a4SAndroid Build Coastguard Worker 
35*bb4ee6a4SAndroid Build Coastguard Worker // MSI length
36*bb4ee6a4SAndroid Build Coastguard Worker const MSI_LENGTH_32BIT_WITHOUT_MASK: u32 = 0xA;
37*bb4ee6a4SAndroid Build Coastguard Worker const MSI_LENGTH_32BIT_WITH_MASK: u32 = 0x14;
38*bb4ee6a4SAndroid Build Coastguard Worker const MSI_LENGTH_64BIT_WITHOUT_MASK: u32 = 0xE;
39*bb4ee6a4SAndroid Build Coastguard Worker const MSI_LENGTH_64BIT_WITH_MASK: u32 = 0x18;
40*bb4ee6a4SAndroid Build Coastguard Worker 
41*bb4ee6a4SAndroid Build Coastguard Worker pub enum MsiStatus {
42*bb4ee6a4SAndroid Build Coastguard Worker     Enabled,
43*bb4ee6a4SAndroid Build Coastguard Worker     Disabled,
44*bb4ee6a4SAndroid Build Coastguard Worker     NothingToDo,
45*bb4ee6a4SAndroid Build Coastguard Worker }
46*bb4ee6a4SAndroid Build Coastguard Worker 
47*bb4ee6a4SAndroid Build Coastguard Worker /// Wrapper over MSI Capability Structure
48*bb4ee6a4SAndroid Build Coastguard Worker pub struct MsiConfig {
49*bb4ee6a4SAndroid Build Coastguard Worker     is_64bit: bool,
50*bb4ee6a4SAndroid Build Coastguard Worker     mask_cap: bool,
51*bb4ee6a4SAndroid Build Coastguard Worker     ctrl: u16,
52*bb4ee6a4SAndroid Build Coastguard Worker     address: u64,
53*bb4ee6a4SAndroid Build Coastguard Worker     data: u16,
54*bb4ee6a4SAndroid Build Coastguard Worker     vm_socket_irq: Tube,
55*bb4ee6a4SAndroid Build Coastguard Worker     irqfd: Option<Event>,
56*bb4ee6a4SAndroid Build Coastguard Worker     gsi: Option<u32>,
57*bb4ee6a4SAndroid Build Coastguard Worker     device_id: u32,
58*bb4ee6a4SAndroid Build Coastguard Worker     device_name: String,
59*bb4ee6a4SAndroid Build Coastguard Worker }
60*bb4ee6a4SAndroid Build Coastguard Worker 
61*bb4ee6a4SAndroid Build Coastguard Worker impl MsiConfig {
new( is_64bit: bool, mask_cap: bool, vm_socket_irq: Tube, device_id: u32, device_name: String, ) -> Self62*bb4ee6a4SAndroid Build Coastguard Worker     pub fn new(
63*bb4ee6a4SAndroid Build Coastguard Worker         is_64bit: bool,
64*bb4ee6a4SAndroid Build Coastguard Worker         mask_cap: bool,
65*bb4ee6a4SAndroid Build Coastguard Worker         vm_socket_irq: Tube,
66*bb4ee6a4SAndroid Build Coastguard Worker         device_id: u32,
67*bb4ee6a4SAndroid Build Coastguard Worker         device_name: String,
68*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Self {
69*bb4ee6a4SAndroid Build Coastguard Worker         let mut ctrl: u16 = 0;
70*bb4ee6a4SAndroid Build Coastguard Worker         if is_64bit {
71*bb4ee6a4SAndroid Build Coastguard Worker             ctrl |= PCI_MSI_FLAGS_64BIT;
72*bb4ee6a4SAndroid Build Coastguard Worker         }
73*bb4ee6a4SAndroid Build Coastguard Worker         if mask_cap {
74*bb4ee6a4SAndroid Build Coastguard Worker             ctrl |= PCI_MSI_FLAGS_MASKBIT;
75*bb4ee6a4SAndroid Build Coastguard Worker         }
76*bb4ee6a4SAndroid Build Coastguard Worker         MsiConfig {
77*bb4ee6a4SAndroid Build Coastguard Worker             is_64bit,
78*bb4ee6a4SAndroid Build Coastguard Worker             mask_cap,
79*bb4ee6a4SAndroid Build Coastguard Worker             ctrl,
80*bb4ee6a4SAndroid Build Coastguard Worker             address: 0,
81*bb4ee6a4SAndroid Build Coastguard Worker             data: 0,
82*bb4ee6a4SAndroid Build Coastguard Worker             vm_socket_irq,
83*bb4ee6a4SAndroid Build Coastguard Worker             irqfd: None,
84*bb4ee6a4SAndroid Build Coastguard Worker             gsi: None,
85*bb4ee6a4SAndroid Build Coastguard Worker             device_id,
86*bb4ee6a4SAndroid Build Coastguard Worker             device_name,
87*bb4ee6a4SAndroid Build Coastguard Worker         }
88*bb4ee6a4SAndroid Build Coastguard Worker     }
89*bb4ee6a4SAndroid Build Coastguard Worker 
len(&self) -> u3290*bb4ee6a4SAndroid Build Coastguard Worker     fn len(&self) -> u32 {
91*bb4ee6a4SAndroid Build Coastguard Worker         match (self.is_64bit, self.mask_cap) {
92*bb4ee6a4SAndroid Build Coastguard Worker             (true, true) => MSI_LENGTH_64BIT_WITH_MASK,
93*bb4ee6a4SAndroid Build Coastguard Worker             (true, false) => MSI_LENGTH_64BIT_WITHOUT_MASK,
94*bb4ee6a4SAndroid Build Coastguard Worker             (false, true) => MSI_LENGTH_32BIT_WITH_MASK,
95*bb4ee6a4SAndroid Build Coastguard Worker             (false, false) => MSI_LENGTH_32BIT_WITHOUT_MASK,
96*bb4ee6a4SAndroid Build Coastguard Worker         }
97*bb4ee6a4SAndroid Build Coastguard Worker     }
98*bb4ee6a4SAndroid Build Coastguard Worker 
is_msi_reg(&self, offset: u32, index: u64, len: usize) -> bool99*bb4ee6a4SAndroid Build Coastguard Worker     pub fn is_msi_reg(&self, offset: u32, index: u64, len: usize) -> bool {
100*bb4ee6a4SAndroid Build Coastguard Worker         let msi_len = self.len();
101*bb4ee6a4SAndroid Build Coastguard Worker         index >= offset as u64
102*bb4ee6a4SAndroid Build Coastguard Worker             && index + len as u64 <= (offset + msi_len) as u64
103*bb4ee6a4SAndroid Build Coastguard Worker             && len as u32 <= msi_len
104*bb4ee6a4SAndroid Build Coastguard Worker     }
105*bb4ee6a4SAndroid Build Coastguard Worker 
read_msi_capability(&self, offset: u32, data: u32) -> u32106*bb4ee6a4SAndroid Build Coastguard Worker     pub fn read_msi_capability(&self, offset: u32, data: u32) -> u32 {
107*bb4ee6a4SAndroid Build Coastguard Worker         if offset == 0 {
108*bb4ee6a4SAndroid Build Coastguard Worker             (self.ctrl as u32) << 16 | (data & u16::MAX as u32)
109*bb4ee6a4SAndroid Build Coastguard Worker         } else {
110*bb4ee6a4SAndroid Build Coastguard Worker             data
111*bb4ee6a4SAndroid Build Coastguard Worker         }
112*bb4ee6a4SAndroid Build Coastguard Worker     }
113*bb4ee6a4SAndroid Build Coastguard Worker 
write_msi_capability(&mut self, offset: u32, data: &[u8]) -> MsiStatus114*bb4ee6a4SAndroid Build Coastguard Worker     pub fn write_msi_capability(&mut self, offset: u32, data: &[u8]) -> MsiStatus {
115*bb4ee6a4SAndroid Build Coastguard Worker         let len = data.len();
116*bb4ee6a4SAndroid Build Coastguard Worker         let mut ret = MsiStatus::NothingToDo;
117*bb4ee6a4SAndroid Build Coastguard Worker         let old_address = self.address;
118*bb4ee6a4SAndroid Build Coastguard Worker         let old_data = self.data;
119*bb4ee6a4SAndroid Build Coastguard Worker 
120*bb4ee6a4SAndroid Build Coastguard Worker         // write msi ctl
121*bb4ee6a4SAndroid Build Coastguard Worker         if len == 2 && offset == PCI_MSI_FLAGS {
122*bb4ee6a4SAndroid Build Coastguard Worker             let was_enabled = self.is_msi_enabled();
123*bb4ee6a4SAndroid Build Coastguard Worker             let value: [u8; 2] = [data[0], data[1]];
124*bb4ee6a4SAndroid Build Coastguard Worker             self.ctrl = u16::from_le_bytes(value);
125*bb4ee6a4SAndroid Build Coastguard Worker             let is_enabled = self.is_msi_enabled();
126*bb4ee6a4SAndroid Build Coastguard Worker             if !was_enabled && is_enabled {
127*bb4ee6a4SAndroid Build Coastguard Worker                 self.enable();
128*bb4ee6a4SAndroid Build Coastguard Worker                 ret = MsiStatus::Enabled;
129*bb4ee6a4SAndroid Build Coastguard Worker             } else if was_enabled && !is_enabled {
130*bb4ee6a4SAndroid Build Coastguard Worker                 ret = MsiStatus::Disabled;
131*bb4ee6a4SAndroid Build Coastguard Worker             }
132*bb4ee6a4SAndroid Build Coastguard Worker         } else if len == 4 && offset == PCI_MSI_ADDRESS_LO && !self.is_64bit {
133*bb4ee6a4SAndroid Build Coastguard Worker             //write 32 bit message address
134*bb4ee6a4SAndroid Build Coastguard Worker             let value: [u8; 8] = [data[0], data[1], data[2], data[3], 0, 0, 0, 0];
135*bb4ee6a4SAndroid Build Coastguard Worker             self.address = u64::from_le_bytes(value);
136*bb4ee6a4SAndroid Build Coastguard Worker         } else if len == 4 && offset == PCI_MSI_ADDRESS_LO && self.is_64bit {
137*bb4ee6a4SAndroid Build Coastguard Worker             // write 64 bit message address low part
138*bb4ee6a4SAndroid Build Coastguard Worker             let value: [u8; 8] = [data[0], data[1], data[2], data[3], 0, 0, 0, 0];
139*bb4ee6a4SAndroid Build Coastguard Worker             self.address &= !0xffffffff;
140*bb4ee6a4SAndroid Build Coastguard Worker             self.address |= u64::from_le_bytes(value);
141*bb4ee6a4SAndroid Build Coastguard Worker         } else if len == 4 && offset == PCI_MSI_ADDRESS_HI && self.is_64bit {
142*bb4ee6a4SAndroid Build Coastguard Worker             //write 64 bit message address high part
143*bb4ee6a4SAndroid Build Coastguard Worker             let value: [u8; 8] = [0, 0, 0, 0, data[0], data[1], data[2], data[3]];
144*bb4ee6a4SAndroid Build Coastguard Worker             self.address &= 0xffffffff;
145*bb4ee6a4SAndroid Build Coastguard Worker             self.address |= u64::from_le_bytes(value);
146*bb4ee6a4SAndroid Build Coastguard Worker         } else if len == 8 && offset == PCI_MSI_ADDRESS_LO && self.is_64bit {
147*bb4ee6a4SAndroid Build Coastguard Worker             // write 64 bit message address
148*bb4ee6a4SAndroid Build Coastguard Worker             let value: [u8; 8] = [
149*bb4ee6a4SAndroid Build Coastguard Worker                 data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7],
150*bb4ee6a4SAndroid Build Coastguard Worker             ];
151*bb4ee6a4SAndroid Build Coastguard Worker             self.address = u64::from_le_bytes(value);
152*bb4ee6a4SAndroid Build Coastguard Worker         } else if len == 2
153*bb4ee6a4SAndroid Build Coastguard Worker             && ((offset == PCI_MSI_DATA_32 && !self.is_64bit)
154*bb4ee6a4SAndroid Build Coastguard Worker                 || (offset == PCI_MSI_DATA_64 && self.is_64bit))
155*bb4ee6a4SAndroid Build Coastguard Worker         {
156*bb4ee6a4SAndroid Build Coastguard Worker             // write message data
157*bb4ee6a4SAndroid Build Coastguard Worker             let value: [u8; 2] = [data[0], data[1]];
158*bb4ee6a4SAndroid Build Coastguard Worker             self.data = u16::from_le_bytes(value);
159*bb4ee6a4SAndroid Build Coastguard Worker         }
160*bb4ee6a4SAndroid Build Coastguard Worker 
161*bb4ee6a4SAndroid Build Coastguard Worker         if self.is_msi_enabled() && (old_address != self.address || old_data != self.data) {
162*bb4ee6a4SAndroid Build Coastguard Worker             self.add_msi_route();
163*bb4ee6a4SAndroid Build Coastguard Worker         }
164*bb4ee6a4SAndroid Build Coastguard Worker 
165*bb4ee6a4SAndroid Build Coastguard Worker         ret
166*bb4ee6a4SAndroid Build Coastguard Worker     }
167*bb4ee6a4SAndroid Build Coastguard Worker 
is_msi_enabled(&self) -> bool168*bb4ee6a4SAndroid Build Coastguard Worker     pub fn is_msi_enabled(&self) -> bool {
169*bb4ee6a4SAndroid Build Coastguard Worker         self.ctrl & PCI_MSI_FLAGS_ENABLE == PCI_MSI_FLAGS_ENABLE
170*bb4ee6a4SAndroid Build Coastguard Worker     }
171*bb4ee6a4SAndroid Build Coastguard Worker 
add_msi_route(&self)172*bb4ee6a4SAndroid Build Coastguard Worker     fn add_msi_route(&self) {
173*bb4ee6a4SAndroid Build Coastguard Worker         let gsi = match self.gsi {
174*bb4ee6a4SAndroid Build Coastguard Worker             Some(g) => g,
175*bb4ee6a4SAndroid Build Coastguard Worker             None => {
176*bb4ee6a4SAndroid Build Coastguard Worker                 error!("Add msi route but gsi is none");
177*bb4ee6a4SAndroid Build Coastguard Worker                 return;
178*bb4ee6a4SAndroid Build Coastguard Worker             }
179*bb4ee6a4SAndroid Build Coastguard Worker         };
180*bb4ee6a4SAndroid Build Coastguard Worker         if let Err(e) = self.vm_socket_irq.send(&VmIrqRequest::AddMsiRoute {
181*bb4ee6a4SAndroid Build Coastguard Worker             gsi,
182*bb4ee6a4SAndroid Build Coastguard Worker             msi_address: self.address,
183*bb4ee6a4SAndroid Build Coastguard Worker             msi_data: self.data.into(),
184*bb4ee6a4SAndroid Build Coastguard Worker         }) {
185*bb4ee6a4SAndroid Build Coastguard Worker             error!("failed to send AddMsiRoute request at {:?}", e);
186*bb4ee6a4SAndroid Build Coastguard Worker             return;
187*bb4ee6a4SAndroid Build Coastguard Worker         }
188*bb4ee6a4SAndroid Build Coastguard Worker         match self.vm_socket_irq.recv() {
189*bb4ee6a4SAndroid Build Coastguard Worker             Ok(VmIrqResponse::Err(e)) => error!("failed to call AddMsiRoute request {:?}", e),
190*bb4ee6a4SAndroid Build Coastguard Worker             Ok(_) => {}
191*bb4ee6a4SAndroid Build Coastguard Worker             Err(e) => error!("failed to receive AddMsiRoute response {:?}", e),
192*bb4ee6a4SAndroid Build Coastguard Worker         }
193*bb4ee6a4SAndroid Build Coastguard Worker     }
194*bb4ee6a4SAndroid Build Coastguard Worker 
allocate_one_msi(&mut self)195*bb4ee6a4SAndroid Build Coastguard Worker     fn allocate_one_msi(&mut self) {
196*bb4ee6a4SAndroid Build Coastguard Worker         let irqfd = match self.irqfd.take() {
197*bb4ee6a4SAndroid Build Coastguard Worker             Some(e) => e,
198*bb4ee6a4SAndroid Build Coastguard Worker             None => match Event::new() {
199*bb4ee6a4SAndroid Build Coastguard Worker                 Ok(e) => e,
200*bb4ee6a4SAndroid Build Coastguard Worker                 Err(e) => {
201*bb4ee6a4SAndroid Build Coastguard Worker                     error!("failed to create event: {:?}", e);
202*bb4ee6a4SAndroid Build Coastguard Worker                     return;
203*bb4ee6a4SAndroid Build Coastguard Worker                 }
204*bb4ee6a4SAndroid Build Coastguard Worker             },
205*bb4ee6a4SAndroid Build Coastguard Worker         };
206*bb4ee6a4SAndroid Build Coastguard Worker 
207*bb4ee6a4SAndroid Build Coastguard Worker         let request = VmIrqRequest::AllocateOneMsi {
208*bb4ee6a4SAndroid Build Coastguard Worker             irqfd,
209*bb4ee6a4SAndroid Build Coastguard Worker             device_id: self.device_id,
210*bb4ee6a4SAndroid Build Coastguard Worker             queue_id: 0,
211*bb4ee6a4SAndroid Build Coastguard Worker             device_name: self.device_name.clone(),
212*bb4ee6a4SAndroid Build Coastguard Worker         };
213*bb4ee6a4SAndroid Build Coastguard Worker         let request_result = self.vm_socket_irq.send(&request);
214*bb4ee6a4SAndroid Build Coastguard Worker 
215*bb4ee6a4SAndroid Build Coastguard Worker         // Stash the irqfd in self immediately because we used take above.
216*bb4ee6a4SAndroid Build Coastguard Worker         self.irqfd = match request {
217*bb4ee6a4SAndroid Build Coastguard Worker             VmIrqRequest::AllocateOneMsi { irqfd, .. } => Some(irqfd),
218*bb4ee6a4SAndroid Build Coastguard Worker             _ => unreachable!(),
219*bb4ee6a4SAndroid Build Coastguard Worker         };
220*bb4ee6a4SAndroid Build Coastguard Worker 
221*bb4ee6a4SAndroid Build Coastguard Worker         if let Err(e) = request_result {
222*bb4ee6a4SAndroid Build Coastguard Worker             error!("failed to send AllocateOneMsi request: {:?}", e);
223*bb4ee6a4SAndroid Build Coastguard Worker             return;
224*bb4ee6a4SAndroid Build Coastguard Worker         }
225*bb4ee6a4SAndroid Build Coastguard Worker 
226*bb4ee6a4SAndroid Build Coastguard Worker         match self.vm_socket_irq.recv() {
227*bb4ee6a4SAndroid Build Coastguard Worker             Ok(VmIrqResponse::AllocateOneMsi { gsi }) => self.gsi = Some(gsi),
228*bb4ee6a4SAndroid Build Coastguard Worker             _ => error!("failed to receive AllocateOneMsi Response"),
229*bb4ee6a4SAndroid Build Coastguard Worker         }
230*bb4ee6a4SAndroid Build Coastguard Worker     }
231*bb4ee6a4SAndroid Build Coastguard Worker 
enable(&mut self)232*bb4ee6a4SAndroid Build Coastguard Worker     fn enable(&mut self) {
233*bb4ee6a4SAndroid Build Coastguard Worker         if self.gsi.is_none() || self.irqfd.is_none() {
234*bb4ee6a4SAndroid Build Coastguard Worker             self.allocate_one_msi();
235*bb4ee6a4SAndroid Build Coastguard Worker         }
236*bb4ee6a4SAndroid Build Coastguard Worker 
237*bb4ee6a4SAndroid Build Coastguard Worker         self.add_msi_route();
238*bb4ee6a4SAndroid Build Coastguard Worker     }
239*bb4ee6a4SAndroid Build Coastguard Worker 
get_irqfd(&self) -> Option<&Event>240*bb4ee6a4SAndroid Build Coastguard Worker     pub fn get_irqfd(&self) -> Option<&Event> {
241*bb4ee6a4SAndroid Build Coastguard Worker         self.irqfd.as_ref()
242*bb4ee6a4SAndroid Build Coastguard Worker     }
243*bb4ee6a4SAndroid Build Coastguard Worker 
destroy(&mut self)244*bb4ee6a4SAndroid Build Coastguard Worker     pub fn destroy(&mut self) {
245*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(gsi) = self.gsi {
246*bb4ee6a4SAndroid Build Coastguard Worker             if let Some(irqfd) = self.irqfd.take() {
247*bb4ee6a4SAndroid Build Coastguard Worker                 let request = VmIrqRequest::ReleaseOneIrq { gsi, irqfd };
248*bb4ee6a4SAndroid Build Coastguard Worker                 if self.vm_socket_irq.send(&request).is_ok() {
249*bb4ee6a4SAndroid Build Coastguard Worker                     let _ = self.vm_socket_irq.recv::<VmIrqResponse>();
250*bb4ee6a4SAndroid Build Coastguard Worker                 }
251*bb4ee6a4SAndroid Build Coastguard Worker             }
252*bb4ee6a4SAndroid Build Coastguard Worker         }
253*bb4ee6a4SAndroid Build Coastguard Worker     }
254*bb4ee6a4SAndroid Build Coastguard Worker 
255*bb4ee6a4SAndroid Build Coastguard Worker     /// Return the raw descriptor of the MSI device socket
get_msi_socket(&self) -> RawDescriptor256*bb4ee6a4SAndroid Build Coastguard Worker     pub fn get_msi_socket(&self) -> RawDescriptor {
257*bb4ee6a4SAndroid Build Coastguard Worker         self.vm_socket_irq.as_raw_descriptor()
258*bb4ee6a4SAndroid Build Coastguard Worker     }
259*bb4ee6a4SAndroid Build Coastguard Worker 
trigger(&self)260*bb4ee6a4SAndroid Build Coastguard Worker     pub fn trigger(&self) {
261*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(irqfd) = self.irqfd.as_ref() {
262*bb4ee6a4SAndroid Build Coastguard Worker             irqfd.signal().unwrap();
263*bb4ee6a4SAndroid Build Coastguard Worker         }
264*bb4ee6a4SAndroid Build Coastguard Worker     }
265*bb4ee6a4SAndroid Build Coastguard Worker }
266*bb4ee6a4SAndroid Build Coastguard Worker 
267*bb4ee6a4SAndroid Build Coastguard Worker #[bitfield]
268*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Copy, Clone, AsBytes, FromZeroes, FromBytes)]
269*bb4ee6a4SAndroid Build Coastguard Worker pub struct MsiCtrl {
270*bb4ee6a4SAndroid Build Coastguard Worker     enable: B1,
271*bb4ee6a4SAndroid Build Coastguard Worker     multi_msg_capable: B3,
272*bb4ee6a4SAndroid Build Coastguard Worker     multi_msg_enable: B3,
273*bb4ee6a4SAndroid Build Coastguard Worker     is_64bit: B1,
274*bb4ee6a4SAndroid Build Coastguard Worker     per_vector_masking: B1,
275*bb4ee6a4SAndroid Build Coastguard Worker     extended_msg_data_capable: B1,
276*bb4ee6a4SAndroid Build Coastguard Worker     extended_msg_data_enable: B1,
277*bb4ee6a4SAndroid Build Coastguard Worker     reserved: B5,
278*bb4ee6a4SAndroid Build Coastguard Worker }
279*bb4ee6a4SAndroid Build Coastguard Worker 
280*bb4ee6a4SAndroid Build Coastguard Worker #[allow(dead_code)]
281*bb4ee6a4SAndroid Build Coastguard Worker #[repr(C, align(4))]
282*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Clone, Copy, Default, AsBytes, FromZeroes, FromBytes)]
283*bb4ee6a4SAndroid Build Coastguard Worker struct Msi32BitWithoutMask {
284*bb4ee6a4SAndroid Build Coastguard Worker     msg_data: u16,
285*bb4ee6a4SAndroid Build Coastguard Worker     msg_extended_data: u16,
286*bb4ee6a4SAndroid Build Coastguard Worker     _padding: [u8; 12],
287*bb4ee6a4SAndroid Build Coastguard Worker }
288*bb4ee6a4SAndroid Build Coastguard Worker 
289*bb4ee6a4SAndroid Build Coastguard Worker #[allow(dead_code)]
290*bb4ee6a4SAndroid Build Coastguard Worker #[repr(C, align(4))]
291*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Clone, Copy, Default, AsBytes, FromZeroes, FromBytes)]
292*bb4ee6a4SAndroid Build Coastguard Worker struct Msi32BitWithMask {
293*bb4ee6a4SAndroid Build Coastguard Worker     msg_data: u16,
294*bb4ee6a4SAndroid Build Coastguard Worker     msg_extended_data: u16,
295*bb4ee6a4SAndroid Build Coastguard Worker     mask_bits: u32,
296*bb4ee6a4SAndroid Build Coastguard Worker     pending_bits: u32,
297*bb4ee6a4SAndroid Build Coastguard Worker     _padding: [u8; 4],
298*bb4ee6a4SAndroid Build Coastguard Worker }
299*bb4ee6a4SAndroid Build Coastguard Worker 
300*bb4ee6a4SAndroid Build Coastguard Worker #[allow(dead_code)]
301*bb4ee6a4SAndroid Build Coastguard Worker #[repr(C, align(4))]
302*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Clone, Copy, Default, AsBytes, FromZeroes, FromBytes)]
303*bb4ee6a4SAndroid Build Coastguard Worker struct Msi64BitWithoutMask {
304*bb4ee6a4SAndroid Build Coastguard Worker     msg_upper: u32,
305*bb4ee6a4SAndroid Build Coastguard Worker     msg_data: u16,
306*bb4ee6a4SAndroid Build Coastguard Worker     msg_extended_data: u16,
307*bb4ee6a4SAndroid Build Coastguard Worker     _padding: [u8; 8],
308*bb4ee6a4SAndroid Build Coastguard Worker }
309*bb4ee6a4SAndroid Build Coastguard Worker 
310*bb4ee6a4SAndroid Build Coastguard Worker #[allow(dead_code)]
311*bb4ee6a4SAndroid Build Coastguard Worker #[repr(C)]
312*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Clone, Copy, Default, AsBytes, FromZeroes, FromBytes)]
313*bb4ee6a4SAndroid Build Coastguard Worker struct Msi64BitWithMask {
314*bb4ee6a4SAndroid Build Coastguard Worker     msg_upper: u32,
315*bb4ee6a4SAndroid Build Coastguard Worker     msg_data: u16,
316*bb4ee6a4SAndroid Build Coastguard Worker     msg_extended_data: u16,
317*bb4ee6a4SAndroid Build Coastguard Worker     mask_bits: u32,
318*bb4ee6a4SAndroid Build Coastguard Worker     pending_bits: u32,
319*bb4ee6a4SAndroid Build Coastguard Worker }
320*bb4ee6a4SAndroid Build Coastguard Worker 
321*bb4ee6a4SAndroid Build Coastguard Worker #[allow(dead_code)]
322*bb4ee6a4SAndroid Build Coastguard Worker #[repr(C)]
323*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Clone, Copy, AsBytes, FromZeroes, FromBytes)]
324*bb4ee6a4SAndroid Build Coastguard Worker union MsiVary {
325*bb4ee6a4SAndroid Build Coastguard Worker     msi_32bit_without_mask: Msi32BitWithoutMask,
326*bb4ee6a4SAndroid Build Coastguard Worker     msi_32bit_with_mask: Msi32BitWithMask,
327*bb4ee6a4SAndroid Build Coastguard Worker     msi_64bit_without_mask: Msi64BitWithoutMask,
328*bb4ee6a4SAndroid Build Coastguard Worker     msi_64bit_with_mask: Msi64BitWithMask,
329*bb4ee6a4SAndroid Build Coastguard Worker }
330*bb4ee6a4SAndroid Build Coastguard Worker 
331*bb4ee6a4SAndroid Build Coastguard Worker #[allow(dead_code)]
332*bb4ee6a4SAndroid Build Coastguard Worker #[repr(C)]
333*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Clone, Copy, AsBytes, FromZeroes, FromBytes)]
334*bb4ee6a4SAndroid Build Coastguard Worker /// MSI Capability Structure
335*bb4ee6a4SAndroid Build Coastguard Worker pub struct MsiCap {
336*bb4ee6a4SAndroid Build Coastguard Worker     // To make add_capability() happy
337*bb4ee6a4SAndroid Build Coastguard Worker     _cap_vndr: u8,
338*bb4ee6a4SAndroid Build Coastguard Worker     _cap_next: u8,
339*bb4ee6a4SAndroid Build Coastguard Worker     // Message Control Register
340*bb4ee6a4SAndroid Build Coastguard Worker     msg_ctl: MsiCtrl,
341*bb4ee6a4SAndroid Build Coastguard Worker     // Message Address
342*bb4ee6a4SAndroid Build Coastguard Worker     msg_addr: u32,
343*bb4ee6a4SAndroid Build Coastguard Worker     // Msi Vary structure
344*bb4ee6a4SAndroid Build Coastguard Worker     msi_vary: MsiVary,
345*bb4ee6a4SAndroid Build Coastguard Worker }
346*bb4ee6a4SAndroid Build Coastguard Worker 
347*bb4ee6a4SAndroid Build Coastguard Worker impl PciCapability for MsiCap {
bytes(&self) -> &[u8]348*bb4ee6a4SAndroid Build Coastguard Worker     fn bytes(&self) -> &[u8] {
349*bb4ee6a4SAndroid Build Coastguard Worker         self.as_bytes()
350*bb4ee6a4SAndroid Build Coastguard Worker     }
351*bb4ee6a4SAndroid Build Coastguard Worker 
id(&self) -> PciCapabilityID352*bb4ee6a4SAndroid Build Coastguard Worker     fn id(&self) -> PciCapabilityID {
353*bb4ee6a4SAndroid Build Coastguard Worker         PciCapabilityID::MessageSignalledInterrupts
354*bb4ee6a4SAndroid Build Coastguard Worker     }
355*bb4ee6a4SAndroid Build Coastguard Worker 
writable_bits(&self) -> Vec<u32>356*bb4ee6a4SAndroid Build Coastguard Worker     fn writable_bits(&self) -> Vec<u32> {
357*bb4ee6a4SAndroid Build Coastguard Worker         // Check spec for detail
358*bb4ee6a4SAndroid Build Coastguard Worker         match (
359*bb4ee6a4SAndroid Build Coastguard Worker             self.msg_ctl.get_is_64bit(),
360*bb4ee6a4SAndroid Build Coastguard Worker             self.msg_ctl.get_per_vector_masking(),
361*bb4ee6a4SAndroid Build Coastguard Worker         ) {
362*bb4ee6a4SAndroid Build Coastguard Worker             (0, 0) => vec![0x0471_0000, 0xffff_fffc, 0xffff_ffff],
363*bb4ee6a4SAndroid Build Coastguard Worker             (0, 1) => vec![0x0471_0000, 0xffff_fffc, 0xffff_ffff, 0xffff_ffff],
364*bb4ee6a4SAndroid Build Coastguard Worker             (1, 0) => vec![
365*bb4ee6a4SAndroid Build Coastguard Worker                 0x0471_0000,
366*bb4ee6a4SAndroid Build Coastguard Worker                 0xffff_fffc,
367*bb4ee6a4SAndroid Build Coastguard Worker                 0xffff_ffff,
368*bb4ee6a4SAndroid Build Coastguard Worker                 0xffff_ffff,
369*bb4ee6a4SAndroid Build Coastguard Worker                 0x0000_0000,
370*bb4ee6a4SAndroid Build Coastguard Worker             ],
371*bb4ee6a4SAndroid Build Coastguard Worker             (1, 1) => vec![
372*bb4ee6a4SAndroid Build Coastguard Worker                 0x0471_0000,
373*bb4ee6a4SAndroid Build Coastguard Worker                 0xffff_fffc,
374*bb4ee6a4SAndroid Build Coastguard Worker                 0xffff_ffff,
375*bb4ee6a4SAndroid Build Coastguard Worker                 0xffff_ffff,
376*bb4ee6a4SAndroid Build Coastguard Worker                 0xffff_ffff,
377*bb4ee6a4SAndroid Build Coastguard Worker                 0x0000_0000,
378*bb4ee6a4SAndroid Build Coastguard Worker             ],
379*bb4ee6a4SAndroid Build Coastguard Worker             (_, _) => Vec::new(),
380*bb4ee6a4SAndroid Build Coastguard Worker         }
381*bb4ee6a4SAndroid Build Coastguard Worker     }
382*bb4ee6a4SAndroid Build Coastguard Worker }
383*bb4ee6a4SAndroid Build Coastguard Worker 
384*bb4ee6a4SAndroid Build Coastguard Worker impl MsiCap {
new(is_64bit: bool, mask_cap: bool) -> Self385*bb4ee6a4SAndroid Build Coastguard Worker     pub fn new(is_64bit: bool, mask_cap: bool) -> Self {
386*bb4ee6a4SAndroid Build Coastguard Worker         let mut msg_ctl = MsiCtrl::new();
387*bb4ee6a4SAndroid Build Coastguard Worker         if is_64bit {
388*bb4ee6a4SAndroid Build Coastguard Worker             msg_ctl.set_is_64bit(1);
389*bb4ee6a4SAndroid Build Coastguard Worker         }
390*bb4ee6a4SAndroid Build Coastguard Worker         if mask_cap {
391*bb4ee6a4SAndroid Build Coastguard Worker             msg_ctl.set_per_vector_masking(1);
392*bb4ee6a4SAndroid Build Coastguard Worker         }
393*bb4ee6a4SAndroid Build Coastguard Worker         let msi_vary = match (is_64bit, mask_cap) {
394*bb4ee6a4SAndroid Build Coastguard Worker             (false, false) => MsiVary {
395*bb4ee6a4SAndroid Build Coastguard Worker                 msi_32bit_without_mask: Msi32BitWithoutMask::default(),
396*bb4ee6a4SAndroid Build Coastguard Worker             },
397*bb4ee6a4SAndroid Build Coastguard Worker             (false, true) => MsiVary {
398*bb4ee6a4SAndroid Build Coastguard Worker                 msi_32bit_with_mask: Msi32BitWithMask::default(),
399*bb4ee6a4SAndroid Build Coastguard Worker             },
400*bb4ee6a4SAndroid Build Coastguard Worker             (true, false) => MsiVary {
401*bb4ee6a4SAndroid Build Coastguard Worker                 msi_64bit_without_mask: Msi64BitWithoutMask::default(),
402*bb4ee6a4SAndroid Build Coastguard Worker             },
403*bb4ee6a4SAndroid Build Coastguard Worker             (true, true) => MsiVary {
404*bb4ee6a4SAndroid Build Coastguard Worker                 msi_64bit_with_mask: Msi64BitWithMask::default(),
405*bb4ee6a4SAndroid Build Coastguard Worker             },
406*bb4ee6a4SAndroid Build Coastguard Worker         };
407*bb4ee6a4SAndroid Build Coastguard Worker         MsiCap {
408*bb4ee6a4SAndroid Build Coastguard Worker             _cap_vndr: 0,
409*bb4ee6a4SAndroid Build Coastguard Worker             _cap_next: 0,
410*bb4ee6a4SAndroid Build Coastguard Worker             msg_ctl,
411*bb4ee6a4SAndroid Build Coastguard Worker             msg_addr: 0,
412*bb4ee6a4SAndroid Build Coastguard Worker             msi_vary,
413*bb4ee6a4SAndroid Build Coastguard Worker         }
414*bb4ee6a4SAndroid Build Coastguard Worker     }
415*bb4ee6a4SAndroid Build Coastguard Worker }
416*bb4ee6a4SAndroid Build Coastguard Worker 
417*bb4ee6a4SAndroid Build Coastguard Worker const MSI_CONFIG_READ_MASK: [u32; MSI_LENGTH_64BIT_WITH_MASK as usize / 4] =
418*bb4ee6a4SAndroid Build Coastguard Worker     [0xffff_0000, 0, 0, 0, 0, 0];
419*bb4ee6a4SAndroid Build Coastguard Worker 
420*bb4ee6a4SAndroid Build Coastguard Worker impl PciCapConfig for MsiConfig {
read_mask(&self) -> &'static [u32]421*bb4ee6a4SAndroid Build Coastguard Worker     fn read_mask(&self) -> &'static [u32] {
422*bb4ee6a4SAndroid Build Coastguard Worker         let num_regs = (self.len() + 3) / 4;
423*bb4ee6a4SAndroid Build Coastguard Worker         &MSI_CONFIG_READ_MASK[0..(num_regs as usize)]
424*bb4ee6a4SAndroid Build Coastguard Worker     }
425*bb4ee6a4SAndroid Build Coastguard Worker 
read_reg(&self, reg_idx: usize) -> u32426*bb4ee6a4SAndroid Build Coastguard Worker     fn read_reg(&self, reg_idx: usize) -> u32 {
427*bb4ee6a4SAndroid Build Coastguard Worker         self.read_msi_capability(reg_idx as u32 * 4, 0)
428*bb4ee6a4SAndroid Build Coastguard Worker     }
429*bb4ee6a4SAndroid Build Coastguard Worker 
write_reg( &mut self, reg_idx: usize, offset: u64, data: &[u8], ) -> Option<Box<dyn PciCapConfigWriteResult>>430*bb4ee6a4SAndroid Build Coastguard Worker     fn write_reg(
431*bb4ee6a4SAndroid Build Coastguard Worker         &mut self,
432*bb4ee6a4SAndroid Build Coastguard Worker         reg_idx: usize,
433*bb4ee6a4SAndroid Build Coastguard Worker         offset: u64,
434*bb4ee6a4SAndroid Build Coastguard Worker         data: &[u8],
435*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Option<Box<dyn PciCapConfigWriteResult>> {
436*bb4ee6a4SAndroid Build Coastguard Worker         let offset = reg_idx as u32 * 4 + offset as u32;
437*bb4ee6a4SAndroid Build Coastguard Worker         self.write_msi_capability(offset, data);
438*bb4ee6a4SAndroid Build Coastguard Worker         None
439*bb4ee6a4SAndroid Build Coastguard Worker     }
440*bb4ee6a4SAndroid Build Coastguard Worker }
441