xref: /aosp_15_r20/external/crosvm/devices/src/pci/msix.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2019 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 use std::convert::TryInto;
6*bb4ee6a4SAndroid Build Coastguard Worker 
7*bb4ee6a4SAndroid Build Coastguard Worker use anyhow::Context;
8*bb4ee6a4SAndroid Build Coastguard Worker use base::error;
9*bb4ee6a4SAndroid Build Coastguard Worker use base::info;
10*bb4ee6a4SAndroid Build Coastguard Worker use base::AsRawDescriptor;
11*bb4ee6a4SAndroid Build Coastguard Worker use base::Error as SysError;
12*bb4ee6a4SAndroid Build Coastguard Worker use base::Event;
13*bb4ee6a4SAndroid Build Coastguard Worker use base::RawDescriptor;
14*bb4ee6a4SAndroid Build Coastguard Worker use base::Tube;
15*bb4ee6a4SAndroid Build Coastguard Worker use base::TubeError;
16*bb4ee6a4SAndroid Build Coastguard Worker use bit_field::*;
17*bb4ee6a4SAndroid Build Coastguard Worker use remain::sorted;
18*bb4ee6a4SAndroid Build Coastguard Worker use serde::Deserialize;
19*bb4ee6a4SAndroid Build Coastguard Worker use serde::Serialize;
20*bb4ee6a4SAndroid Build Coastguard Worker use thiserror::Error;
21*bb4ee6a4SAndroid Build Coastguard Worker use vm_control::VmIrqRequest;
22*bb4ee6a4SAndroid Build Coastguard Worker use vm_control::VmIrqResponse;
23*bb4ee6a4SAndroid Build Coastguard Worker use zerocopy::AsBytes;
24*bb4ee6a4SAndroid Build Coastguard Worker use zerocopy::FromBytes;
25*bb4ee6a4SAndroid Build Coastguard Worker use zerocopy::FromZeroes;
26*bb4ee6a4SAndroid Build Coastguard Worker 
27*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::pci_configuration::PciCapConfig;
28*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::pci_configuration::PciCapConfigWriteResult;
29*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::PciCapability;
30*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::PciCapabilityID;
31*bb4ee6a4SAndroid Build Coastguard Worker 
32*bb4ee6a4SAndroid Build Coastguard Worker const MAX_MSIX_VECTORS_PER_DEVICE: u16 = 2048;
33*bb4ee6a4SAndroid Build Coastguard Worker pub const MSIX_TABLE_ENTRIES_MODULO: u64 = 16;
34*bb4ee6a4SAndroid Build Coastguard Worker pub const MSIX_PBA_ENTRIES_MODULO: u64 = 8;
35*bb4ee6a4SAndroid Build Coastguard Worker pub const BITS_PER_PBA_ENTRY: usize = 64;
36*bb4ee6a4SAndroid Build Coastguard Worker const FUNCTION_MASK_BIT: u16 = 0x4000;
37*bb4ee6a4SAndroid Build Coastguard Worker const MSIX_ENABLE_BIT: u16 = 0x8000;
38*bb4ee6a4SAndroid Build Coastguard Worker const MSIX_TABLE_ENTRY_MASK_BIT: u32 = 0x1;
39*bb4ee6a4SAndroid Build Coastguard Worker 
40*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Serialize, Deserialize, Clone, Default)]
41*bb4ee6a4SAndroid Build Coastguard Worker struct MsixTableEntry {
42*bb4ee6a4SAndroid Build Coastguard Worker     msg_addr_lo: u32,
43*bb4ee6a4SAndroid Build Coastguard Worker     msg_addr_hi: u32,
44*bb4ee6a4SAndroid Build Coastguard Worker     msg_data: u32,
45*bb4ee6a4SAndroid Build Coastguard Worker     vector_ctl: u32,
46*bb4ee6a4SAndroid Build Coastguard Worker }
47*bb4ee6a4SAndroid Build Coastguard Worker 
48*bb4ee6a4SAndroid Build Coastguard Worker impl MsixTableEntry {
masked(&self) -> bool49*bb4ee6a4SAndroid Build Coastguard Worker     fn masked(&self) -> bool {
50*bb4ee6a4SAndroid Build Coastguard Worker         self.vector_ctl & MSIX_TABLE_ENTRY_MASK_BIT == MSIX_TABLE_ENTRY_MASK_BIT
51*bb4ee6a4SAndroid Build Coastguard Worker     }
52*bb4ee6a4SAndroid Build Coastguard Worker }
53*bb4ee6a4SAndroid Build Coastguard Worker 
54*bb4ee6a4SAndroid Build Coastguard Worker struct IrqfdGsi {
55*bb4ee6a4SAndroid Build Coastguard Worker     irqfd: Event,
56*bb4ee6a4SAndroid Build Coastguard Worker     gsi: u32,
57*bb4ee6a4SAndroid Build Coastguard Worker }
58*bb4ee6a4SAndroid Build Coastguard Worker 
59*bb4ee6a4SAndroid Build Coastguard Worker /// Wrapper over MSI-X Capability Structure and MSI-X Tables
60*bb4ee6a4SAndroid Build Coastguard Worker pub struct MsixConfig {
61*bb4ee6a4SAndroid Build Coastguard Worker     table_entries: Vec<MsixTableEntry>,
62*bb4ee6a4SAndroid Build Coastguard Worker     pba_entries: Vec<u64>,
63*bb4ee6a4SAndroid Build Coastguard Worker     irq_vec: Vec<Option<IrqfdGsi>>,
64*bb4ee6a4SAndroid Build Coastguard Worker     masked: bool,
65*bb4ee6a4SAndroid Build Coastguard Worker     enabled: bool,
66*bb4ee6a4SAndroid Build Coastguard Worker     msi_device_socket: Tube,
67*bb4ee6a4SAndroid Build Coastguard Worker     msix_num: u16,
68*bb4ee6a4SAndroid Build Coastguard Worker     pci_id: u32,
69*bb4ee6a4SAndroid Build Coastguard Worker     device_name: String,
70*bb4ee6a4SAndroid Build Coastguard Worker }
71*bb4ee6a4SAndroid Build Coastguard Worker 
72*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Serialize, Deserialize)]
73*bb4ee6a4SAndroid Build Coastguard Worker struct MsixConfigSnapshot {
74*bb4ee6a4SAndroid Build Coastguard Worker     table_entries: Vec<MsixTableEntry>,
75*bb4ee6a4SAndroid Build Coastguard Worker     pba_entries: Vec<u64>,
76*bb4ee6a4SAndroid Build Coastguard Worker     /// Just like MsixConfig::irq_vec, but only the GSI.
77*bb4ee6a4SAndroid Build Coastguard Worker     irq_gsi_vec: Vec<Option<u32>>,
78*bb4ee6a4SAndroid Build Coastguard Worker     masked: bool,
79*bb4ee6a4SAndroid Build Coastguard Worker     enabled: bool,
80*bb4ee6a4SAndroid Build Coastguard Worker     msix_num: u16,
81*bb4ee6a4SAndroid Build Coastguard Worker     pci_id: u32,
82*bb4ee6a4SAndroid Build Coastguard Worker     device_name: String,
83*bb4ee6a4SAndroid Build Coastguard Worker }
84*bb4ee6a4SAndroid Build Coastguard Worker 
85*bb4ee6a4SAndroid Build Coastguard Worker #[sorted]
86*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Error, Debug)]
87*bb4ee6a4SAndroid Build Coastguard Worker pub enum MsixError {
88*bb4ee6a4SAndroid Build Coastguard Worker     #[error("AddMsiRoute failed: {0}")]
89*bb4ee6a4SAndroid Build Coastguard Worker     AddMsiRoute(SysError),
90*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to receive AddMsiRoute response: {0}")]
91*bb4ee6a4SAndroid Build Coastguard Worker     AddMsiRouteRecv(TubeError),
92*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to send AddMsiRoute request: {0}")]
93*bb4ee6a4SAndroid Build Coastguard Worker     AddMsiRouteSend(TubeError),
94*bb4ee6a4SAndroid Build Coastguard Worker     #[error("AllocateOneMsi failed: {0}")]
95*bb4ee6a4SAndroid Build Coastguard Worker     AllocateOneMsi(SysError),
96*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to receive AllocateOneMsi response: {0}")]
97*bb4ee6a4SAndroid Build Coastguard Worker     AllocateOneMsiRecv(TubeError),
98*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to send AllocateOneMsi request: {0}")]
99*bb4ee6a4SAndroid Build Coastguard Worker     AllocateOneMsiSend(TubeError),
100*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to deserialize snapshot: {0}")]
101*bb4ee6a4SAndroid Build Coastguard Worker     DeserializationFailed(serde_json::Error),
102*bb4ee6a4SAndroid Build Coastguard Worker     #[error("invalid vector length in snapshot: {0}")]
103*bb4ee6a4SAndroid Build Coastguard Worker     InvalidVectorLength(std::num::TryFromIntError),
104*bb4ee6a4SAndroid Build Coastguard Worker     #[error("ReleaseOneIrq failed: {0}")]
105*bb4ee6a4SAndroid Build Coastguard Worker     ReleaseOneIrq(base::Error),
106*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to receive ReleaseOneIrq response: {0}")]
107*bb4ee6a4SAndroid Build Coastguard Worker     ReleaseOneIrqRecv(TubeError),
108*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to send ReleaseOneIrq request: {0}")]
109*bb4ee6a4SAndroid Build Coastguard Worker     ReleaseOneIrqSend(TubeError),
110*bb4ee6a4SAndroid Build Coastguard Worker }
111*bb4ee6a4SAndroid Build Coastguard Worker 
112*bb4ee6a4SAndroid Build Coastguard Worker type MsixResult<T> = std::result::Result<T, MsixError>;
113*bb4ee6a4SAndroid Build Coastguard Worker 
114*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Copy, Clone)]
115*bb4ee6a4SAndroid Build Coastguard Worker pub enum MsixStatus {
116*bb4ee6a4SAndroid Build Coastguard Worker     Changed,
117*bb4ee6a4SAndroid Build Coastguard Worker     EntryChanged(usize),
118*bb4ee6a4SAndroid Build Coastguard Worker     NothingToDo,
119*bb4ee6a4SAndroid Build Coastguard Worker }
120*bb4ee6a4SAndroid Build Coastguard Worker 
121*bb4ee6a4SAndroid Build Coastguard Worker impl PciCapConfigWriteResult for MsixStatus {}
122*bb4ee6a4SAndroid Build Coastguard Worker 
123*bb4ee6a4SAndroid Build Coastguard Worker impl MsixConfig {
new(msix_vectors: u16, vm_socket: Tube, pci_id: u32, device_name: String) -> Self124*bb4ee6a4SAndroid Build Coastguard Worker     pub fn new(msix_vectors: u16, vm_socket: Tube, pci_id: u32, device_name: String) -> Self {
125*bb4ee6a4SAndroid Build Coastguard Worker         assert!(msix_vectors <= MAX_MSIX_VECTORS_PER_DEVICE);
126*bb4ee6a4SAndroid Build Coastguard Worker 
127*bb4ee6a4SAndroid Build Coastguard Worker         let mut table_entries: Vec<MsixTableEntry> = Vec::new();
128*bb4ee6a4SAndroid Build Coastguard Worker         table_entries.resize_with(msix_vectors as usize, Default::default);
129*bb4ee6a4SAndroid Build Coastguard Worker         table_entries
130*bb4ee6a4SAndroid Build Coastguard Worker             .iter_mut()
131*bb4ee6a4SAndroid Build Coastguard Worker             .for_each(|entry| entry.vector_ctl |= MSIX_TABLE_ENTRY_MASK_BIT);
132*bb4ee6a4SAndroid Build Coastguard Worker         let mut pba_entries: Vec<u64> = Vec::new();
133*bb4ee6a4SAndroid Build Coastguard Worker         let num_pba_entries: usize =
134*bb4ee6a4SAndroid Build Coastguard Worker             ((msix_vectors as usize) + BITS_PER_PBA_ENTRY - 1) / BITS_PER_PBA_ENTRY;
135*bb4ee6a4SAndroid Build Coastguard Worker         pba_entries.resize_with(num_pba_entries, Default::default);
136*bb4ee6a4SAndroid Build Coastguard Worker 
137*bb4ee6a4SAndroid Build Coastguard Worker         let mut irq_vec = Vec::new();
138*bb4ee6a4SAndroid Build Coastguard Worker         irq_vec.resize_with(msix_vectors.into(), || None::<IrqfdGsi>);
139*bb4ee6a4SAndroid Build Coastguard Worker 
140*bb4ee6a4SAndroid Build Coastguard Worker         MsixConfig {
141*bb4ee6a4SAndroid Build Coastguard Worker             table_entries,
142*bb4ee6a4SAndroid Build Coastguard Worker             pba_entries,
143*bb4ee6a4SAndroid Build Coastguard Worker             irq_vec,
144*bb4ee6a4SAndroid Build Coastguard Worker             masked: false,
145*bb4ee6a4SAndroid Build Coastguard Worker             enabled: false,
146*bb4ee6a4SAndroid Build Coastguard Worker             msi_device_socket: vm_socket,
147*bb4ee6a4SAndroid Build Coastguard Worker             msix_num: msix_vectors,
148*bb4ee6a4SAndroid Build Coastguard Worker             pci_id,
149*bb4ee6a4SAndroid Build Coastguard Worker             device_name,
150*bb4ee6a4SAndroid Build Coastguard Worker         }
151*bb4ee6a4SAndroid Build Coastguard Worker     }
152*bb4ee6a4SAndroid Build Coastguard Worker 
153*bb4ee6a4SAndroid Build Coastguard Worker     /// Get the number of MSI-X vectors in this configuration.
num_vectors(&self) -> u16154*bb4ee6a4SAndroid Build Coastguard Worker     pub fn num_vectors(&self) -> u16 {
155*bb4ee6a4SAndroid Build Coastguard Worker         self.msix_num
156*bb4ee6a4SAndroid Build Coastguard Worker     }
157*bb4ee6a4SAndroid Build Coastguard Worker 
158*bb4ee6a4SAndroid Build Coastguard Worker     /// Check whether the Function Mask bit in Message Control word in set or not.
159*bb4ee6a4SAndroid Build Coastguard Worker     /// if 1, all of the vectors associated with the function are masked,
160*bb4ee6a4SAndroid Build Coastguard Worker     /// regardless of their per-vector Mask bit states.
161*bb4ee6a4SAndroid Build Coastguard Worker     /// If 0, each vector's Mask bit determines whether the vector is masked or not.
masked(&self) -> bool162*bb4ee6a4SAndroid Build Coastguard Worker     pub fn masked(&self) -> bool {
163*bb4ee6a4SAndroid Build Coastguard Worker         self.masked
164*bb4ee6a4SAndroid Build Coastguard Worker     }
165*bb4ee6a4SAndroid Build Coastguard Worker 
166*bb4ee6a4SAndroid Build Coastguard Worker     /// Check whether the Function Mask bit in MSIX table Message Control
167*bb4ee6a4SAndroid Build Coastguard Worker     /// word in set or not.
168*bb4ee6a4SAndroid Build Coastguard Worker     /// If true, the vector is masked.
169*bb4ee6a4SAndroid Build Coastguard Worker     /// If false, the vector is unmasked.
table_masked(&self, index: usize) -> bool170*bb4ee6a4SAndroid Build Coastguard Worker     pub fn table_masked(&self, index: usize) -> bool {
171*bb4ee6a4SAndroid Build Coastguard Worker         if index >= self.table_entries.len() {
172*bb4ee6a4SAndroid Build Coastguard Worker             true
173*bb4ee6a4SAndroid Build Coastguard Worker         } else {
174*bb4ee6a4SAndroid Build Coastguard Worker             self.table_entries[index].masked()
175*bb4ee6a4SAndroid Build Coastguard Worker         }
176*bb4ee6a4SAndroid Build Coastguard Worker     }
177*bb4ee6a4SAndroid Build Coastguard Worker 
178*bb4ee6a4SAndroid Build Coastguard Worker     /// Check whether the MSI-X Enable bit in Message Control word in set or not.
179*bb4ee6a4SAndroid Build Coastguard Worker     /// if 1, the function is permitted to use MSI-X to request service.
enabled(&self) -> bool180*bb4ee6a4SAndroid Build Coastguard Worker     pub fn enabled(&self) -> bool {
181*bb4ee6a4SAndroid Build Coastguard Worker         self.enabled
182*bb4ee6a4SAndroid Build Coastguard Worker     }
183*bb4ee6a4SAndroid Build Coastguard Worker 
184*bb4ee6a4SAndroid Build Coastguard Worker     /// Read the MSI-X Capability Structure.
185*bb4ee6a4SAndroid Build Coastguard Worker     /// The top 2 bits in Message Control word are emulated and all other
186*bb4ee6a4SAndroid Build Coastguard Worker     /// bits are read only.
read_msix_capability(&self, data: u32) -> u32187*bb4ee6a4SAndroid Build Coastguard Worker     pub fn read_msix_capability(&self, data: u32) -> u32 {
188*bb4ee6a4SAndroid Build Coastguard Worker         let mut msg_ctl = (data >> 16) as u16;
189*bb4ee6a4SAndroid Build Coastguard Worker         msg_ctl &= !(MSIX_ENABLE_BIT | FUNCTION_MASK_BIT);
190*bb4ee6a4SAndroid Build Coastguard Worker 
191*bb4ee6a4SAndroid Build Coastguard Worker         if self.enabled {
192*bb4ee6a4SAndroid Build Coastguard Worker             msg_ctl |= MSIX_ENABLE_BIT;
193*bb4ee6a4SAndroid Build Coastguard Worker         }
194*bb4ee6a4SAndroid Build Coastguard Worker         if self.masked {
195*bb4ee6a4SAndroid Build Coastguard Worker             msg_ctl |= FUNCTION_MASK_BIT;
196*bb4ee6a4SAndroid Build Coastguard Worker         }
197*bb4ee6a4SAndroid Build Coastguard Worker         (msg_ctl as u32) << 16 | (data & u16::MAX as u32)
198*bb4ee6a4SAndroid Build Coastguard Worker     }
199*bb4ee6a4SAndroid Build Coastguard Worker 
200*bb4ee6a4SAndroid Build Coastguard Worker     /// Write to the MSI-X Capability Structure.
201*bb4ee6a4SAndroid Build Coastguard Worker     /// Only the top 2 bits in Message Control Word are writable.
write_msix_capability(&mut self, offset: u64, data: &[u8]) -> MsixStatus202*bb4ee6a4SAndroid Build Coastguard Worker     pub fn write_msix_capability(&mut self, offset: u64, data: &[u8]) -> MsixStatus {
203*bb4ee6a4SAndroid Build Coastguard Worker         if offset == 2 && data.len() == 2 {
204*bb4ee6a4SAndroid Build Coastguard Worker             let reg = u16::from_le_bytes([data[0], data[1]]);
205*bb4ee6a4SAndroid Build Coastguard Worker             let old_masked = self.masked;
206*bb4ee6a4SAndroid Build Coastguard Worker             let old_enabled = self.enabled;
207*bb4ee6a4SAndroid Build Coastguard Worker 
208*bb4ee6a4SAndroid Build Coastguard Worker             self.masked = (reg & FUNCTION_MASK_BIT) == FUNCTION_MASK_BIT;
209*bb4ee6a4SAndroid Build Coastguard Worker             self.enabled = (reg & MSIX_ENABLE_BIT) == MSIX_ENABLE_BIT;
210*bb4ee6a4SAndroid Build Coastguard Worker 
211*bb4ee6a4SAndroid Build Coastguard Worker             if !old_enabled && self.enabled {
212*bb4ee6a4SAndroid Build Coastguard Worker                 if let Err(e) = self.msix_enable_all() {
213*bb4ee6a4SAndroid Build Coastguard Worker                     error!("failed to enable MSI-X: {}", e);
214*bb4ee6a4SAndroid Build Coastguard Worker                     self.enabled = false;
215*bb4ee6a4SAndroid Build Coastguard Worker                 }
216*bb4ee6a4SAndroid Build Coastguard Worker             }
217*bb4ee6a4SAndroid Build Coastguard Worker 
218*bb4ee6a4SAndroid Build Coastguard Worker             // If the Function Mask bit was set, and has just been cleared, it's
219*bb4ee6a4SAndroid Build Coastguard Worker             // important to go through the entire PBA to check if there was any
220*bb4ee6a4SAndroid Build Coastguard Worker             // pending MSI-X message to inject, given that the vector is not
221*bb4ee6a4SAndroid Build Coastguard Worker             // masked.
222*bb4ee6a4SAndroid Build Coastguard Worker             if old_masked && !self.masked {
223*bb4ee6a4SAndroid Build Coastguard Worker                 for (index, entry) in self.table_entries.clone().iter().enumerate() {
224*bb4ee6a4SAndroid Build Coastguard Worker                     if !entry.masked() && self.get_pba_bit(index as u16) == 1 {
225*bb4ee6a4SAndroid Build Coastguard Worker                         self.inject_msix_and_clear_pba(index);
226*bb4ee6a4SAndroid Build Coastguard Worker                     }
227*bb4ee6a4SAndroid Build Coastguard Worker                 }
228*bb4ee6a4SAndroid Build Coastguard Worker                 return MsixStatus::Changed;
229*bb4ee6a4SAndroid Build Coastguard Worker             } else if !old_masked && self.masked {
230*bb4ee6a4SAndroid Build Coastguard Worker                 return MsixStatus::Changed;
231*bb4ee6a4SAndroid Build Coastguard Worker             }
232*bb4ee6a4SAndroid Build Coastguard Worker         } else {
233*bb4ee6a4SAndroid Build Coastguard Worker             error!(
234*bb4ee6a4SAndroid Build Coastguard Worker                 "invalid write to MSI-X Capability Structure offset {:x}",
235*bb4ee6a4SAndroid Build Coastguard Worker                 offset
236*bb4ee6a4SAndroid Build Coastguard Worker             );
237*bb4ee6a4SAndroid Build Coastguard Worker         }
238*bb4ee6a4SAndroid Build Coastguard Worker         MsixStatus::NothingToDo
239*bb4ee6a4SAndroid Build Coastguard Worker     }
240*bb4ee6a4SAndroid Build Coastguard Worker 
241*bb4ee6a4SAndroid Build Coastguard Worker     /// Create a snapshot of the current MsixConfig struct for use in
242*bb4ee6a4SAndroid Build Coastguard Worker     /// snapshotting.
snapshot(&mut self) -> anyhow::Result<serde_json::Value>243*bb4ee6a4SAndroid Build Coastguard Worker     pub fn snapshot(&mut self) -> anyhow::Result<serde_json::Value> {
244*bb4ee6a4SAndroid Build Coastguard Worker         serde_json::to_value(MsixConfigSnapshot {
245*bb4ee6a4SAndroid Build Coastguard Worker             table_entries: self.table_entries.clone(),
246*bb4ee6a4SAndroid Build Coastguard Worker             pba_entries: self.pba_entries.clone(),
247*bb4ee6a4SAndroid Build Coastguard Worker             masked: self.masked,
248*bb4ee6a4SAndroid Build Coastguard Worker             enabled: self.enabled,
249*bb4ee6a4SAndroid Build Coastguard Worker             msix_num: self.msix_num,
250*bb4ee6a4SAndroid Build Coastguard Worker             pci_id: self.pci_id,
251*bb4ee6a4SAndroid Build Coastguard Worker             device_name: self.device_name.clone(),
252*bb4ee6a4SAndroid Build Coastguard Worker             irq_gsi_vec: self
253*bb4ee6a4SAndroid Build Coastguard Worker                 .irq_vec
254*bb4ee6a4SAndroid Build Coastguard Worker                 .iter()
255*bb4ee6a4SAndroid Build Coastguard Worker                 .map(|irq_opt| irq_opt.as_ref().map(|irq| irq.gsi))
256*bb4ee6a4SAndroid Build Coastguard Worker                 .collect(),
257*bb4ee6a4SAndroid Build Coastguard Worker         })
258*bb4ee6a4SAndroid Build Coastguard Worker         .context("failed to serialize MsixConfigSnapshot")
259*bb4ee6a4SAndroid Build Coastguard Worker     }
260*bb4ee6a4SAndroid Build Coastguard Worker 
261*bb4ee6a4SAndroid Build Coastguard Worker     /// Restore a MsixConfig struct based on a snapshot. In short, this will
262*bb4ee6a4SAndroid Build Coastguard Worker     /// restore all data exposed via MMIO, and recreate all MSI-X vectors (they
263*bb4ee6a4SAndroid Build Coastguard Worker     /// will be re-wired to the irq chip).
restore(&mut self, snapshot: serde_json::Value) -> MsixResult<()>264*bb4ee6a4SAndroid Build Coastguard Worker     pub fn restore(&mut self, snapshot: serde_json::Value) -> MsixResult<()> {
265*bb4ee6a4SAndroid Build Coastguard Worker         let snapshot: MsixConfigSnapshot =
266*bb4ee6a4SAndroid Build Coastguard Worker             serde_json::from_value(snapshot).map_err(MsixError::DeserializationFailed)?;
267*bb4ee6a4SAndroid Build Coastguard Worker 
268*bb4ee6a4SAndroid Build Coastguard Worker         self.table_entries = snapshot.table_entries;
269*bb4ee6a4SAndroid Build Coastguard Worker         self.pba_entries = snapshot.pba_entries;
270*bb4ee6a4SAndroid Build Coastguard Worker         self.masked = snapshot.masked;
271*bb4ee6a4SAndroid Build Coastguard Worker         self.enabled = snapshot.enabled;
272*bb4ee6a4SAndroid Build Coastguard Worker         self.msix_num = snapshot.msix_num;
273*bb4ee6a4SAndroid Build Coastguard Worker         self.pci_id = snapshot.pci_id;
274*bb4ee6a4SAndroid Build Coastguard Worker         self.device_name = snapshot.device_name;
275*bb4ee6a4SAndroid Build Coastguard Worker 
276*bb4ee6a4SAndroid Build Coastguard Worker         self.msix_release_all()?;
277*bb4ee6a4SAndroid Build Coastguard Worker         self.irq_vec
278*bb4ee6a4SAndroid Build Coastguard Worker             .resize_with(snapshot.irq_gsi_vec.len(), || None::<IrqfdGsi>);
279*bb4ee6a4SAndroid Build Coastguard Worker         for (vector, gsi) in snapshot.irq_gsi_vec.iter().enumerate() {
280*bb4ee6a4SAndroid Build Coastguard Worker             if let Some(gsi_num) = gsi {
281*bb4ee6a4SAndroid Build Coastguard Worker                 self.msix_restore_one(vector, *gsi_num)?;
282*bb4ee6a4SAndroid Build Coastguard Worker             } else {
283*bb4ee6a4SAndroid Build Coastguard Worker                 info!(
284*bb4ee6a4SAndroid Build Coastguard Worker                     "skipping restore of vector {} for device {}",
285*bb4ee6a4SAndroid Build Coastguard Worker                     vector, self.device_name
286*bb4ee6a4SAndroid Build Coastguard Worker                 );
287*bb4ee6a4SAndroid Build Coastguard Worker             }
288*bb4ee6a4SAndroid Build Coastguard Worker         }
289*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
290*bb4ee6a4SAndroid Build Coastguard Worker     }
291*bb4ee6a4SAndroid Build Coastguard Worker 
292*bb4ee6a4SAndroid Build Coastguard Worker     /// Restore the specified MSI-X vector.
293*bb4ee6a4SAndroid Build Coastguard Worker     ///
294*bb4ee6a4SAndroid Build Coastguard Worker     /// Note: we skip the checks from [MsixConfig::msix_enable_one] because for
295*bb4ee6a4SAndroid Build Coastguard Worker     /// an interrupt to be present in [MsixConfigSnapshot::irq_gsi_vec], it must
296*bb4ee6a4SAndroid Build Coastguard Worker     /// have passed those checks.
msix_restore_one(&mut self, index: usize, gsi: u32) -> MsixResult<()>297*bb4ee6a4SAndroid Build Coastguard Worker     fn msix_restore_one(&mut self, index: usize, gsi: u32) -> MsixResult<()> {
298*bb4ee6a4SAndroid Build Coastguard Worker         let irqfd = Event::new().map_err(MsixError::AllocateOneMsi)?;
299*bb4ee6a4SAndroid Build Coastguard Worker         let request = VmIrqRequest::AllocateOneMsiAtGsi {
300*bb4ee6a4SAndroid Build Coastguard Worker             irqfd,
301*bb4ee6a4SAndroid Build Coastguard Worker             gsi,
302*bb4ee6a4SAndroid Build Coastguard Worker             device_id: self.pci_id,
303*bb4ee6a4SAndroid Build Coastguard Worker             queue_id: index,
304*bb4ee6a4SAndroid Build Coastguard Worker             device_name: self.device_name.clone(),
305*bb4ee6a4SAndroid Build Coastguard Worker         };
306*bb4ee6a4SAndroid Build Coastguard Worker         self.msi_device_socket
307*bb4ee6a4SAndroid Build Coastguard Worker             .send(&request)
308*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(MsixError::AllocateOneMsiSend)?;
309*bb4ee6a4SAndroid Build Coastguard Worker         if let VmIrqResponse::Err(e) = self
310*bb4ee6a4SAndroid Build Coastguard Worker             .msi_device_socket
311*bb4ee6a4SAndroid Build Coastguard Worker             .recv()
312*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(MsixError::AllocateOneMsiRecv)?
313*bb4ee6a4SAndroid Build Coastguard Worker         {
314*bb4ee6a4SAndroid Build Coastguard Worker             return Err(MsixError::AllocateOneMsi(e));
315*bb4ee6a4SAndroid Build Coastguard Worker         };
316*bb4ee6a4SAndroid Build Coastguard Worker 
317*bb4ee6a4SAndroid Build Coastguard Worker         self.irq_vec[index] = Some(IrqfdGsi {
318*bb4ee6a4SAndroid Build Coastguard Worker             irqfd: match request {
319*bb4ee6a4SAndroid Build Coastguard Worker                 VmIrqRequest::AllocateOneMsiAtGsi { irqfd, .. } => irqfd,
320*bb4ee6a4SAndroid Build Coastguard Worker                 _ => unreachable!(),
321*bb4ee6a4SAndroid Build Coastguard Worker             },
322*bb4ee6a4SAndroid Build Coastguard Worker             gsi,
323*bb4ee6a4SAndroid Build Coastguard Worker         });
324*bb4ee6a4SAndroid Build Coastguard Worker         self.add_msi_route(index as u16, gsi)?;
325*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
326*bb4ee6a4SAndroid Build Coastguard Worker     }
327*bb4ee6a4SAndroid Build Coastguard Worker 
328*bb4ee6a4SAndroid Build Coastguard Worker     /// On warm restore, there could already be MSIs registered. We need to
329*bb4ee6a4SAndroid Build Coastguard Worker     /// release them in case the routing has changed (e.g. different
330*bb4ee6a4SAndroid Build Coastguard Worker     /// data <-> GSI).
msix_release_all(&mut self) -> MsixResult<()>331*bb4ee6a4SAndroid Build Coastguard Worker     fn msix_release_all(&mut self) -> MsixResult<()> {
332*bb4ee6a4SAndroid Build Coastguard Worker         for irqfd_gsi in self.irq_vec.drain(..).flatten() {
333*bb4ee6a4SAndroid Build Coastguard Worker             let request = VmIrqRequest::ReleaseOneIrq {
334*bb4ee6a4SAndroid Build Coastguard Worker                 gsi: irqfd_gsi.gsi,
335*bb4ee6a4SAndroid Build Coastguard Worker                 irqfd: irqfd_gsi.irqfd,
336*bb4ee6a4SAndroid Build Coastguard Worker             };
337*bb4ee6a4SAndroid Build Coastguard Worker 
338*bb4ee6a4SAndroid Build Coastguard Worker             self.msi_device_socket
339*bb4ee6a4SAndroid Build Coastguard Worker                 .send(&request)
340*bb4ee6a4SAndroid Build Coastguard Worker                 .map_err(MsixError::ReleaseOneIrqSend)?;
341*bb4ee6a4SAndroid Build Coastguard Worker             if let VmIrqResponse::Err(e) = self
342*bb4ee6a4SAndroid Build Coastguard Worker                 .msi_device_socket
343*bb4ee6a4SAndroid Build Coastguard Worker                 .recv()
344*bb4ee6a4SAndroid Build Coastguard Worker                 .map_err(MsixError::ReleaseOneIrqRecv)?
345*bb4ee6a4SAndroid Build Coastguard Worker             {
346*bb4ee6a4SAndroid Build Coastguard Worker                 return Err(MsixError::ReleaseOneIrq(e));
347*bb4ee6a4SAndroid Build Coastguard Worker             }
348*bb4ee6a4SAndroid Build Coastguard Worker         }
349*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
350*bb4ee6a4SAndroid Build Coastguard Worker     }
351*bb4ee6a4SAndroid Build Coastguard Worker 
add_msi_route(&mut self, index: u16, gsi: u32) -> MsixResult<()>352*bb4ee6a4SAndroid Build Coastguard Worker     fn add_msi_route(&mut self, index: u16, gsi: u32) -> MsixResult<()> {
353*bb4ee6a4SAndroid Build Coastguard Worker         let mut data: [u8; 8] = [0, 0, 0, 0, 0, 0, 0, 0];
354*bb4ee6a4SAndroid Build Coastguard Worker         self.read_msix_table((index * 16).into(), data.as_mut());
355*bb4ee6a4SAndroid Build Coastguard Worker         let msi_address: u64 = u64::from_le_bytes(data);
356*bb4ee6a4SAndroid Build Coastguard Worker         let mut data: [u8; 4] = [0, 0, 0, 0];
357*bb4ee6a4SAndroid Build Coastguard Worker         self.read_msix_table((index * 16 + 8).into(), data.as_mut());
358*bb4ee6a4SAndroid Build Coastguard Worker         let msi_data: u32 = u32::from_le_bytes(data);
359*bb4ee6a4SAndroid Build Coastguard Worker 
360*bb4ee6a4SAndroid Build Coastguard Worker         if msi_address == 0 {
361*bb4ee6a4SAndroid Build Coastguard Worker             return Ok(());
362*bb4ee6a4SAndroid Build Coastguard Worker         }
363*bb4ee6a4SAndroid Build Coastguard Worker 
364*bb4ee6a4SAndroid Build Coastguard Worker         self.msi_device_socket
365*bb4ee6a4SAndroid Build Coastguard Worker             .send(&VmIrqRequest::AddMsiRoute {
366*bb4ee6a4SAndroid Build Coastguard Worker                 gsi,
367*bb4ee6a4SAndroid Build Coastguard Worker                 msi_address,
368*bb4ee6a4SAndroid Build Coastguard Worker                 msi_data,
369*bb4ee6a4SAndroid Build Coastguard Worker             })
370*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(MsixError::AddMsiRouteSend)?;
371*bb4ee6a4SAndroid Build Coastguard Worker         if let VmIrqResponse::Err(e) = self
372*bb4ee6a4SAndroid Build Coastguard Worker             .msi_device_socket
373*bb4ee6a4SAndroid Build Coastguard Worker             .recv()
374*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(MsixError::AddMsiRouteRecv)?
375*bb4ee6a4SAndroid Build Coastguard Worker         {
376*bb4ee6a4SAndroid Build Coastguard Worker             return Err(MsixError::AddMsiRoute(e));
377*bb4ee6a4SAndroid Build Coastguard Worker         }
378*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
379*bb4ee6a4SAndroid Build Coastguard Worker     }
380*bb4ee6a4SAndroid Build Coastguard Worker 
381*bb4ee6a4SAndroid Build Coastguard Worker     // Enable MSI-X
msix_enable_all(&mut self) -> MsixResult<()>382*bb4ee6a4SAndroid Build Coastguard Worker     fn msix_enable_all(&mut self) -> MsixResult<()> {
383*bb4ee6a4SAndroid Build Coastguard Worker         for index in 0..self.irq_vec.len() {
384*bb4ee6a4SAndroid Build Coastguard Worker             self.msix_enable_one(index)?;
385*bb4ee6a4SAndroid Build Coastguard Worker         }
386*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
387*bb4ee6a4SAndroid Build Coastguard Worker     }
388*bb4ee6a4SAndroid Build Coastguard Worker 
389*bb4ee6a4SAndroid Build Coastguard Worker     // Use a new MSI-X vector
390*bb4ee6a4SAndroid Build Coastguard Worker     // Create a new eventfd and bind them to a new msi
msix_enable_one(&mut self, index: usize) -> MsixResult<()>391*bb4ee6a4SAndroid Build Coastguard Worker     fn msix_enable_one(&mut self, index: usize) -> MsixResult<()> {
392*bb4ee6a4SAndroid Build Coastguard Worker         if self.irq_vec[index].is_some()
393*bb4ee6a4SAndroid Build Coastguard Worker             || !self.enabled()
394*bb4ee6a4SAndroid Build Coastguard Worker             || self.masked()
395*bb4ee6a4SAndroid Build Coastguard Worker             || self.table_masked(index)
396*bb4ee6a4SAndroid Build Coastguard Worker         {
397*bb4ee6a4SAndroid Build Coastguard Worker             return Ok(());
398*bb4ee6a4SAndroid Build Coastguard Worker         }
399*bb4ee6a4SAndroid Build Coastguard Worker         let irqfd = Event::new().map_err(MsixError::AllocateOneMsi)?;
400*bb4ee6a4SAndroid Build Coastguard Worker         let request = VmIrqRequest::AllocateOneMsi {
401*bb4ee6a4SAndroid Build Coastguard Worker             irqfd,
402*bb4ee6a4SAndroid Build Coastguard Worker             device_id: self.pci_id,
403*bb4ee6a4SAndroid Build Coastguard Worker             queue_id: index,
404*bb4ee6a4SAndroid Build Coastguard Worker             device_name: self.device_name.clone(),
405*bb4ee6a4SAndroid Build Coastguard Worker         };
406*bb4ee6a4SAndroid Build Coastguard Worker         self.msi_device_socket
407*bb4ee6a4SAndroid Build Coastguard Worker             .send(&request)
408*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(MsixError::AllocateOneMsiSend)?;
409*bb4ee6a4SAndroid Build Coastguard Worker         let irq_num: u32 = match self
410*bb4ee6a4SAndroid Build Coastguard Worker             .msi_device_socket
411*bb4ee6a4SAndroid Build Coastguard Worker             .recv()
412*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(MsixError::AllocateOneMsiRecv)?
413*bb4ee6a4SAndroid Build Coastguard Worker         {
414*bb4ee6a4SAndroid Build Coastguard Worker             VmIrqResponse::AllocateOneMsi { gsi } => gsi,
415*bb4ee6a4SAndroid Build Coastguard Worker             VmIrqResponse::Err(e) => return Err(MsixError::AllocateOneMsi(e)),
416*bb4ee6a4SAndroid Build Coastguard Worker             _ => unreachable!(),
417*bb4ee6a4SAndroid Build Coastguard Worker         };
418*bb4ee6a4SAndroid Build Coastguard Worker         self.irq_vec[index] = Some(IrqfdGsi {
419*bb4ee6a4SAndroid Build Coastguard Worker             irqfd: match request {
420*bb4ee6a4SAndroid Build Coastguard Worker                 VmIrqRequest::AllocateOneMsi { irqfd, .. } => irqfd,
421*bb4ee6a4SAndroid Build Coastguard Worker                 _ => unreachable!(),
422*bb4ee6a4SAndroid Build Coastguard Worker             },
423*bb4ee6a4SAndroid Build Coastguard Worker             gsi: irq_num,
424*bb4ee6a4SAndroid Build Coastguard Worker         });
425*bb4ee6a4SAndroid Build Coastguard Worker 
426*bb4ee6a4SAndroid Build Coastguard Worker         self.add_msi_route(index as u16, irq_num)?;
427*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
428*bb4ee6a4SAndroid Build Coastguard Worker     }
429*bb4ee6a4SAndroid Build Coastguard Worker 
430*bb4ee6a4SAndroid Build Coastguard Worker     /// Read MSI-X table
431*bb4ee6a4SAndroid Build Coastguard Worker     ///  # Arguments
432*bb4ee6a4SAndroid Build Coastguard Worker     ///  * 'offset' - the offset within the MSI-X Table
433*bb4ee6a4SAndroid Build Coastguard Worker     ///  * 'data' - used to store the read results
434*bb4ee6a4SAndroid Build Coastguard Worker     ///
435*bb4ee6a4SAndroid Build Coastguard Worker     /// For all accesses to MSI-X Table and MSI-X PBA fields, software must use aligned full
436*bb4ee6a4SAndroid Build Coastguard Worker     /// DWORD or aligned full QWORD transactions; otherwise, the result is undefined.
437*bb4ee6a4SAndroid Build Coastguard Worker     ///
438*bb4ee6a4SAndroid Build Coastguard Worker     ///   location: DWORD3            DWORD2      DWORD1            DWORD0
439*bb4ee6a4SAndroid Build Coastguard Worker     ///   entry 0:  Vector Control    Msg Data    Msg Upper Addr    Msg Addr
440*bb4ee6a4SAndroid Build Coastguard Worker     ///   entry 1:  Vector Control    Msg Data    Msg Upper Addr    Msg Addr
441*bb4ee6a4SAndroid Build Coastguard Worker     ///   entry 2:  Vector Control    Msg Data    Msg Upper Addr    Msg Addr
442*bb4ee6a4SAndroid Build Coastguard Worker     ///   ...
read_msix_table(&self, offset: u64, data: &mut [u8])443*bb4ee6a4SAndroid Build Coastguard Worker     pub fn read_msix_table(&self, offset: u64, data: &mut [u8]) {
444*bb4ee6a4SAndroid Build Coastguard Worker         let index: usize = (offset / MSIX_TABLE_ENTRIES_MODULO) as usize;
445*bb4ee6a4SAndroid Build Coastguard Worker         let modulo_offset = offset % MSIX_TABLE_ENTRIES_MODULO;
446*bb4ee6a4SAndroid Build Coastguard Worker 
447*bb4ee6a4SAndroid Build Coastguard Worker         match data.len() {
448*bb4ee6a4SAndroid Build Coastguard Worker             4 => {
449*bb4ee6a4SAndroid Build Coastguard Worker                 let value = match modulo_offset {
450*bb4ee6a4SAndroid Build Coastguard Worker                     0x0 => self.table_entries[index].msg_addr_lo,
451*bb4ee6a4SAndroid Build Coastguard Worker                     0x4 => self.table_entries[index].msg_addr_hi,
452*bb4ee6a4SAndroid Build Coastguard Worker                     0x8 => self.table_entries[index].msg_data,
453*bb4ee6a4SAndroid Build Coastguard Worker                     0xc => self.table_entries[index].vector_ctl,
454*bb4ee6a4SAndroid Build Coastguard Worker                     _ => {
455*bb4ee6a4SAndroid Build Coastguard Worker                         error!("invalid offset");
456*bb4ee6a4SAndroid Build Coastguard Worker                         0
457*bb4ee6a4SAndroid Build Coastguard Worker                     }
458*bb4ee6a4SAndroid Build Coastguard Worker                 };
459*bb4ee6a4SAndroid Build Coastguard Worker 
460*bb4ee6a4SAndroid Build Coastguard Worker                 data.copy_from_slice(&value.to_le_bytes());
461*bb4ee6a4SAndroid Build Coastguard Worker             }
462*bb4ee6a4SAndroid Build Coastguard Worker             8 => {
463*bb4ee6a4SAndroid Build Coastguard Worker                 let value = match modulo_offset {
464*bb4ee6a4SAndroid Build Coastguard Worker                     0x0 => {
465*bb4ee6a4SAndroid Build Coastguard Worker                         (u64::from(self.table_entries[index].msg_addr_hi) << 32)
466*bb4ee6a4SAndroid Build Coastguard Worker                             | u64::from(self.table_entries[index].msg_addr_lo)
467*bb4ee6a4SAndroid Build Coastguard Worker                     }
468*bb4ee6a4SAndroid Build Coastguard Worker                     0x8 => {
469*bb4ee6a4SAndroid Build Coastguard Worker                         (u64::from(self.table_entries[index].vector_ctl) << 32)
470*bb4ee6a4SAndroid Build Coastguard Worker                             | u64::from(self.table_entries[index].msg_data)
471*bb4ee6a4SAndroid Build Coastguard Worker                     }
472*bb4ee6a4SAndroid Build Coastguard Worker                     _ => {
473*bb4ee6a4SAndroid Build Coastguard Worker                         error!("invalid offset");
474*bb4ee6a4SAndroid Build Coastguard Worker                         0
475*bb4ee6a4SAndroid Build Coastguard Worker                     }
476*bb4ee6a4SAndroid Build Coastguard Worker                 };
477*bb4ee6a4SAndroid Build Coastguard Worker 
478*bb4ee6a4SAndroid Build Coastguard Worker                 data.copy_from_slice(&value.to_le_bytes());
479*bb4ee6a4SAndroid Build Coastguard Worker             }
480*bb4ee6a4SAndroid Build Coastguard Worker             _ => error!("invalid data length"),
481*bb4ee6a4SAndroid Build Coastguard Worker         };
482*bb4ee6a4SAndroid Build Coastguard Worker     }
483*bb4ee6a4SAndroid Build Coastguard Worker 
484*bb4ee6a4SAndroid Build Coastguard Worker     /// Write to MSI-X table
485*bb4ee6a4SAndroid Build Coastguard Worker     ///
486*bb4ee6a4SAndroid Build Coastguard Worker     /// Message Address: the contents of this field specifies the address
487*bb4ee6a4SAndroid Build Coastguard Worker     ///     for the memory write transaction; different MSI-X vectors have
488*bb4ee6a4SAndroid Build Coastguard Worker     ///     different Message Address values
489*bb4ee6a4SAndroid Build Coastguard Worker     /// Message Data: the contents of this field specifies the data driven
490*bb4ee6a4SAndroid Build Coastguard Worker     ///     on AD\[31::00\] during the memory write transaction's data phase.
491*bb4ee6a4SAndroid Build Coastguard Worker     /// Vector Control: only bit 0 (Mask Bit) is not reserved: when this bit
492*bb4ee6a4SAndroid Build Coastguard Worker     ///     is set, the function is prohibited from sending a message using
493*bb4ee6a4SAndroid Build Coastguard Worker     ///     this MSI-X Table entry.
write_msix_table(&mut self, offset: u64, data: &[u8]) -> MsixStatus494*bb4ee6a4SAndroid Build Coastguard Worker     pub fn write_msix_table(&mut self, offset: u64, data: &[u8]) -> MsixStatus {
495*bb4ee6a4SAndroid Build Coastguard Worker         let index: usize = (offset / MSIX_TABLE_ENTRIES_MODULO) as usize;
496*bb4ee6a4SAndroid Build Coastguard Worker         let modulo_offset = offset % MSIX_TABLE_ENTRIES_MODULO;
497*bb4ee6a4SAndroid Build Coastguard Worker 
498*bb4ee6a4SAndroid Build Coastguard Worker         // Store the value of the entry before modification
499*bb4ee6a4SAndroid Build Coastguard Worker         let old_entry = self.table_entries[index].clone();
500*bb4ee6a4SAndroid Build Coastguard Worker 
501*bb4ee6a4SAndroid Build Coastguard Worker         match data.len() {
502*bb4ee6a4SAndroid Build Coastguard Worker             4 => {
503*bb4ee6a4SAndroid Build Coastguard Worker                 let value = u32::from_le_bytes(data.try_into().unwrap());
504*bb4ee6a4SAndroid Build Coastguard Worker                 match modulo_offset {
505*bb4ee6a4SAndroid Build Coastguard Worker                     0x0 => self.table_entries[index].msg_addr_lo = value,
506*bb4ee6a4SAndroid Build Coastguard Worker                     0x4 => self.table_entries[index].msg_addr_hi = value,
507*bb4ee6a4SAndroid Build Coastguard Worker                     0x8 => self.table_entries[index].msg_data = value,
508*bb4ee6a4SAndroid Build Coastguard Worker                     0xc => self.table_entries[index].vector_ctl = value,
509*bb4ee6a4SAndroid Build Coastguard Worker                     _ => error!("invalid offset"),
510*bb4ee6a4SAndroid Build Coastguard Worker                 };
511*bb4ee6a4SAndroid Build Coastguard Worker             }
512*bb4ee6a4SAndroid Build Coastguard Worker             8 => {
513*bb4ee6a4SAndroid Build Coastguard Worker                 let value = u64::from_le_bytes(data.try_into().unwrap());
514*bb4ee6a4SAndroid Build Coastguard Worker                 match modulo_offset {
515*bb4ee6a4SAndroid Build Coastguard Worker                     0x0 => {
516*bb4ee6a4SAndroid Build Coastguard Worker                         self.table_entries[index].msg_addr_lo = (value & 0xffff_ffffu64) as u32;
517*bb4ee6a4SAndroid Build Coastguard Worker                         self.table_entries[index].msg_addr_hi = (value >> 32) as u32;
518*bb4ee6a4SAndroid Build Coastguard Worker                     }
519*bb4ee6a4SAndroid Build Coastguard Worker                     0x8 => {
520*bb4ee6a4SAndroid Build Coastguard Worker                         self.table_entries[index].msg_data = (value & 0xffff_ffffu64) as u32;
521*bb4ee6a4SAndroid Build Coastguard Worker                         self.table_entries[index].vector_ctl = (value >> 32) as u32;
522*bb4ee6a4SAndroid Build Coastguard Worker                     }
523*bb4ee6a4SAndroid Build Coastguard Worker                     _ => error!("invalid offset"),
524*bb4ee6a4SAndroid Build Coastguard Worker                 };
525*bb4ee6a4SAndroid Build Coastguard Worker             }
526*bb4ee6a4SAndroid Build Coastguard Worker             _ => error!("invalid data length"),
527*bb4ee6a4SAndroid Build Coastguard Worker         };
528*bb4ee6a4SAndroid Build Coastguard Worker 
529*bb4ee6a4SAndroid Build Coastguard Worker         let new_entry = self.table_entries[index].clone();
530*bb4ee6a4SAndroid Build Coastguard Worker 
531*bb4ee6a4SAndroid Build Coastguard Worker         // This MSI-X vector is enabled for the first time.
532*bb4ee6a4SAndroid Build Coastguard Worker         if self.enabled()
533*bb4ee6a4SAndroid Build Coastguard Worker             && !self.masked()
534*bb4ee6a4SAndroid Build Coastguard Worker             && self.irq_vec[index].is_none()
535*bb4ee6a4SAndroid Build Coastguard Worker             && old_entry.masked()
536*bb4ee6a4SAndroid Build Coastguard Worker             && !new_entry.masked()
537*bb4ee6a4SAndroid Build Coastguard Worker         {
538*bb4ee6a4SAndroid Build Coastguard Worker             if let Err(e) = self.msix_enable_one(index) {
539*bb4ee6a4SAndroid Build Coastguard Worker                 error!("failed to enable MSI-X vector {}: {}", index, e);
540*bb4ee6a4SAndroid Build Coastguard Worker                 self.table_entries[index].vector_ctl |= MSIX_TABLE_ENTRY_MASK_BIT;
541*bb4ee6a4SAndroid Build Coastguard Worker             }
542*bb4ee6a4SAndroid Build Coastguard Worker             return MsixStatus::EntryChanged(index);
543*bb4ee6a4SAndroid Build Coastguard Worker         }
544*bb4ee6a4SAndroid Build Coastguard Worker 
545*bb4ee6a4SAndroid Build Coastguard Worker         if self.enabled()
546*bb4ee6a4SAndroid Build Coastguard Worker             && (old_entry.msg_addr_lo != new_entry.msg_addr_lo
547*bb4ee6a4SAndroid Build Coastguard Worker                 || old_entry.msg_addr_hi != new_entry.msg_addr_hi
548*bb4ee6a4SAndroid Build Coastguard Worker                 || old_entry.msg_data != new_entry.msg_data)
549*bb4ee6a4SAndroid Build Coastguard Worker         {
550*bb4ee6a4SAndroid Build Coastguard Worker             if let Some(irqfd_gsi) = &self.irq_vec[index] {
551*bb4ee6a4SAndroid Build Coastguard Worker                 let irq_num = irqfd_gsi.gsi;
552*bb4ee6a4SAndroid Build Coastguard Worker                 if let Err(e) = self.add_msi_route(index as u16, irq_num) {
553*bb4ee6a4SAndroid Build Coastguard Worker                     error!("add_msi_route failed: {}", e);
554*bb4ee6a4SAndroid Build Coastguard Worker                 }
555*bb4ee6a4SAndroid Build Coastguard Worker             }
556*bb4ee6a4SAndroid Build Coastguard Worker         }
557*bb4ee6a4SAndroid Build Coastguard Worker 
558*bb4ee6a4SAndroid Build Coastguard Worker         // After the MSI-X table entry has been updated, it is necessary to
559*bb4ee6a4SAndroid Build Coastguard Worker         // check if the vector control masking bit has changed. In case the
560*bb4ee6a4SAndroid Build Coastguard Worker         // bit has been flipped from 1 to 0, we need to inject a MSI message
561*bb4ee6a4SAndroid Build Coastguard Worker         // if the corresponding pending bit from the PBA is set. Once the MSI
562*bb4ee6a4SAndroid Build Coastguard Worker         // has been injected, the pending bit in the PBA needs to be cleared.
563*bb4ee6a4SAndroid Build Coastguard Worker         // All of this is valid only if MSI-X has not been masked for the whole
564*bb4ee6a4SAndroid Build Coastguard Worker         // device.
565*bb4ee6a4SAndroid Build Coastguard Worker 
566*bb4ee6a4SAndroid Build Coastguard Worker         // Check if bit has been flipped
567*bb4ee6a4SAndroid Build Coastguard Worker         if !self.masked() {
568*bb4ee6a4SAndroid Build Coastguard Worker             if old_entry.masked() && !self.table_entries[index].masked() {
569*bb4ee6a4SAndroid Build Coastguard Worker                 if self.get_pba_bit(index as u16) == 1 {
570*bb4ee6a4SAndroid Build Coastguard Worker                     self.inject_msix_and_clear_pba(index);
571*bb4ee6a4SAndroid Build Coastguard Worker                 }
572*bb4ee6a4SAndroid Build Coastguard Worker                 return MsixStatus::EntryChanged(index);
573*bb4ee6a4SAndroid Build Coastguard Worker             } else if !old_entry.masked() && self.table_entries[index].masked() {
574*bb4ee6a4SAndroid Build Coastguard Worker                 return MsixStatus::EntryChanged(index);
575*bb4ee6a4SAndroid Build Coastguard Worker             }
576*bb4ee6a4SAndroid Build Coastguard Worker         }
577*bb4ee6a4SAndroid Build Coastguard Worker         MsixStatus::NothingToDo
578*bb4ee6a4SAndroid Build Coastguard Worker     }
579*bb4ee6a4SAndroid Build Coastguard Worker 
580*bb4ee6a4SAndroid Build Coastguard Worker     /// Read PBA Entries
581*bb4ee6a4SAndroid Build Coastguard Worker     ///  # Arguments
582*bb4ee6a4SAndroid Build Coastguard Worker     ///  * 'offset' - the offset within the PBA entries
583*bb4ee6a4SAndroid Build Coastguard Worker     ///  * 'data' - used to store the read results
584*bb4ee6a4SAndroid Build Coastguard Worker     ///
585*bb4ee6a4SAndroid Build Coastguard Worker     /// Pending Bits\[63::00\]: For each Pending Bit that is set, the function
586*bb4ee6a4SAndroid Build Coastguard Worker     /// has a pending message for the associated MSI-X Table entry.
read_pba_entries(&self, offset: u64, data: &mut [u8])587*bb4ee6a4SAndroid Build Coastguard Worker     pub fn read_pba_entries(&self, offset: u64, data: &mut [u8]) {
588*bb4ee6a4SAndroid Build Coastguard Worker         let index: usize = (offset / MSIX_PBA_ENTRIES_MODULO) as usize;
589*bb4ee6a4SAndroid Build Coastguard Worker         let modulo_offset = offset % MSIX_PBA_ENTRIES_MODULO;
590*bb4ee6a4SAndroid Build Coastguard Worker 
591*bb4ee6a4SAndroid Build Coastguard Worker         match data.len() {
592*bb4ee6a4SAndroid Build Coastguard Worker             4 => {
593*bb4ee6a4SAndroid Build Coastguard Worker                 let value: u32 = match modulo_offset {
594*bb4ee6a4SAndroid Build Coastguard Worker                     0x0 => (self.pba_entries[index] & 0xffff_ffffu64) as u32,
595*bb4ee6a4SAndroid Build Coastguard Worker                     0x4 => (self.pba_entries[index] >> 32) as u32,
596*bb4ee6a4SAndroid Build Coastguard Worker                     _ => {
597*bb4ee6a4SAndroid Build Coastguard Worker                         error!("invalid offset");
598*bb4ee6a4SAndroid Build Coastguard Worker                         0
599*bb4ee6a4SAndroid Build Coastguard Worker                     }
600*bb4ee6a4SAndroid Build Coastguard Worker                 };
601*bb4ee6a4SAndroid Build Coastguard Worker 
602*bb4ee6a4SAndroid Build Coastguard Worker                 data.copy_from_slice(&value.to_le_bytes());
603*bb4ee6a4SAndroid Build Coastguard Worker             }
604*bb4ee6a4SAndroid Build Coastguard Worker             8 => {
605*bb4ee6a4SAndroid Build Coastguard Worker                 let value: u64 = match modulo_offset {
606*bb4ee6a4SAndroid Build Coastguard Worker                     0x0 => self.pba_entries[index],
607*bb4ee6a4SAndroid Build Coastguard Worker                     _ => {
608*bb4ee6a4SAndroid Build Coastguard Worker                         error!("invalid offset");
609*bb4ee6a4SAndroid Build Coastguard Worker                         0
610*bb4ee6a4SAndroid Build Coastguard Worker                     }
611*bb4ee6a4SAndroid Build Coastguard Worker                 };
612*bb4ee6a4SAndroid Build Coastguard Worker 
613*bb4ee6a4SAndroid Build Coastguard Worker                 data.copy_from_slice(&value.to_le_bytes());
614*bb4ee6a4SAndroid Build Coastguard Worker             }
615*bb4ee6a4SAndroid Build Coastguard Worker             _ => error!("invalid data length"),
616*bb4ee6a4SAndroid Build Coastguard Worker         }
617*bb4ee6a4SAndroid Build Coastguard Worker     }
618*bb4ee6a4SAndroid Build Coastguard Worker 
619*bb4ee6a4SAndroid Build Coastguard Worker     /// Write to PBA Entries
620*bb4ee6a4SAndroid Build Coastguard Worker     ///
621*bb4ee6a4SAndroid Build Coastguard Worker     /// Software should never write, and should only read Pending Bits.
622*bb4ee6a4SAndroid Build Coastguard Worker     /// If software writes to Pending Bits, the result is undefined.
write_pba_entries(&mut self, _offset: u64, _data: &[u8])623*bb4ee6a4SAndroid Build Coastguard Worker     pub fn write_pba_entries(&mut self, _offset: u64, _data: &[u8]) {
624*bb4ee6a4SAndroid Build Coastguard Worker         error!("Pending Bit Array is read only");
625*bb4ee6a4SAndroid Build Coastguard Worker     }
626*bb4ee6a4SAndroid Build Coastguard Worker 
set_pba_bit(&mut self, vector: u16, set: bool)627*bb4ee6a4SAndroid Build Coastguard Worker     fn set_pba_bit(&mut self, vector: u16, set: bool) {
628*bb4ee6a4SAndroid Build Coastguard Worker         assert!(vector < MAX_MSIX_VECTORS_PER_DEVICE);
629*bb4ee6a4SAndroid Build Coastguard Worker 
630*bb4ee6a4SAndroid Build Coastguard Worker         let index: usize = (vector as usize) / BITS_PER_PBA_ENTRY;
631*bb4ee6a4SAndroid Build Coastguard Worker         let shift: usize = (vector as usize) % BITS_PER_PBA_ENTRY;
632*bb4ee6a4SAndroid Build Coastguard Worker         let mut mask: u64 = (1 << shift) as u64;
633*bb4ee6a4SAndroid Build Coastguard Worker 
634*bb4ee6a4SAndroid Build Coastguard Worker         if set {
635*bb4ee6a4SAndroid Build Coastguard Worker             self.pba_entries[index] |= mask;
636*bb4ee6a4SAndroid Build Coastguard Worker         } else {
637*bb4ee6a4SAndroid Build Coastguard Worker             mask = !mask;
638*bb4ee6a4SAndroid Build Coastguard Worker             self.pba_entries[index] &= mask;
639*bb4ee6a4SAndroid Build Coastguard Worker         }
640*bb4ee6a4SAndroid Build Coastguard Worker     }
641*bb4ee6a4SAndroid Build Coastguard Worker 
get_pba_bit(&self, vector: u16) -> u8642*bb4ee6a4SAndroid Build Coastguard Worker     fn get_pba_bit(&self, vector: u16) -> u8 {
643*bb4ee6a4SAndroid Build Coastguard Worker         assert!(vector < MAX_MSIX_VECTORS_PER_DEVICE);
644*bb4ee6a4SAndroid Build Coastguard Worker 
645*bb4ee6a4SAndroid Build Coastguard Worker         let index: usize = (vector as usize) / BITS_PER_PBA_ENTRY;
646*bb4ee6a4SAndroid Build Coastguard Worker         let shift: usize = (vector as usize) % BITS_PER_PBA_ENTRY;
647*bb4ee6a4SAndroid Build Coastguard Worker 
648*bb4ee6a4SAndroid Build Coastguard Worker         ((self.pba_entries[index] >> shift) & 0x0000_0001u64) as u8
649*bb4ee6a4SAndroid Build Coastguard Worker     }
650*bb4ee6a4SAndroid Build Coastguard Worker 
inject_msix_and_clear_pba(&mut self, vector: usize)651*bb4ee6a4SAndroid Build Coastguard Worker     fn inject_msix_and_clear_pba(&mut self, vector: usize) {
652*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(irq) = &self.irq_vec[vector] {
653*bb4ee6a4SAndroid Build Coastguard Worker             irq.irqfd.signal().unwrap();
654*bb4ee6a4SAndroid Build Coastguard Worker         }
655*bb4ee6a4SAndroid Build Coastguard Worker 
656*bb4ee6a4SAndroid Build Coastguard Worker         // Clear the bit from PBA
657*bb4ee6a4SAndroid Build Coastguard Worker         self.set_pba_bit(vector as u16, false);
658*bb4ee6a4SAndroid Build Coastguard Worker     }
659*bb4ee6a4SAndroid Build Coastguard Worker 
660*bb4ee6a4SAndroid Build Coastguard Worker     /// Inject virtual interrupt to the guest
661*bb4ee6a4SAndroid Build Coastguard Worker     ///
662*bb4ee6a4SAndroid Build Coastguard Worker     ///  # Arguments
663*bb4ee6a4SAndroid Build Coastguard Worker     ///  * 'vector' - the index to the MSI-X Table entry
664*bb4ee6a4SAndroid Build Coastguard Worker     ///
665*bb4ee6a4SAndroid Build Coastguard Worker     /// PCI Spec 3.0 6.8.3.5: while a vector is masked, the function is
666*bb4ee6a4SAndroid Build Coastguard Worker     /// prohibited from sending the associated message, and the function
667*bb4ee6a4SAndroid Build Coastguard Worker     /// must set the associated Pending bit whenever the function would
668*bb4ee6a4SAndroid Build Coastguard Worker     /// otherwise send the message. When software unmasks a vector whose
669*bb4ee6a4SAndroid Build Coastguard Worker     /// associated Pending bit is set, the function must schedule sending
670*bb4ee6a4SAndroid Build Coastguard Worker     /// the associated message, and clear the Pending bit as soon as the
671*bb4ee6a4SAndroid Build Coastguard Worker     /// message has been sent.
672*bb4ee6a4SAndroid Build Coastguard Worker     ///
673*bb4ee6a4SAndroid Build Coastguard Worker     /// If the vector is unmasked, writing to irqfd which wakes up KVM to
674*bb4ee6a4SAndroid Build Coastguard Worker     /// inject virtual interrupt to the guest.
trigger(&mut self, vector: u16)675*bb4ee6a4SAndroid Build Coastguard Worker     pub fn trigger(&mut self, vector: u16) {
676*bb4ee6a4SAndroid Build Coastguard Worker         if self.table_entries[vector as usize].masked() || self.masked() {
677*bb4ee6a4SAndroid Build Coastguard Worker             self.set_pba_bit(vector, true);
678*bb4ee6a4SAndroid Build Coastguard Worker         } else if let Some(irq) = self.irq_vec.get(vector as usize).unwrap_or(&None) {
679*bb4ee6a4SAndroid Build Coastguard Worker             irq.irqfd.signal().unwrap();
680*bb4ee6a4SAndroid Build Coastguard Worker         }
681*bb4ee6a4SAndroid Build Coastguard Worker     }
682*bb4ee6a4SAndroid Build Coastguard Worker 
683*bb4ee6a4SAndroid Build Coastguard Worker     /// Return the raw descriptor of the MSI device socket
get_msi_socket(&self) -> RawDescriptor684*bb4ee6a4SAndroid Build Coastguard Worker     pub fn get_msi_socket(&self) -> RawDescriptor {
685*bb4ee6a4SAndroid Build Coastguard Worker         self.msi_device_socket.as_raw_descriptor()
686*bb4ee6a4SAndroid Build Coastguard Worker     }
687*bb4ee6a4SAndroid Build Coastguard Worker 
688*bb4ee6a4SAndroid Build Coastguard Worker     /// Return irqfd of MSI-X Table entry
689*bb4ee6a4SAndroid Build Coastguard Worker     ///
690*bb4ee6a4SAndroid Build Coastguard Worker     ///  # Arguments
691*bb4ee6a4SAndroid Build Coastguard Worker     ///  * 'vector' - the index to the MSI-X table entry
get_irqfd(&self, vector: usize) -> Option<&Event>692*bb4ee6a4SAndroid Build Coastguard Worker     pub fn get_irqfd(&self, vector: usize) -> Option<&Event> {
693*bb4ee6a4SAndroid Build Coastguard Worker         match self.irq_vec.get(vector).unwrap_or(&None) {
694*bb4ee6a4SAndroid Build Coastguard Worker             Some(irq) => Some(&irq.irqfd),
695*bb4ee6a4SAndroid Build Coastguard Worker             None => None,
696*bb4ee6a4SAndroid Build Coastguard Worker         }
697*bb4ee6a4SAndroid Build Coastguard Worker     }
698*bb4ee6a4SAndroid Build Coastguard Worker 
destroy(&mut self)699*bb4ee6a4SAndroid Build Coastguard Worker     pub fn destroy(&mut self) {
700*bb4ee6a4SAndroid Build Coastguard Worker         while let Some(irq) = self.irq_vec.pop() {
701*bb4ee6a4SAndroid Build Coastguard Worker             if let Some(irq) = irq {
702*bb4ee6a4SAndroid Build Coastguard Worker                 let request = VmIrqRequest::ReleaseOneIrq {
703*bb4ee6a4SAndroid Build Coastguard Worker                     gsi: irq.gsi,
704*bb4ee6a4SAndroid Build Coastguard Worker                     irqfd: irq.irqfd,
705*bb4ee6a4SAndroid Build Coastguard Worker                 };
706*bb4ee6a4SAndroid Build Coastguard Worker                 if self.msi_device_socket.send(&request).is_err() {
707*bb4ee6a4SAndroid Build Coastguard Worker                     continue;
708*bb4ee6a4SAndroid Build Coastguard Worker                 }
709*bb4ee6a4SAndroid Build Coastguard Worker                 let _ = self.msi_device_socket.recv::<VmIrqResponse>();
710*bb4ee6a4SAndroid Build Coastguard Worker             }
711*bb4ee6a4SAndroid Build Coastguard Worker         }
712*bb4ee6a4SAndroid Build Coastguard Worker     }
713*bb4ee6a4SAndroid Build Coastguard Worker }
714*bb4ee6a4SAndroid Build Coastguard Worker 
715*bb4ee6a4SAndroid Build Coastguard Worker const MSIX_CONFIG_READ_MASK: [u32; 3] = [0xc000_0000, 0, 0];
716*bb4ee6a4SAndroid Build Coastguard Worker 
717*bb4ee6a4SAndroid Build Coastguard Worker impl PciCapConfig for MsixConfig {
read_mask(&self) -> &'static [u32]718*bb4ee6a4SAndroid Build Coastguard Worker     fn read_mask(&self) -> &'static [u32] {
719*bb4ee6a4SAndroid Build Coastguard Worker         &MSIX_CONFIG_READ_MASK
720*bb4ee6a4SAndroid Build Coastguard Worker     }
721*bb4ee6a4SAndroid Build Coastguard Worker 
read_reg(&self, reg_idx: usize) -> u32722*bb4ee6a4SAndroid Build Coastguard Worker     fn read_reg(&self, reg_idx: usize) -> u32 {
723*bb4ee6a4SAndroid Build Coastguard Worker         if reg_idx == 0 {
724*bb4ee6a4SAndroid Build Coastguard Worker             self.read_msix_capability(0)
725*bb4ee6a4SAndroid Build Coastguard Worker         } else {
726*bb4ee6a4SAndroid Build Coastguard Worker             0
727*bb4ee6a4SAndroid Build Coastguard Worker         }
728*bb4ee6a4SAndroid Build Coastguard Worker     }
729*bb4ee6a4SAndroid Build Coastguard Worker 
write_reg( &mut self, reg_idx: usize, offset: u64, data: &[u8], ) -> Option<Box<dyn PciCapConfigWriteResult>>730*bb4ee6a4SAndroid Build Coastguard Worker     fn write_reg(
731*bb4ee6a4SAndroid Build Coastguard Worker         &mut self,
732*bb4ee6a4SAndroid Build Coastguard Worker         reg_idx: usize,
733*bb4ee6a4SAndroid Build Coastguard Worker         offset: u64,
734*bb4ee6a4SAndroid Build Coastguard Worker         data: &[u8],
735*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Option<Box<dyn PciCapConfigWriteResult>> {
736*bb4ee6a4SAndroid Build Coastguard Worker         let status = if reg_idx == 0 {
737*bb4ee6a4SAndroid Build Coastguard Worker             self.write_msix_capability(offset, data)
738*bb4ee6a4SAndroid Build Coastguard Worker         } else {
739*bb4ee6a4SAndroid Build Coastguard Worker             MsixStatus::NothingToDo
740*bb4ee6a4SAndroid Build Coastguard Worker         };
741*bb4ee6a4SAndroid Build Coastguard Worker         Some(Box::new(status))
742*bb4ee6a4SAndroid Build Coastguard Worker     }
743*bb4ee6a4SAndroid Build Coastguard Worker }
744*bb4ee6a4SAndroid Build Coastguard Worker 
745*bb4ee6a4SAndroid Build Coastguard Worker impl AsRawDescriptor for MsixConfig {
as_raw_descriptor(&self) -> RawDescriptor746*bb4ee6a4SAndroid Build Coastguard Worker     fn as_raw_descriptor(&self) -> RawDescriptor {
747*bb4ee6a4SAndroid Build Coastguard Worker         self.msi_device_socket.as_raw_descriptor()
748*bb4ee6a4SAndroid Build Coastguard Worker     }
749*bb4ee6a4SAndroid Build Coastguard Worker }
750*bb4ee6a4SAndroid Build Coastguard Worker 
751*bb4ee6a4SAndroid Build Coastguard Worker /// Message Control Register
752*bb4ee6a4SAndroid Build Coastguard Worker //   10-0:  MSI-X Table size
753*bb4ee6a4SAndroid Build Coastguard Worker //   13-11: Reserved
754*bb4ee6a4SAndroid Build Coastguard Worker //   14:    Mask. Mask all MSI-X when set.
755*bb4ee6a4SAndroid Build Coastguard Worker //   15:    Enable. Enable all MSI-X when set.
756*bb4ee6a4SAndroid Build Coastguard Worker // See <https://wiki.osdev.org/PCI#Enabling_MSI-X> for the details.
757*bb4ee6a4SAndroid Build Coastguard Worker #[bitfield]
758*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Copy, Clone, Default, AsBytes, FromZeroes, FromBytes)]
759*bb4ee6a4SAndroid Build Coastguard Worker pub struct MsixCtrl {
760*bb4ee6a4SAndroid Build Coastguard Worker     table_size: B10,
761*bb4ee6a4SAndroid Build Coastguard Worker     reserved: B4,
762*bb4ee6a4SAndroid Build Coastguard Worker     mask: B1,
763*bb4ee6a4SAndroid Build Coastguard Worker     enable: B1,
764*bb4ee6a4SAndroid Build Coastguard Worker }
765*bb4ee6a4SAndroid Build Coastguard Worker 
766*bb4ee6a4SAndroid Build Coastguard Worker #[allow(dead_code)]
767*bb4ee6a4SAndroid Build Coastguard Worker #[repr(C)]
768*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Clone, Copy, Default, AsBytes, FromZeroes, FromBytes)]
769*bb4ee6a4SAndroid Build Coastguard Worker /// MSI-X Capability Structure
770*bb4ee6a4SAndroid Build Coastguard Worker pub struct MsixCap {
771*bb4ee6a4SAndroid Build Coastguard Worker     // To make add_capability() happy
772*bb4ee6a4SAndroid Build Coastguard Worker     _cap_vndr: u8,
773*bb4ee6a4SAndroid Build Coastguard Worker     _cap_next: u8,
774*bb4ee6a4SAndroid Build Coastguard Worker     // Message Control Register
775*bb4ee6a4SAndroid Build Coastguard Worker     msg_ctl: MsixCtrl,
776*bb4ee6a4SAndroid Build Coastguard Worker     // Table. Contains the offset and the BAR indicator (BIR)
777*bb4ee6a4SAndroid Build Coastguard Worker     //   2-0:  Table BAR indicator (BIR). Can be 0 to 5.
778*bb4ee6a4SAndroid Build Coastguard Worker     //   31-3: Table offset in the BAR pointed by the BIR.
779*bb4ee6a4SAndroid Build Coastguard Worker     table: u32,
780*bb4ee6a4SAndroid Build Coastguard Worker     // Pending Bit Array. Contains the offset and the BAR indicator (BIR)
781*bb4ee6a4SAndroid Build Coastguard Worker     //   2-0:  PBA BAR indicator (BIR). Can be 0 to 5.
782*bb4ee6a4SAndroid Build Coastguard Worker     //   31-3: PBA offset in the BAR pointed by the BIR.
783*bb4ee6a4SAndroid Build Coastguard Worker     pba: u32,
784*bb4ee6a4SAndroid Build Coastguard Worker }
785*bb4ee6a4SAndroid Build Coastguard Worker 
786*bb4ee6a4SAndroid Build Coastguard Worker impl PciCapability for MsixCap {
bytes(&self) -> &[u8]787*bb4ee6a4SAndroid Build Coastguard Worker     fn bytes(&self) -> &[u8] {
788*bb4ee6a4SAndroid Build Coastguard Worker         self.as_bytes()
789*bb4ee6a4SAndroid Build Coastguard Worker     }
790*bb4ee6a4SAndroid Build Coastguard Worker 
id(&self) -> PciCapabilityID791*bb4ee6a4SAndroid Build Coastguard Worker     fn id(&self) -> PciCapabilityID {
792*bb4ee6a4SAndroid Build Coastguard Worker         PciCapabilityID::Msix
793*bb4ee6a4SAndroid Build Coastguard Worker     }
794*bb4ee6a4SAndroid Build Coastguard Worker 
writable_bits(&self) -> Vec<u32>795*bb4ee6a4SAndroid Build Coastguard Worker     fn writable_bits(&self) -> Vec<u32> {
796*bb4ee6a4SAndroid Build Coastguard Worker         // Only msg_ctl[15:14] is writable
797*bb4ee6a4SAndroid Build Coastguard Worker         vec![0x3000_0000, 0, 0]
798*bb4ee6a4SAndroid Build Coastguard Worker     }
799*bb4ee6a4SAndroid Build Coastguard Worker }
800*bb4ee6a4SAndroid Build Coastguard Worker 
801*bb4ee6a4SAndroid Build Coastguard Worker impl MsixCap {
new( table_pci_bar: u8, table_size: u16, table_off: u32, pba_pci_bar: u8, pba_off: u32, ) -> Self802*bb4ee6a4SAndroid Build Coastguard Worker     pub fn new(
803*bb4ee6a4SAndroid Build Coastguard Worker         table_pci_bar: u8,
804*bb4ee6a4SAndroid Build Coastguard Worker         table_size: u16,
805*bb4ee6a4SAndroid Build Coastguard Worker         table_off: u32,
806*bb4ee6a4SAndroid Build Coastguard Worker         pba_pci_bar: u8,
807*bb4ee6a4SAndroid Build Coastguard Worker         pba_off: u32,
808*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Self {
809*bb4ee6a4SAndroid Build Coastguard Worker         assert!(table_size < MAX_MSIX_VECTORS_PER_DEVICE);
810*bb4ee6a4SAndroid Build Coastguard Worker 
811*bb4ee6a4SAndroid Build Coastguard Worker         // Set the table size and enable MSI-X.
812*bb4ee6a4SAndroid Build Coastguard Worker         let mut msg_ctl = MsixCtrl::new();
813*bb4ee6a4SAndroid Build Coastguard Worker         msg_ctl.set_enable(1);
814*bb4ee6a4SAndroid Build Coastguard Worker         // Table Size is N - 1 encoded.
815*bb4ee6a4SAndroid Build Coastguard Worker         msg_ctl.set_table_size(table_size - 1);
816*bb4ee6a4SAndroid Build Coastguard Worker 
817*bb4ee6a4SAndroid Build Coastguard Worker         MsixCap {
818*bb4ee6a4SAndroid Build Coastguard Worker             _cap_vndr: 0,
819*bb4ee6a4SAndroid Build Coastguard Worker             _cap_next: 0,
820*bb4ee6a4SAndroid Build Coastguard Worker             msg_ctl,
821*bb4ee6a4SAndroid Build Coastguard Worker             table: (table_off & 0xffff_fff8u32) | u32::from(table_pci_bar & 0x7u8),
822*bb4ee6a4SAndroid Build Coastguard Worker             pba: (pba_off & 0xffff_fff8u32) | u32::from(pba_pci_bar & 0x7u8),
823*bb4ee6a4SAndroid Build Coastguard Worker         }
824*bb4ee6a4SAndroid Build Coastguard Worker     }
825*bb4ee6a4SAndroid Build Coastguard Worker }
826*bb4ee6a4SAndroid Build Coastguard Worker 
827*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(test)]
828*bb4ee6a4SAndroid Build Coastguard Worker mod tests {
829*bb4ee6a4SAndroid Build Coastguard Worker 
830*bb4ee6a4SAndroid Build Coastguard Worker     use std::thread;
831*bb4ee6a4SAndroid Build Coastguard Worker 
832*bb4ee6a4SAndroid Build Coastguard Worker     use super::*;
833*bb4ee6a4SAndroid Build Coastguard Worker 
834*bb4ee6a4SAndroid Build Coastguard Worker     #[track_caller]
recv_allocate_msi(t: &Tube) -> u32835*bb4ee6a4SAndroid Build Coastguard Worker     fn recv_allocate_msi(t: &Tube) -> u32 {
836*bb4ee6a4SAndroid Build Coastguard Worker         match t.recv::<VmIrqRequest>().unwrap() {
837*bb4ee6a4SAndroid Build Coastguard Worker             VmIrqRequest::AllocateOneMsiAtGsi { gsi, .. } => gsi,
838*bb4ee6a4SAndroid Build Coastguard Worker             msg => panic!("unexpected irqchip message: {:?}", msg),
839*bb4ee6a4SAndroid Build Coastguard Worker         }
840*bb4ee6a4SAndroid Build Coastguard Worker     }
841*bb4ee6a4SAndroid Build Coastguard Worker 
842*bb4ee6a4SAndroid Build Coastguard Worker     struct MsiRouteDetails {
843*bb4ee6a4SAndroid Build Coastguard Worker         gsi: u32,
844*bb4ee6a4SAndroid Build Coastguard Worker         msi_address: u64,
845*bb4ee6a4SAndroid Build Coastguard Worker         msi_data: u32,
846*bb4ee6a4SAndroid Build Coastguard Worker     }
847*bb4ee6a4SAndroid Build Coastguard Worker 
848*bb4ee6a4SAndroid Build Coastguard Worker     #[track_caller]
recv_add_msi_route(t: &Tube) -> MsiRouteDetails849*bb4ee6a4SAndroid Build Coastguard Worker     fn recv_add_msi_route(t: &Tube) -> MsiRouteDetails {
850*bb4ee6a4SAndroid Build Coastguard Worker         match t.recv::<VmIrqRequest>().unwrap() {
851*bb4ee6a4SAndroid Build Coastguard Worker             VmIrqRequest::AddMsiRoute {
852*bb4ee6a4SAndroid Build Coastguard Worker                 gsi,
853*bb4ee6a4SAndroid Build Coastguard Worker                 msi_address,
854*bb4ee6a4SAndroid Build Coastguard Worker                 msi_data,
855*bb4ee6a4SAndroid Build Coastguard Worker             } => MsiRouteDetails {
856*bb4ee6a4SAndroid Build Coastguard Worker                 gsi,
857*bb4ee6a4SAndroid Build Coastguard Worker                 msi_address,
858*bb4ee6a4SAndroid Build Coastguard Worker                 msi_data,
859*bb4ee6a4SAndroid Build Coastguard Worker             },
860*bb4ee6a4SAndroid Build Coastguard Worker             msg => panic!("unexpected irqchip message: {:?}", msg),
861*bb4ee6a4SAndroid Build Coastguard Worker         }
862*bb4ee6a4SAndroid Build Coastguard Worker     }
863*bb4ee6a4SAndroid Build Coastguard Worker 
864*bb4ee6a4SAndroid Build Coastguard Worker     #[track_caller]
recv_release_one_irq(t: &Tube) -> u32865*bb4ee6a4SAndroid Build Coastguard Worker     fn recv_release_one_irq(t: &Tube) -> u32 {
866*bb4ee6a4SAndroid Build Coastguard Worker         match t.recv::<VmIrqRequest>().unwrap() {
867*bb4ee6a4SAndroid Build Coastguard Worker             VmIrqRequest::ReleaseOneIrq { gsi, irqfd: _ } => gsi,
868*bb4ee6a4SAndroid Build Coastguard Worker             msg => panic!("unexpected irqchip message: {:?}", msg),
869*bb4ee6a4SAndroid Build Coastguard Worker         }
870*bb4ee6a4SAndroid Build Coastguard Worker     }
871*bb4ee6a4SAndroid Build Coastguard Worker 
872*bb4ee6a4SAndroid Build Coastguard Worker     #[track_caller]
send_ok(t: &Tube)873*bb4ee6a4SAndroid Build Coastguard Worker     fn send_ok(t: &Tube) {
874*bb4ee6a4SAndroid Build Coastguard Worker         t.send(&VmIrqResponse::Ok).unwrap();
875*bb4ee6a4SAndroid Build Coastguard Worker     }
876*bb4ee6a4SAndroid Build Coastguard Worker 
877*bb4ee6a4SAndroid Build Coastguard Worker     /// Tests a cold restore where there are no existing vectors at the time
878*bb4ee6a4SAndroid Build Coastguard Worker     /// restore is called.
879*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
verify_msix_restore_cold_smoke()880*bb4ee6a4SAndroid Build Coastguard Worker     fn verify_msix_restore_cold_smoke() {
881*bb4ee6a4SAndroid Build Coastguard Worker         let (irqchip_tube, msix_config_tube) = Tube::pair().unwrap();
882*bb4ee6a4SAndroid Build Coastguard Worker         let (_unused, unused_config_tube) = Tube::pair().unwrap();
883*bb4ee6a4SAndroid Build Coastguard Worker 
884*bb4ee6a4SAndroid Build Coastguard Worker         let mut cfg = MsixConfig::new(2, unused_config_tube, 0, "test_device".to_owned());
885*bb4ee6a4SAndroid Build Coastguard Worker 
886*bb4ee6a4SAndroid Build Coastguard Worker         // Set up two MSI-X vectors (0 and 1).
887*bb4ee6a4SAndroid Build Coastguard Worker         // Data is 0xdVEC_NUM. Address is 0xaVEC_NUM.
888*bb4ee6a4SAndroid Build Coastguard Worker         cfg.table_entries[0].msg_data = 0xd0;
889*bb4ee6a4SAndroid Build Coastguard Worker         cfg.table_entries[0].msg_addr_lo = 0xa0;
890*bb4ee6a4SAndroid Build Coastguard Worker         cfg.table_entries[0].msg_addr_hi = 0;
891*bb4ee6a4SAndroid Build Coastguard Worker         cfg.table_entries[1].msg_data = 0xd1;
892*bb4ee6a4SAndroid Build Coastguard Worker         cfg.table_entries[1].msg_addr_lo = 0xa1;
893*bb4ee6a4SAndroid Build Coastguard Worker         cfg.table_entries[1].msg_addr_hi = 0;
894*bb4ee6a4SAndroid Build Coastguard Worker 
895*bb4ee6a4SAndroid Build Coastguard Worker         // Pretend that these vectors were hooked up to GSIs 10 & 20,
896*bb4ee6a4SAndroid Build Coastguard Worker         // respectively.
897*bb4ee6a4SAndroid Build Coastguard Worker         cfg.irq_vec = vec![
898*bb4ee6a4SAndroid Build Coastguard Worker             Some(IrqfdGsi {
899*bb4ee6a4SAndroid Build Coastguard Worker                 gsi: 10,
900*bb4ee6a4SAndroid Build Coastguard Worker                 irqfd: Event::new().unwrap(),
901*bb4ee6a4SAndroid Build Coastguard Worker             }),
902*bb4ee6a4SAndroid Build Coastguard Worker             Some(IrqfdGsi {
903*bb4ee6a4SAndroid Build Coastguard Worker                 gsi: 20,
904*bb4ee6a4SAndroid Build Coastguard Worker                 irqfd: Event::new().unwrap(),
905*bb4ee6a4SAndroid Build Coastguard Worker             }),
906*bb4ee6a4SAndroid Build Coastguard Worker         ];
907*bb4ee6a4SAndroid Build Coastguard Worker 
908*bb4ee6a4SAndroid Build Coastguard Worker         // Take a snapshot of MsixConfig.
909*bb4ee6a4SAndroid Build Coastguard Worker         let snapshot = cfg.snapshot().unwrap();
910*bb4ee6a4SAndroid Build Coastguard Worker 
911*bb4ee6a4SAndroid Build Coastguard Worker         // Create a fake irqchip to respond to our requests
912*bb4ee6a4SAndroid Build Coastguard Worker         let irqchip_fake = thread::spawn(move || {
913*bb4ee6a4SAndroid Build Coastguard Worker             assert_eq!(recv_allocate_msi(&irqchip_tube), 10);
914*bb4ee6a4SAndroid Build Coastguard Worker             send_ok(&irqchip_tube);
915*bb4ee6a4SAndroid Build Coastguard Worker             let route_one = recv_add_msi_route(&irqchip_tube);
916*bb4ee6a4SAndroid Build Coastguard Worker             assert_eq!(route_one.gsi, 10);
917*bb4ee6a4SAndroid Build Coastguard Worker             assert_eq!(route_one.msi_address, 0xa0);
918*bb4ee6a4SAndroid Build Coastguard Worker             assert_eq!(route_one.msi_data, 0xd0);
919*bb4ee6a4SAndroid Build Coastguard Worker             send_ok(&irqchip_tube);
920*bb4ee6a4SAndroid Build Coastguard Worker 
921*bb4ee6a4SAndroid Build Coastguard Worker             assert_eq!(recv_allocate_msi(&irqchip_tube), 20);
922*bb4ee6a4SAndroid Build Coastguard Worker             send_ok(&irqchip_tube);
923*bb4ee6a4SAndroid Build Coastguard Worker             let route_two = recv_add_msi_route(&irqchip_tube);
924*bb4ee6a4SAndroid Build Coastguard Worker             assert_eq!(route_two.gsi, 20);
925*bb4ee6a4SAndroid Build Coastguard Worker             assert_eq!(route_two.msi_address, 0xa1);
926*bb4ee6a4SAndroid Build Coastguard Worker             assert_eq!(route_two.msi_data, 0xd1);
927*bb4ee6a4SAndroid Build Coastguard Worker             send_ok(&irqchip_tube);
928*bb4ee6a4SAndroid Build Coastguard Worker             irqchip_tube
929*bb4ee6a4SAndroid Build Coastguard Worker         });
930*bb4ee6a4SAndroid Build Coastguard Worker 
931*bb4ee6a4SAndroid Build Coastguard Worker         let mut restored_cfg = MsixConfig::new(10, msix_config_tube, 10, "some_device".to_owned());
932*bb4ee6a4SAndroid Build Coastguard Worker         restored_cfg.restore(snapshot).unwrap();
933*bb4ee6a4SAndroid Build Coastguard Worker         irqchip_fake.join().unwrap();
934*bb4ee6a4SAndroid Build Coastguard Worker 
935*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(restored_cfg.pci_id, 0);
936*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(restored_cfg.device_name, "test_device");
937*bb4ee6a4SAndroid Build Coastguard Worker     }
938*bb4ee6a4SAndroid Build Coastguard Worker 
939*bb4ee6a4SAndroid Build Coastguard Worker     /// Tests a warm restore where there are existing vectors at the time
940*bb4ee6a4SAndroid Build Coastguard Worker     /// restore is called. These vectors need to be released first.
941*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
verify_msix_restore_warm_smoke()942*bb4ee6a4SAndroid Build Coastguard Worker     fn verify_msix_restore_warm_smoke() {
943*bb4ee6a4SAndroid Build Coastguard Worker         let (irqchip_tube, msix_config_tube) = Tube::pair().unwrap();
944*bb4ee6a4SAndroid Build Coastguard Worker 
945*bb4ee6a4SAndroid Build Coastguard Worker         let mut cfg = MsixConfig::new(2, msix_config_tube, 0, "test_device".to_owned());
946*bb4ee6a4SAndroid Build Coastguard Worker 
947*bb4ee6a4SAndroid Build Coastguard Worker         // Set up two MSI-X vectors (0 and 1).
948*bb4ee6a4SAndroid Build Coastguard Worker         // Data is 0xdVEC_NUM. Address is 0xaVEC_NUM.
949*bb4ee6a4SAndroid Build Coastguard Worker         cfg.table_entries[0].msg_data = 0xd0;
950*bb4ee6a4SAndroid Build Coastguard Worker         cfg.table_entries[0].msg_addr_lo = 0xa0;
951*bb4ee6a4SAndroid Build Coastguard Worker         cfg.table_entries[0].msg_addr_hi = 0;
952*bb4ee6a4SAndroid Build Coastguard Worker         cfg.table_entries[1].msg_data = 0xd1;
953*bb4ee6a4SAndroid Build Coastguard Worker         cfg.table_entries[1].msg_addr_lo = 0xa1;
954*bb4ee6a4SAndroid Build Coastguard Worker         cfg.table_entries[1].msg_addr_hi = 0;
955*bb4ee6a4SAndroid Build Coastguard Worker 
956*bb4ee6a4SAndroid Build Coastguard Worker         // Pretend that these vectors were hooked up to GSIs 10 & 20,
957*bb4ee6a4SAndroid Build Coastguard Worker         // respectively.
958*bb4ee6a4SAndroid Build Coastguard Worker         cfg.irq_vec = vec![
959*bb4ee6a4SAndroid Build Coastguard Worker             Some(IrqfdGsi {
960*bb4ee6a4SAndroid Build Coastguard Worker                 gsi: 10,
961*bb4ee6a4SAndroid Build Coastguard Worker                 irqfd: Event::new().unwrap(),
962*bb4ee6a4SAndroid Build Coastguard Worker             }),
963*bb4ee6a4SAndroid Build Coastguard Worker             Some(IrqfdGsi {
964*bb4ee6a4SAndroid Build Coastguard Worker                 gsi: 20,
965*bb4ee6a4SAndroid Build Coastguard Worker                 irqfd: Event::new().unwrap(),
966*bb4ee6a4SAndroid Build Coastguard Worker             }),
967*bb4ee6a4SAndroid Build Coastguard Worker         ];
968*bb4ee6a4SAndroid Build Coastguard Worker 
969*bb4ee6a4SAndroid Build Coastguard Worker         // Take a snapshot of MsixConfig.
970*bb4ee6a4SAndroid Build Coastguard Worker         let snapshot = cfg.snapshot().unwrap();
971*bb4ee6a4SAndroid Build Coastguard Worker 
972*bb4ee6a4SAndroid Build Coastguard Worker         // Create a fake irqchip to respond to our requests
973*bb4ee6a4SAndroid Build Coastguard Worker         let irqchip_fake = thread::spawn(move || {
974*bb4ee6a4SAndroid Build Coastguard Worker             // First, we free the existing vectors / GSIs.
975*bb4ee6a4SAndroid Build Coastguard Worker             assert_eq!(recv_release_one_irq(&irqchip_tube), 10);
976*bb4ee6a4SAndroid Build Coastguard Worker             send_ok(&irqchip_tube);
977*bb4ee6a4SAndroid Build Coastguard Worker             assert_eq!(recv_release_one_irq(&irqchip_tube), 20);
978*bb4ee6a4SAndroid Build Coastguard Worker             send_ok(&irqchip_tube);
979*bb4ee6a4SAndroid Build Coastguard Worker 
980*bb4ee6a4SAndroid Build Coastguard Worker             // Now we re-allocate them.
981*bb4ee6a4SAndroid Build Coastguard Worker             assert_eq!(recv_allocate_msi(&irqchip_tube), 10);
982*bb4ee6a4SAndroid Build Coastguard Worker             send_ok(&irqchip_tube);
983*bb4ee6a4SAndroid Build Coastguard Worker             let route_one = recv_add_msi_route(&irqchip_tube);
984*bb4ee6a4SAndroid Build Coastguard Worker             assert_eq!(route_one.gsi, 10);
985*bb4ee6a4SAndroid Build Coastguard Worker             assert_eq!(route_one.msi_address, 0xa0);
986*bb4ee6a4SAndroid Build Coastguard Worker             assert_eq!(route_one.msi_data, 0xd0);
987*bb4ee6a4SAndroid Build Coastguard Worker             send_ok(&irqchip_tube);
988*bb4ee6a4SAndroid Build Coastguard Worker 
989*bb4ee6a4SAndroid Build Coastguard Worker             assert_eq!(recv_allocate_msi(&irqchip_tube), 20);
990*bb4ee6a4SAndroid Build Coastguard Worker             send_ok(&irqchip_tube);
991*bb4ee6a4SAndroid Build Coastguard Worker             let route_two = recv_add_msi_route(&irqchip_tube);
992*bb4ee6a4SAndroid Build Coastguard Worker             assert_eq!(route_two.gsi, 20);
993*bb4ee6a4SAndroid Build Coastguard Worker             assert_eq!(route_two.msi_address, 0xa1);
994*bb4ee6a4SAndroid Build Coastguard Worker             assert_eq!(route_two.msi_data, 0xd1);
995*bb4ee6a4SAndroid Build Coastguard Worker             send_ok(&irqchip_tube);
996*bb4ee6a4SAndroid Build Coastguard Worker             irqchip_tube
997*bb4ee6a4SAndroid Build Coastguard Worker         });
998*bb4ee6a4SAndroid Build Coastguard Worker 
999*bb4ee6a4SAndroid Build Coastguard Worker         cfg.restore(snapshot).unwrap();
1000*bb4ee6a4SAndroid Build Coastguard Worker         irqchip_fake.join().unwrap();
1001*bb4ee6a4SAndroid Build Coastguard Worker 
1002*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(cfg.pci_id, 0);
1003*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(cfg.device_name, "test_device");
1004*bb4ee6a4SAndroid Build Coastguard Worker     }
1005*bb4ee6a4SAndroid Build Coastguard Worker }
1006