xref: /aosp_15_r20/external/crosvm/devices/src/pci/vfio_pci.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::cmp::max;
6*bb4ee6a4SAndroid Build Coastguard Worker use std::cmp::Reverse;
7*bb4ee6a4SAndroid Build Coastguard Worker use std::collections::BTreeMap;
8*bb4ee6a4SAndroid Build Coastguard Worker use std::collections::BTreeSet;
9*bb4ee6a4SAndroid Build Coastguard Worker use std::fs;
10*bb4ee6a4SAndroid Build Coastguard Worker use std::path::Path;
11*bb4ee6a4SAndroid Build Coastguard Worker use std::path::PathBuf;
12*bb4ee6a4SAndroid Build Coastguard Worker use std::str::FromStr;
13*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::Arc;
14*bb4ee6a4SAndroid Build Coastguard Worker 
15*bb4ee6a4SAndroid Build Coastguard Worker use acpi_tables::aml::Aml;
16*bb4ee6a4SAndroid Build Coastguard Worker use base::debug;
17*bb4ee6a4SAndroid Build Coastguard Worker use base::error;
18*bb4ee6a4SAndroid Build Coastguard Worker use base::pagesize;
19*bb4ee6a4SAndroid Build Coastguard Worker use base::warn;
20*bb4ee6a4SAndroid Build Coastguard Worker use base::AsRawDescriptor;
21*bb4ee6a4SAndroid Build Coastguard Worker use base::AsRawDescriptors;
22*bb4ee6a4SAndroid Build Coastguard Worker use base::Event;
23*bb4ee6a4SAndroid Build Coastguard Worker use base::EventToken;
24*bb4ee6a4SAndroid Build Coastguard Worker use base::MemoryMapping;
25*bb4ee6a4SAndroid Build Coastguard Worker use base::Protection;
26*bb4ee6a4SAndroid Build Coastguard Worker use base::RawDescriptor;
27*bb4ee6a4SAndroid Build Coastguard Worker use base::Tube;
28*bb4ee6a4SAndroid Build Coastguard Worker use base::WaitContext;
29*bb4ee6a4SAndroid Build Coastguard Worker use base::WorkerThread;
30*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::MemCacheType;
31*bb4ee6a4SAndroid Build Coastguard Worker use resources::AddressRange;
32*bb4ee6a4SAndroid Build Coastguard Worker use resources::Alloc;
33*bb4ee6a4SAndroid Build Coastguard Worker use resources::AllocOptions;
34*bb4ee6a4SAndroid Build Coastguard Worker use resources::MmioType;
35*bb4ee6a4SAndroid Build Coastguard Worker use resources::SystemAllocator;
36*bb4ee6a4SAndroid Build Coastguard Worker use sync::Mutex;
37*bb4ee6a4SAndroid Build Coastguard Worker use vfio_sys::vfio::VFIO_PCI_ACPI_NTFY_IRQ_INDEX;
38*bb4ee6a4SAndroid Build Coastguard Worker use vfio_sys::*;
39*bb4ee6a4SAndroid Build Coastguard Worker use vm_control::api::VmMemoryClient;
40*bb4ee6a4SAndroid Build Coastguard Worker use vm_control::HotPlugDeviceInfo;
41*bb4ee6a4SAndroid Build Coastguard Worker use vm_control::HotPlugDeviceType;
42*bb4ee6a4SAndroid Build Coastguard Worker use vm_control::VmMemoryDestination;
43*bb4ee6a4SAndroid Build Coastguard Worker use vm_control::VmMemoryRegionId;
44*bb4ee6a4SAndroid Build Coastguard Worker use vm_control::VmMemorySource;
45*bb4ee6a4SAndroid Build Coastguard Worker use vm_control::VmRequest;
46*bb4ee6a4SAndroid Build Coastguard Worker use vm_control::VmResponse;
47*bb4ee6a4SAndroid Build Coastguard Worker 
48*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::acpi::DeviceVcfgRegister;
49*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::acpi::DsmMethod;
50*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::acpi::PowerResourceMethod;
51*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::acpi::SHM_OFFSET;
52*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::msi::MsiConfig;
53*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::msi::MsiStatus;
54*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::msi::PCI_MSI_FLAGS;
55*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::msi::PCI_MSI_FLAGS_64BIT;
56*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::msi::PCI_MSI_FLAGS_MASKBIT;
57*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::msi::PCI_MSI_NEXT_POINTER;
58*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::msix::MsixConfig;
59*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::msix::MsixStatus;
60*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::msix::BITS_PER_PBA_ENTRY;
61*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::msix::MSIX_PBA_ENTRIES_MODULO;
62*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::msix::MSIX_TABLE_ENTRIES_MODULO;
63*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::pci_device::BarRange;
64*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::pci_device::Error as PciDeviceError;
65*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::pci_device::PciDevice;
66*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::pci_device::PreferredIrq;
67*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::pm::PciPmCap;
68*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::pm::PmConfig;
69*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::pm::PM_CAP_LENGTH;
70*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::PciAddress;
71*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::PciBarConfiguration;
72*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::PciBarIndex;
73*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::PciBarPrefetchable;
74*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::PciBarRegionType;
75*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::PciCapabilityID;
76*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::PciClassCode;
77*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::PciId;
78*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::PciInterruptPin;
79*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::PCI_VCFG_DSM;
80*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::PCI_VCFG_NOTY;
81*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::PCI_VCFG_PM;
82*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::PCI_VENDOR_ID_INTEL;
83*bb4ee6a4SAndroid Build Coastguard Worker use crate::vfio::VfioDevice;
84*bb4ee6a4SAndroid Build Coastguard Worker use crate::vfio::VfioError;
85*bb4ee6a4SAndroid Build Coastguard Worker use crate::vfio::VfioIrqType;
86*bb4ee6a4SAndroid Build Coastguard Worker use crate::vfio::VfioPciConfig;
87*bb4ee6a4SAndroid Build Coastguard Worker use crate::IrqLevelEvent;
88*bb4ee6a4SAndroid Build Coastguard Worker use crate::Suspendable;
89*bb4ee6a4SAndroid Build Coastguard Worker 
90*bb4ee6a4SAndroid Build Coastguard Worker const PCI_VENDOR_ID: u32 = 0x0;
91*bb4ee6a4SAndroid Build Coastguard Worker const PCI_DEVICE_ID: u32 = 0x2;
92*bb4ee6a4SAndroid Build Coastguard Worker const PCI_COMMAND: u32 = 0x4;
93*bb4ee6a4SAndroid Build Coastguard Worker const PCI_COMMAND_MEMORY: u8 = 0x2;
94*bb4ee6a4SAndroid Build Coastguard Worker const PCI_BASE_CLASS_CODE: u32 = 0x0B;
95*bb4ee6a4SAndroid Build Coastguard Worker const PCI_INTERRUPT_NUM: u32 = 0x3C;
96*bb4ee6a4SAndroid Build Coastguard Worker const PCI_INTERRUPT_PIN: u32 = 0x3D;
97*bb4ee6a4SAndroid Build Coastguard Worker 
98*bb4ee6a4SAndroid Build Coastguard Worker const PCI_CAPABILITY_LIST: u32 = 0x34;
99*bb4ee6a4SAndroid Build Coastguard Worker const PCI_CAP_ID_MSI: u8 = 0x05;
100*bb4ee6a4SAndroid Build Coastguard Worker const PCI_CAP_ID_MSIX: u8 = 0x11;
101*bb4ee6a4SAndroid Build Coastguard Worker const PCI_CAP_ID_PM: u8 = 0x01;
102*bb4ee6a4SAndroid Build Coastguard Worker 
103*bb4ee6a4SAndroid Build Coastguard Worker // Size of the standard PCI config space
104*bb4ee6a4SAndroid Build Coastguard Worker const PCI_CONFIG_SPACE_SIZE: u32 = 0x100;
105*bb4ee6a4SAndroid Build Coastguard Worker // Size of the standard PCIe config space: 4KB
106*bb4ee6a4SAndroid Build Coastguard Worker const PCIE_CONFIG_SPACE_SIZE: u32 = 0x1000;
107*bb4ee6a4SAndroid Build Coastguard Worker 
108*bb4ee6a4SAndroid Build Coastguard Worker // Extended Capabilities
109*bb4ee6a4SAndroid Build Coastguard Worker const PCI_EXT_CAP_ID_CAC: u16 = 0x0C;
110*bb4ee6a4SAndroid Build Coastguard Worker const PCI_EXT_CAP_ID_ARI: u16 = 0x0E;
111*bb4ee6a4SAndroid Build Coastguard Worker const PCI_EXT_CAP_ID_SRIOV: u16 = 0x10;
112*bb4ee6a4SAndroid Build Coastguard Worker const PCI_EXT_CAP_ID_REBAR: u16 = 0x15;
113*bb4ee6a4SAndroid Build Coastguard Worker 
114*bb4ee6a4SAndroid Build Coastguard Worker struct VfioPmCap {
115*bb4ee6a4SAndroid Build Coastguard Worker     offset: u32,
116*bb4ee6a4SAndroid Build Coastguard Worker     capabilities: u32,
117*bb4ee6a4SAndroid Build Coastguard Worker     config: PmConfig,
118*bb4ee6a4SAndroid Build Coastguard Worker }
119*bb4ee6a4SAndroid Build Coastguard Worker 
120*bb4ee6a4SAndroid Build Coastguard Worker impl VfioPmCap {
new(config: &VfioPciConfig, cap_start: u32) -> Self121*bb4ee6a4SAndroid Build Coastguard Worker     fn new(config: &VfioPciConfig, cap_start: u32) -> Self {
122*bb4ee6a4SAndroid Build Coastguard Worker         let mut capabilities: u32 = config.read_config(cap_start);
123*bb4ee6a4SAndroid Build Coastguard Worker         capabilities |= (PciPmCap::default_cap() as u32) << 16;
124*bb4ee6a4SAndroid Build Coastguard Worker         VfioPmCap {
125*bb4ee6a4SAndroid Build Coastguard Worker             offset: cap_start,
126*bb4ee6a4SAndroid Build Coastguard Worker             capabilities,
127*bb4ee6a4SAndroid Build Coastguard Worker             config: PmConfig::new(false),
128*bb4ee6a4SAndroid Build Coastguard Worker         }
129*bb4ee6a4SAndroid Build Coastguard Worker     }
130*bb4ee6a4SAndroid Build Coastguard Worker 
should_trigger_pme(&mut self) -> bool131*bb4ee6a4SAndroid Build Coastguard Worker     pub fn should_trigger_pme(&mut self) -> bool {
132*bb4ee6a4SAndroid Build Coastguard Worker         self.config.should_trigger_pme()
133*bb4ee6a4SAndroid Build Coastguard Worker     }
134*bb4ee6a4SAndroid Build Coastguard Worker 
is_pm_reg(&self, offset: u32) -> bool135*bb4ee6a4SAndroid Build Coastguard Worker     fn is_pm_reg(&self, offset: u32) -> bool {
136*bb4ee6a4SAndroid Build Coastguard Worker         (offset >= self.offset) && (offset < self.offset + PM_CAP_LENGTH as u32)
137*bb4ee6a4SAndroid Build Coastguard Worker     }
138*bb4ee6a4SAndroid Build Coastguard Worker 
read(&self, offset: u32) -> u32139*bb4ee6a4SAndroid Build Coastguard Worker     pub fn read(&self, offset: u32) -> u32 {
140*bb4ee6a4SAndroid Build Coastguard Worker         let offset = offset - self.offset;
141*bb4ee6a4SAndroid Build Coastguard Worker         if offset == 0 {
142*bb4ee6a4SAndroid Build Coastguard Worker             self.capabilities
143*bb4ee6a4SAndroid Build Coastguard Worker         } else {
144*bb4ee6a4SAndroid Build Coastguard Worker             let mut data = 0;
145*bb4ee6a4SAndroid Build Coastguard Worker             self.config.read(&mut data);
146*bb4ee6a4SAndroid Build Coastguard Worker             data
147*bb4ee6a4SAndroid Build Coastguard Worker         }
148*bb4ee6a4SAndroid Build Coastguard Worker     }
149*bb4ee6a4SAndroid Build Coastguard Worker 
write(&mut self, offset: u64, data: &[u8])150*bb4ee6a4SAndroid Build Coastguard Worker     pub fn write(&mut self, offset: u64, data: &[u8]) {
151*bb4ee6a4SAndroid Build Coastguard Worker         let offset = offset - self.offset as u64;
152*bb4ee6a4SAndroid Build Coastguard Worker         if offset >= std::mem::size_of::<u32>() as u64 {
153*bb4ee6a4SAndroid Build Coastguard Worker             let offset = offset - std::mem::size_of::<u32>() as u64;
154*bb4ee6a4SAndroid Build Coastguard Worker             self.config.write(offset, data);
155*bb4ee6a4SAndroid Build Coastguard Worker         }
156*bb4ee6a4SAndroid Build Coastguard Worker     }
157*bb4ee6a4SAndroid Build Coastguard Worker }
158*bb4ee6a4SAndroid Build Coastguard Worker 
159*bb4ee6a4SAndroid Build Coastguard Worker enum VfioMsiChange {
160*bb4ee6a4SAndroid Build Coastguard Worker     Disable,
161*bb4ee6a4SAndroid Build Coastguard Worker     Enable,
162*bb4ee6a4SAndroid Build Coastguard Worker     FunctionChanged,
163*bb4ee6a4SAndroid Build Coastguard Worker }
164*bb4ee6a4SAndroid Build Coastguard Worker 
165*bb4ee6a4SAndroid Build Coastguard Worker struct VfioMsiCap {
166*bb4ee6a4SAndroid Build Coastguard Worker     config: MsiConfig,
167*bb4ee6a4SAndroid Build Coastguard Worker     offset: u32,
168*bb4ee6a4SAndroid Build Coastguard Worker }
169*bb4ee6a4SAndroid Build Coastguard Worker 
170*bb4ee6a4SAndroid Build Coastguard Worker impl VfioMsiCap {
new( config: &VfioPciConfig, msi_cap_start: u32, vm_socket_irq: Tube, device_id: u32, device_name: String, ) -> Self171*bb4ee6a4SAndroid Build Coastguard Worker     fn new(
172*bb4ee6a4SAndroid Build Coastguard Worker         config: &VfioPciConfig,
173*bb4ee6a4SAndroid Build Coastguard Worker         msi_cap_start: u32,
174*bb4ee6a4SAndroid Build Coastguard Worker         vm_socket_irq: Tube,
175*bb4ee6a4SAndroid Build Coastguard Worker         device_id: u32,
176*bb4ee6a4SAndroid Build Coastguard Worker         device_name: String,
177*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Self {
178*bb4ee6a4SAndroid Build Coastguard Worker         let msi_ctl: u16 = config.read_config(msi_cap_start + PCI_MSI_FLAGS);
179*bb4ee6a4SAndroid Build Coastguard Worker         let is_64bit = (msi_ctl & PCI_MSI_FLAGS_64BIT) != 0;
180*bb4ee6a4SAndroid Build Coastguard Worker         let mask_cap = (msi_ctl & PCI_MSI_FLAGS_MASKBIT) != 0;
181*bb4ee6a4SAndroid Build Coastguard Worker 
182*bb4ee6a4SAndroid Build Coastguard Worker         VfioMsiCap {
183*bb4ee6a4SAndroid Build Coastguard Worker             config: MsiConfig::new(is_64bit, mask_cap, vm_socket_irq, device_id, device_name),
184*bb4ee6a4SAndroid Build Coastguard Worker             offset: msi_cap_start,
185*bb4ee6a4SAndroid Build Coastguard Worker         }
186*bb4ee6a4SAndroid Build Coastguard Worker     }
187*bb4ee6a4SAndroid Build Coastguard Worker 
is_msi_reg(&self, index: u64, len: usize) -> bool188*bb4ee6a4SAndroid Build Coastguard Worker     fn is_msi_reg(&self, index: u64, len: usize) -> bool {
189*bb4ee6a4SAndroid Build Coastguard Worker         self.config.is_msi_reg(self.offset, index, len)
190*bb4ee6a4SAndroid Build Coastguard Worker     }
191*bb4ee6a4SAndroid Build Coastguard Worker 
write_msi_reg(&mut self, index: u64, data: &[u8]) -> Option<VfioMsiChange>192*bb4ee6a4SAndroid Build Coastguard Worker     fn write_msi_reg(&mut self, index: u64, data: &[u8]) -> Option<VfioMsiChange> {
193*bb4ee6a4SAndroid Build Coastguard Worker         let offset = index as u32 - self.offset;
194*bb4ee6a4SAndroid Build Coastguard Worker         match self.config.write_msi_capability(offset, data) {
195*bb4ee6a4SAndroid Build Coastguard Worker             MsiStatus::Enabled => Some(VfioMsiChange::Enable),
196*bb4ee6a4SAndroid Build Coastguard Worker             MsiStatus::Disabled => Some(VfioMsiChange::Disable),
197*bb4ee6a4SAndroid Build Coastguard Worker             MsiStatus::NothingToDo => None,
198*bb4ee6a4SAndroid Build Coastguard Worker         }
199*bb4ee6a4SAndroid Build Coastguard Worker     }
200*bb4ee6a4SAndroid Build Coastguard Worker 
get_msi_irqfd(&self) -> Option<&Event>201*bb4ee6a4SAndroid Build Coastguard Worker     fn get_msi_irqfd(&self) -> Option<&Event> {
202*bb4ee6a4SAndroid Build Coastguard Worker         self.config.get_irqfd()
203*bb4ee6a4SAndroid Build Coastguard Worker     }
204*bb4ee6a4SAndroid Build Coastguard Worker 
destroy(&mut self)205*bb4ee6a4SAndroid Build Coastguard Worker     fn destroy(&mut self) {
206*bb4ee6a4SAndroid Build Coastguard Worker         self.config.destroy()
207*bb4ee6a4SAndroid Build Coastguard Worker     }
208*bb4ee6a4SAndroid Build Coastguard Worker }
209*bb4ee6a4SAndroid Build Coastguard Worker 
210*bb4ee6a4SAndroid Build Coastguard Worker // MSI-X registers in MSI-X capability
211*bb4ee6a4SAndroid Build Coastguard Worker const PCI_MSIX_FLAGS: u32 = 0x02; // Message Control
212*bb4ee6a4SAndroid Build Coastguard Worker const PCI_MSIX_FLAGS_QSIZE: u16 = 0x07FF; // Table size
213*bb4ee6a4SAndroid Build Coastguard Worker const PCI_MSIX_TABLE: u32 = 0x04; // Table offset
214*bb4ee6a4SAndroid Build Coastguard Worker const PCI_MSIX_TABLE_BIR: u32 = 0x07; // BAR index
215*bb4ee6a4SAndroid Build Coastguard Worker const PCI_MSIX_TABLE_OFFSET: u32 = 0xFFFFFFF8; // Offset into specified BAR
216*bb4ee6a4SAndroid Build Coastguard Worker const PCI_MSIX_PBA: u32 = 0x08; // Pending bit Array offset
217*bb4ee6a4SAndroid Build Coastguard Worker const PCI_MSIX_PBA_BIR: u32 = 0x07; // BAR index
218*bb4ee6a4SAndroid Build Coastguard Worker const PCI_MSIX_PBA_OFFSET: u32 = 0xFFFFFFF8; // Offset into specified BAR
219*bb4ee6a4SAndroid Build Coastguard Worker 
220*bb4ee6a4SAndroid Build Coastguard Worker struct VfioMsixCap {
221*bb4ee6a4SAndroid Build Coastguard Worker     config: MsixConfig,
222*bb4ee6a4SAndroid Build Coastguard Worker     offset: u32,
223*bb4ee6a4SAndroid Build Coastguard Worker     table_size: u16,
224*bb4ee6a4SAndroid Build Coastguard Worker     table_pci_bar: PciBarIndex,
225*bb4ee6a4SAndroid Build Coastguard Worker     table_offset: u64,
226*bb4ee6a4SAndroid Build Coastguard Worker     table_size_bytes: u64,
227*bb4ee6a4SAndroid Build Coastguard Worker     pba_pci_bar: PciBarIndex,
228*bb4ee6a4SAndroid Build Coastguard Worker     pba_offset: u64,
229*bb4ee6a4SAndroid Build Coastguard Worker     pba_size_bytes: u64,
230*bb4ee6a4SAndroid Build Coastguard Worker     msix_interrupt_evt: Vec<Event>,
231*bb4ee6a4SAndroid Build Coastguard Worker }
232*bb4ee6a4SAndroid Build Coastguard Worker 
233*bb4ee6a4SAndroid Build Coastguard Worker impl VfioMsixCap {
new( config: &VfioPciConfig, msix_cap_start: u32, vm_socket_irq: Tube, pci_id: u32, device_name: String, ) -> Self234*bb4ee6a4SAndroid Build Coastguard Worker     fn new(
235*bb4ee6a4SAndroid Build Coastguard Worker         config: &VfioPciConfig,
236*bb4ee6a4SAndroid Build Coastguard Worker         msix_cap_start: u32,
237*bb4ee6a4SAndroid Build Coastguard Worker         vm_socket_irq: Tube,
238*bb4ee6a4SAndroid Build Coastguard Worker         pci_id: u32,
239*bb4ee6a4SAndroid Build Coastguard Worker         device_name: String,
240*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Self {
241*bb4ee6a4SAndroid Build Coastguard Worker         let msix_ctl: u16 = config.read_config(msix_cap_start + PCI_MSIX_FLAGS);
242*bb4ee6a4SAndroid Build Coastguard Worker         let table: u32 = config.read_config(msix_cap_start + PCI_MSIX_TABLE);
243*bb4ee6a4SAndroid Build Coastguard Worker         let table_pci_bar = (table & PCI_MSIX_TABLE_BIR) as PciBarIndex;
244*bb4ee6a4SAndroid Build Coastguard Worker         let table_offset = (table & PCI_MSIX_TABLE_OFFSET) as u64;
245*bb4ee6a4SAndroid Build Coastguard Worker         let pba: u32 = config.read_config(msix_cap_start + PCI_MSIX_PBA);
246*bb4ee6a4SAndroid Build Coastguard Worker         let pba_pci_bar = (pba & PCI_MSIX_PBA_BIR) as PciBarIndex;
247*bb4ee6a4SAndroid Build Coastguard Worker         let pba_offset = (pba & PCI_MSIX_PBA_OFFSET) as u64;
248*bb4ee6a4SAndroid Build Coastguard Worker 
249*bb4ee6a4SAndroid Build Coastguard Worker         let mut table_size = (msix_ctl & PCI_MSIX_FLAGS_QSIZE) as u64 + 1;
250*bb4ee6a4SAndroid Build Coastguard Worker         if table_pci_bar == pba_pci_bar
251*bb4ee6a4SAndroid Build Coastguard Worker             && pba_offset > table_offset
252*bb4ee6a4SAndroid Build Coastguard Worker             && (table_offset + table_size * MSIX_TABLE_ENTRIES_MODULO) > pba_offset
253*bb4ee6a4SAndroid Build Coastguard Worker         {
254*bb4ee6a4SAndroid Build Coastguard Worker             table_size = (pba_offset - table_offset) / MSIX_TABLE_ENTRIES_MODULO;
255*bb4ee6a4SAndroid Build Coastguard Worker         }
256*bb4ee6a4SAndroid Build Coastguard Worker 
257*bb4ee6a4SAndroid Build Coastguard Worker         let table_size_bytes = table_size * MSIX_TABLE_ENTRIES_MODULO;
258*bb4ee6a4SAndroid Build Coastguard Worker         let pba_size_bytes = ((table_size + BITS_PER_PBA_ENTRY as u64 - 1)
259*bb4ee6a4SAndroid Build Coastguard Worker             / BITS_PER_PBA_ENTRY as u64)
260*bb4ee6a4SAndroid Build Coastguard Worker             * MSIX_PBA_ENTRIES_MODULO;
261*bb4ee6a4SAndroid Build Coastguard Worker         let mut msix_interrupt_evt = Vec::new();
262*bb4ee6a4SAndroid Build Coastguard Worker         for _ in 0..table_size {
263*bb4ee6a4SAndroid Build Coastguard Worker             msix_interrupt_evt.push(Event::new().expect("failed to create msix interrupt"));
264*bb4ee6a4SAndroid Build Coastguard Worker         }
265*bb4ee6a4SAndroid Build Coastguard Worker         VfioMsixCap {
266*bb4ee6a4SAndroid Build Coastguard Worker             config: MsixConfig::new(table_size as u16, vm_socket_irq, pci_id, device_name),
267*bb4ee6a4SAndroid Build Coastguard Worker             offset: msix_cap_start,
268*bb4ee6a4SAndroid Build Coastguard Worker             table_size: table_size as u16,
269*bb4ee6a4SAndroid Build Coastguard Worker             table_pci_bar,
270*bb4ee6a4SAndroid Build Coastguard Worker             table_offset,
271*bb4ee6a4SAndroid Build Coastguard Worker             table_size_bytes,
272*bb4ee6a4SAndroid Build Coastguard Worker             pba_pci_bar,
273*bb4ee6a4SAndroid Build Coastguard Worker             pba_offset,
274*bb4ee6a4SAndroid Build Coastguard Worker             pba_size_bytes,
275*bb4ee6a4SAndroid Build Coastguard Worker             msix_interrupt_evt,
276*bb4ee6a4SAndroid Build Coastguard Worker         }
277*bb4ee6a4SAndroid Build Coastguard Worker     }
278*bb4ee6a4SAndroid Build Coastguard Worker 
279*bb4ee6a4SAndroid Build Coastguard Worker     // only msix control register is writable and need special handle in pci r/w
is_msix_control_reg(&self, offset: u32, size: u32) -> bool280*bb4ee6a4SAndroid Build Coastguard Worker     fn is_msix_control_reg(&self, offset: u32, size: u32) -> bool {
281*bb4ee6a4SAndroid Build Coastguard Worker         let control_start = self.offset + PCI_MSIX_FLAGS;
282*bb4ee6a4SAndroid Build Coastguard Worker         let control_end = control_start + 2;
283*bb4ee6a4SAndroid Build Coastguard Worker 
284*bb4ee6a4SAndroid Build Coastguard Worker         offset < control_end && offset + size > control_start
285*bb4ee6a4SAndroid Build Coastguard Worker     }
286*bb4ee6a4SAndroid Build Coastguard Worker 
read_msix_control(&self, data: &mut u32)287*bb4ee6a4SAndroid Build Coastguard Worker     fn read_msix_control(&self, data: &mut u32) {
288*bb4ee6a4SAndroid Build Coastguard Worker         *data = self.config.read_msix_capability(*data);
289*bb4ee6a4SAndroid Build Coastguard Worker     }
290*bb4ee6a4SAndroid Build Coastguard Worker 
write_msix_control(&mut self, data: &[u8]) -> Option<VfioMsiChange>291*bb4ee6a4SAndroid Build Coastguard Worker     fn write_msix_control(&mut self, data: &[u8]) -> Option<VfioMsiChange> {
292*bb4ee6a4SAndroid Build Coastguard Worker         let old_enabled = self.config.enabled();
293*bb4ee6a4SAndroid Build Coastguard Worker         let old_masked = self.config.masked();
294*bb4ee6a4SAndroid Build Coastguard Worker 
295*bb4ee6a4SAndroid Build Coastguard Worker         self.config
296*bb4ee6a4SAndroid Build Coastguard Worker             .write_msix_capability(PCI_MSIX_FLAGS.into(), data);
297*bb4ee6a4SAndroid Build Coastguard Worker 
298*bb4ee6a4SAndroid Build Coastguard Worker         let new_enabled = self.config.enabled();
299*bb4ee6a4SAndroid Build Coastguard Worker         let new_masked = self.config.masked();
300*bb4ee6a4SAndroid Build Coastguard Worker 
301*bb4ee6a4SAndroid Build Coastguard Worker         if !old_enabled && new_enabled {
302*bb4ee6a4SAndroid Build Coastguard Worker             Some(VfioMsiChange::Enable)
303*bb4ee6a4SAndroid Build Coastguard Worker         } else if old_enabled && !new_enabled {
304*bb4ee6a4SAndroid Build Coastguard Worker             Some(VfioMsiChange::Disable)
305*bb4ee6a4SAndroid Build Coastguard Worker         } else if new_enabled && old_masked != new_masked {
306*bb4ee6a4SAndroid Build Coastguard Worker             Some(VfioMsiChange::FunctionChanged)
307*bb4ee6a4SAndroid Build Coastguard Worker         } else {
308*bb4ee6a4SAndroid Build Coastguard Worker             None
309*bb4ee6a4SAndroid Build Coastguard Worker         }
310*bb4ee6a4SAndroid Build Coastguard Worker     }
311*bb4ee6a4SAndroid Build Coastguard Worker 
is_msix_table(&self, bar_index: PciBarIndex, offset: u64) -> bool312*bb4ee6a4SAndroid Build Coastguard Worker     fn is_msix_table(&self, bar_index: PciBarIndex, offset: u64) -> bool {
313*bb4ee6a4SAndroid Build Coastguard Worker         bar_index == self.table_pci_bar
314*bb4ee6a4SAndroid Build Coastguard Worker             && offset >= self.table_offset
315*bb4ee6a4SAndroid Build Coastguard Worker             && offset < self.table_offset + self.table_size_bytes
316*bb4ee6a4SAndroid Build Coastguard Worker     }
317*bb4ee6a4SAndroid Build Coastguard Worker 
get_msix_table(&self, bar_index: PciBarIndex) -> Option<AddressRange>318*bb4ee6a4SAndroid Build Coastguard Worker     fn get_msix_table(&self, bar_index: PciBarIndex) -> Option<AddressRange> {
319*bb4ee6a4SAndroid Build Coastguard Worker         if bar_index == self.table_pci_bar {
320*bb4ee6a4SAndroid Build Coastguard Worker             AddressRange::from_start_and_size(self.table_offset, self.table_size_bytes)
321*bb4ee6a4SAndroid Build Coastguard Worker         } else {
322*bb4ee6a4SAndroid Build Coastguard Worker             None
323*bb4ee6a4SAndroid Build Coastguard Worker         }
324*bb4ee6a4SAndroid Build Coastguard Worker     }
325*bb4ee6a4SAndroid Build Coastguard Worker 
read_table(&self, offset: u64, data: &mut [u8])326*bb4ee6a4SAndroid Build Coastguard Worker     fn read_table(&self, offset: u64, data: &mut [u8]) {
327*bb4ee6a4SAndroid Build Coastguard Worker         let offset = offset - self.table_offset;
328*bb4ee6a4SAndroid Build Coastguard Worker         self.config.read_msix_table(offset, data);
329*bb4ee6a4SAndroid Build Coastguard Worker     }
330*bb4ee6a4SAndroid Build Coastguard Worker 
write_table(&mut self, offset: u64, data: &[u8]) -> MsixStatus331*bb4ee6a4SAndroid Build Coastguard Worker     fn write_table(&mut self, offset: u64, data: &[u8]) -> MsixStatus {
332*bb4ee6a4SAndroid Build Coastguard Worker         let offset = offset - self.table_offset;
333*bb4ee6a4SAndroid Build Coastguard Worker         self.config.write_msix_table(offset, data)
334*bb4ee6a4SAndroid Build Coastguard Worker     }
335*bb4ee6a4SAndroid Build Coastguard Worker 
is_msix_pba(&self, bar_index: PciBarIndex, offset: u64) -> bool336*bb4ee6a4SAndroid Build Coastguard Worker     fn is_msix_pba(&self, bar_index: PciBarIndex, offset: u64) -> bool {
337*bb4ee6a4SAndroid Build Coastguard Worker         bar_index == self.pba_pci_bar
338*bb4ee6a4SAndroid Build Coastguard Worker             && offset >= self.pba_offset
339*bb4ee6a4SAndroid Build Coastguard Worker             && offset < self.pba_offset + self.pba_size_bytes
340*bb4ee6a4SAndroid Build Coastguard Worker     }
341*bb4ee6a4SAndroid Build Coastguard Worker 
get_msix_pba(&self, bar_index: PciBarIndex) -> Option<AddressRange>342*bb4ee6a4SAndroid Build Coastguard Worker     fn get_msix_pba(&self, bar_index: PciBarIndex) -> Option<AddressRange> {
343*bb4ee6a4SAndroid Build Coastguard Worker         if bar_index == self.pba_pci_bar {
344*bb4ee6a4SAndroid Build Coastguard Worker             AddressRange::from_start_and_size(self.pba_offset, self.pba_size_bytes)
345*bb4ee6a4SAndroid Build Coastguard Worker         } else {
346*bb4ee6a4SAndroid Build Coastguard Worker             None
347*bb4ee6a4SAndroid Build Coastguard Worker         }
348*bb4ee6a4SAndroid Build Coastguard Worker     }
349*bb4ee6a4SAndroid Build Coastguard Worker 
read_pba(&self, offset: u64, data: &mut [u8])350*bb4ee6a4SAndroid Build Coastguard Worker     fn read_pba(&self, offset: u64, data: &mut [u8]) {
351*bb4ee6a4SAndroid Build Coastguard Worker         let offset = offset - self.pba_offset;
352*bb4ee6a4SAndroid Build Coastguard Worker         self.config.read_pba_entries(offset, data);
353*bb4ee6a4SAndroid Build Coastguard Worker     }
354*bb4ee6a4SAndroid Build Coastguard Worker 
write_pba(&mut self, offset: u64, data: &[u8])355*bb4ee6a4SAndroid Build Coastguard Worker     fn write_pba(&mut self, offset: u64, data: &[u8]) {
356*bb4ee6a4SAndroid Build Coastguard Worker         let offset = offset - self.pba_offset;
357*bb4ee6a4SAndroid Build Coastguard Worker         self.config.write_pba_entries(offset, data);
358*bb4ee6a4SAndroid Build Coastguard Worker     }
359*bb4ee6a4SAndroid Build Coastguard Worker 
get_msix_irqfd(&self, index: usize) -> Option<&Event>360*bb4ee6a4SAndroid Build Coastguard Worker     fn get_msix_irqfd(&self, index: usize) -> Option<&Event> {
361*bb4ee6a4SAndroid Build Coastguard Worker         let irqfd = self.config.get_irqfd(index);
362*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(fd) = irqfd {
363*bb4ee6a4SAndroid Build Coastguard Worker             if self.msix_vector_masked(index) {
364*bb4ee6a4SAndroid Build Coastguard Worker                 Some(&self.msix_interrupt_evt[index])
365*bb4ee6a4SAndroid Build Coastguard Worker             } else {
366*bb4ee6a4SAndroid Build Coastguard Worker                 Some(fd)
367*bb4ee6a4SAndroid Build Coastguard Worker             }
368*bb4ee6a4SAndroid Build Coastguard Worker         } else {
369*bb4ee6a4SAndroid Build Coastguard Worker             None
370*bb4ee6a4SAndroid Build Coastguard Worker         }
371*bb4ee6a4SAndroid Build Coastguard Worker     }
372*bb4ee6a4SAndroid Build Coastguard Worker 
get_msix_irqfds(&self) -> Vec<Option<&Event>>373*bb4ee6a4SAndroid Build Coastguard Worker     fn get_msix_irqfds(&self) -> Vec<Option<&Event>> {
374*bb4ee6a4SAndroid Build Coastguard Worker         let mut irqfds = Vec::new();
375*bb4ee6a4SAndroid Build Coastguard Worker 
376*bb4ee6a4SAndroid Build Coastguard Worker         for i in 0..self.table_size {
377*bb4ee6a4SAndroid Build Coastguard Worker             irqfds.push(self.get_msix_irqfd(i as usize));
378*bb4ee6a4SAndroid Build Coastguard Worker         }
379*bb4ee6a4SAndroid Build Coastguard Worker 
380*bb4ee6a4SAndroid Build Coastguard Worker         irqfds
381*bb4ee6a4SAndroid Build Coastguard Worker     }
382*bb4ee6a4SAndroid Build Coastguard Worker 
table_size(&self) -> usize383*bb4ee6a4SAndroid Build Coastguard Worker     fn table_size(&self) -> usize {
384*bb4ee6a4SAndroid Build Coastguard Worker         self.table_size.into()
385*bb4ee6a4SAndroid Build Coastguard Worker     }
386*bb4ee6a4SAndroid Build Coastguard Worker 
clone_msix_evt(&self) -> Vec<Event>387*bb4ee6a4SAndroid Build Coastguard Worker     fn clone_msix_evt(&self) -> Vec<Event> {
388*bb4ee6a4SAndroid Build Coastguard Worker         self.msix_interrupt_evt
389*bb4ee6a4SAndroid Build Coastguard Worker             .iter()
390*bb4ee6a4SAndroid Build Coastguard Worker             .map(|irq| irq.try_clone().unwrap())
391*bb4ee6a4SAndroid Build Coastguard Worker             .collect()
392*bb4ee6a4SAndroid Build Coastguard Worker     }
393*bb4ee6a4SAndroid Build Coastguard Worker 
msix_vector_masked(&self, index: usize) -> bool394*bb4ee6a4SAndroid Build Coastguard Worker     fn msix_vector_masked(&self, index: usize) -> bool {
395*bb4ee6a4SAndroid Build Coastguard Worker         !self.config.enabled() || self.config.masked() || self.config.table_masked(index)
396*bb4ee6a4SAndroid Build Coastguard Worker     }
397*bb4ee6a4SAndroid Build Coastguard Worker 
trigger(&mut self, index: usize)398*bb4ee6a4SAndroid Build Coastguard Worker     fn trigger(&mut self, index: usize) {
399*bb4ee6a4SAndroid Build Coastguard Worker         self.config.trigger(index as u16);
400*bb4ee6a4SAndroid Build Coastguard Worker     }
401*bb4ee6a4SAndroid Build Coastguard Worker 
destroy(&mut self)402*bb4ee6a4SAndroid Build Coastguard Worker     fn destroy(&mut self) {
403*bb4ee6a4SAndroid Build Coastguard Worker         self.config.destroy()
404*bb4ee6a4SAndroid Build Coastguard Worker     }
405*bb4ee6a4SAndroid Build Coastguard Worker }
406*bb4ee6a4SAndroid Build Coastguard Worker 
407*bb4ee6a4SAndroid Build Coastguard Worker struct VfioResourceAllocator {
408*bb4ee6a4SAndroid Build Coastguard Worker     // The region that is not allocated yet.
409*bb4ee6a4SAndroid Build Coastguard Worker     regions: BTreeSet<AddressRange>,
410*bb4ee6a4SAndroid Build Coastguard Worker }
411*bb4ee6a4SAndroid Build Coastguard Worker 
412*bb4ee6a4SAndroid Build Coastguard Worker impl VfioResourceAllocator {
413*bb4ee6a4SAndroid Build Coastguard Worker     // Creates a new `VfioResourceAllocator` for managing VFIO resources.
414*bb4ee6a4SAndroid Build Coastguard Worker     // Can return `Err` if `base` + `size` overflows a u64.
415*bb4ee6a4SAndroid Build Coastguard Worker     //
416*bb4ee6a4SAndroid Build Coastguard Worker     // * `base` - The starting address of the range to manage.
417*bb4ee6a4SAndroid Build Coastguard Worker     // * `size` - The size of the address range in bytes.
new(pool: AddressRange) -> Result<Self, PciDeviceError>418*bb4ee6a4SAndroid Build Coastguard Worker     fn new(pool: AddressRange) -> Result<Self, PciDeviceError> {
419*bb4ee6a4SAndroid Build Coastguard Worker         if pool.is_empty() {
420*bb4ee6a4SAndroid Build Coastguard Worker             return Err(PciDeviceError::SizeZero);
421*bb4ee6a4SAndroid Build Coastguard Worker         }
422*bb4ee6a4SAndroid Build Coastguard Worker         let mut regions = BTreeSet::new();
423*bb4ee6a4SAndroid Build Coastguard Worker         regions.insert(pool);
424*bb4ee6a4SAndroid Build Coastguard Worker         Ok(VfioResourceAllocator { regions })
425*bb4ee6a4SAndroid Build Coastguard Worker     }
426*bb4ee6a4SAndroid Build Coastguard Worker 
internal_allocate_from_slot( &mut self, slot: AddressRange, range: AddressRange, ) -> Result<u64, PciDeviceError>427*bb4ee6a4SAndroid Build Coastguard Worker     fn internal_allocate_from_slot(
428*bb4ee6a4SAndroid Build Coastguard Worker         &mut self,
429*bb4ee6a4SAndroid Build Coastguard Worker         slot: AddressRange,
430*bb4ee6a4SAndroid Build Coastguard Worker         range: AddressRange,
431*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Result<u64, PciDeviceError> {
432*bb4ee6a4SAndroid Build Coastguard Worker         let slot_was_present = self.regions.remove(&slot);
433*bb4ee6a4SAndroid Build Coastguard Worker         assert!(slot_was_present);
434*bb4ee6a4SAndroid Build Coastguard Worker 
435*bb4ee6a4SAndroid Build Coastguard Worker         let (before, after) = slot.non_overlapping_ranges(range);
436*bb4ee6a4SAndroid Build Coastguard Worker 
437*bb4ee6a4SAndroid Build Coastguard Worker         if !before.is_empty() {
438*bb4ee6a4SAndroid Build Coastguard Worker             self.regions.insert(before);
439*bb4ee6a4SAndroid Build Coastguard Worker         }
440*bb4ee6a4SAndroid Build Coastguard Worker         if !after.is_empty() {
441*bb4ee6a4SAndroid Build Coastguard Worker             self.regions.insert(after);
442*bb4ee6a4SAndroid Build Coastguard Worker         }
443*bb4ee6a4SAndroid Build Coastguard Worker 
444*bb4ee6a4SAndroid Build Coastguard Worker         Ok(range.start)
445*bb4ee6a4SAndroid Build Coastguard Worker     }
446*bb4ee6a4SAndroid Build Coastguard Worker 
447*bb4ee6a4SAndroid Build Coastguard Worker     // Allocates a range of addresses from the managed region with a minimal alignment.
448*bb4ee6a4SAndroid Build Coastguard Worker     // Overlapping with a previous allocation is _not_ allowed.
449*bb4ee6a4SAndroid Build Coastguard Worker     // Returns allocated address.
allocate_with_align(&mut self, size: u64, alignment: u64) -> Result<u64, PciDeviceError>450*bb4ee6a4SAndroid Build Coastguard Worker     fn allocate_with_align(&mut self, size: u64, alignment: u64) -> Result<u64, PciDeviceError> {
451*bb4ee6a4SAndroid Build Coastguard Worker         if size == 0 {
452*bb4ee6a4SAndroid Build Coastguard Worker             return Err(PciDeviceError::SizeZero);
453*bb4ee6a4SAndroid Build Coastguard Worker         }
454*bb4ee6a4SAndroid Build Coastguard Worker         if !alignment.is_power_of_two() {
455*bb4ee6a4SAndroid Build Coastguard Worker             return Err(PciDeviceError::BadAlignment);
456*bb4ee6a4SAndroid Build Coastguard Worker         }
457*bb4ee6a4SAndroid Build Coastguard Worker 
458*bb4ee6a4SAndroid Build Coastguard Worker         // finds first region matching alignment and size.
459*bb4ee6a4SAndroid Build Coastguard Worker         let region = self.regions.iter().find(|range| {
460*bb4ee6a4SAndroid Build Coastguard Worker             match range.start % alignment {
461*bb4ee6a4SAndroid Build Coastguard Worker                 0 => range.start.checked_add(size - 1),
462*bb4ee6a4SAndroid Build Coastguard Worker                 r => range.start.checked_add(size - 1 + alignment - r),
463*bb4ee6a4SAndroid Build Coastguard Worker             }
464*bb4ee6a4SAndroid Build Coastguard Worker             .map_or(false, |end| end <= range.end)
465*bb4ee6a4SAndroid Build Coastguard Worker         });
466*bb4ee6a4SAndroid Build Coastguard Worker 
467*bb4ee6a4SAndroid Build Coastguard Worker         match region {
468*bb4ee6a4SAndroid Build Coastguard Worker             Some(&slot) => {
469*bb4ee6a4SAndroid Build Coastguard Worker                 let start = match slot.start % alignment {
470*bb4ee6a4SAndroid Build Coastguard Worker                     0 => slot.start,
471*bb4ee6a4SAndroid Build Coastguard Worker                     r => slot.start + alignment - r,
472*bb4ee6a4SAndroid Build Coastguard Worker                 };
473*bb4ee6a4SAndroid Build Coastguard Worker                 let end = start + size - 1;
474*bb4ee6a4SAndroid Build Coastguard Worker                 let range = AddressRange::from_start_and_end(start, end);
475*bb4ee6a4SAndroid Build Coastguard Worker 
476*bb4ee6a4SAndroid Build Coastguard Worker                 self.internal_allocate_from_slot(slot, range)
477*bb4ee6a4SAndroid Build Coastguard Worker             }
478*bb4ee6a4SAndroid Build Coastguard Worker             None => Err(PciDeviceError::OutOfSpace),
479*bb4ee6a4SAndroid Build Coastguard Worker         }
480*bb4ee6a4SAndroid Build Coastguard Worker     }
481*bb4ee6a4SAndroid Build Coastguard Worker 
482*bb4ee6a4SAndroid Build Coastguard Worker     // Allocates a range of addresses from the managed region with a required location.
483*bb4ee6a4SAndroid Build Coastguard Worker     // Overlapping with a previous allocation is allowed.
allocate_at_can_overlap(&mut self, range: AddressRange) -> Result<(), PciDeviceError>484*bb4ee6a4SAndroid Build Coastguard Worker     fn allocate_at_can_overlap(&mut self, range: AddressRange) -> Result<(), PciDeviceError> {
485*bb4ee6a4SAndroid Build Coastguard Worker         if range.is_empty() {
486*bb4ee6a4SAndroid Build Coastguard Worker             return Err(PciDeviceError::SizeZero);
487*bb4ee6a4SAndroid Build Coastguard Worker         }
488*bb4ee6a4SAndroid Build Coastguard Worker 
489*bb4ee6a4SAndroid Build Coastguard Worker         while let Some(&slot) = self
490*bb4ee6a4SAndroid Build Coastguard Worker             .regions
491*bb4ee6a4SAndroid Build Coastguard Worker             .iter()
492*bb4ee6a4SAndroid Build Coastguard Worker             .find(|avail_range| avail_range.overlaps(range))
493*bb4ee6a4SAndroid Build Coastguard Worker         {
494*bb4ee6a4SAndroid Build Coastguard Worker             let _address = self.internal_allocate_from_slot(slot, range)?;
495*bb4ee6a4SAndroid Build Coastguard Worker         }
496*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
497*bb4ee6a4SAndroid Build Coastguard Worker     }
498*bb4ee6a4SAndroid Build Coastguard Worker }
499*bb4ee6a4SAndroid Build Coastguard Worker 
500*bb4ee6a4SAndroid Build Coastguard Worker struct VfioPciWorker {
501*bb4ee6a4SAndroid Build Coastguard Worker     address: PciAddress,
502*bb4ee6a4SAndroid Build Coastguard Worker     sysfs_path: PathBuf,
503*bb4ee6a4SAndroid Build Coastguard Worker     vm_socket: Tube,
504*bb4ee6a4SAndroid Build Coastguard Worker     name: String,
505*bb4ee6a4SAndroid Build Coastguard Worker     pm_cap: Option<Arc<Mutex<VfioPmCap>>>,
506*bb4ee6a4SAndroid Build Coastguard Worker     msix_cap: Option<Arc<Mutex<VfioMsixCap>>>,
507*bb4ee6a4SAndroid Build Coastguard Worker }
508*bb4ee6a4SAndroid Build Coastguard Worker 
509*bb4ee6a4SAndroid Build Coastguard Worker impl VfioPciWorker {
run( &mut self, req_irq_evt: Event, wakeup_evt: Event, acpi_notify_evt: Event, kill_evt: Event, msix_evt: Vec<Event>, is_in_low_power: Arc<Mutex<bool>>, gpe: Option<u32>, notification_val: Arc<Mutex<Vec<u32>>>, )510*bb4ee6a4SAndroid Build Coastguard Worker     fn run(
511*bb4ee6a4SAndroid Build Coastguard Worker         &mut self,
512*bb4ee6a4SAndroid Build Coastguard Worker         req_irq_evt: Event,
513*bb4ee6a4SAndroid Build Coastguard Worker         wakeup_evt: Event,
514*bb4ee6a4SAndroid Build Coastguard Worker         acpi_notify_evt: Event,
515*bb4ee6a4SAndroid Build Coastguard Worker         kill_evt: Event,
516*bb4ee6a4SAndroid Build Coastguard Worker         msix_evt: Vec<Event>,
517*bb4ee6a4SAndroid Build Coastguard Worker         is_in_low_power: Arc<Mutex<bool>>,
518*bb4ee6a4SAndroid Build Coastguard Worker         gpe: Option<u32>,
519*bb4ee6a4SAndroid Build Coastguard Worker         notification_val: Arc<Mutex<Vec<u32>>>,
520*bb4ee6a4SAndroid Build Coastguard Worker     ) {
521*bb4ee6a4SAndroid Build Coastguard Worker         #[derive(EventToken, Debug)]
522*bb4ee6a4SAndroid Build Coastguard Worker         enum Token {
523*bb4ee6a4SAndroid Build Coastguard Worker             ReqIrq,
524*bb4ee6a4SAndroid Build Coastguard Worker             WakeUp,
525*bb4ee6a4SAndroid Build Coastguard Worker             AcpiNotifyEvent,
526*bb4ee6a4SAndroid Build Coastguard Worker             Kill,
527*bb4ee6a4SAndroid Build Coastguard Worker             MsixIrqi { index: usize },
528*bb4ee6a4SAndroid Build Coastguard Worker         }
529*bb4ee6a4SAndroid Build Coastguard Worker 
530*bb4ee6a4SAndroid Build Coastguard Worker         let wait_ctx: WaitContext<Token> = match WaitContext::build_with(&[
531*bb4ee6a4SAndroid Build Coastguard Worker             (&req_irq_evt, Token::ReqIrq),
532*bb4ee6a4SAndroid Build Coastguard Worker             (&wakeup_evt, Token::WakeUp),
533*bb4ee6a4SAndroid Build Coastguard Worker             (&acpi_notify_evt, Token::AcpiNotifyEvent),
534*bb4ee6a4SAndroid Build Coastguard Worker             (&kill_evt, Token::Kill),
535*bb4ee6a4SAndroid Build Coastguard Worker         ]) {
536*bb4ee6a4SAndroid Build Coastguard Worker             Ok(pc) => pc,
537*bb4ee6a4SAndroid Build Coastguard Worker             Err(e) => {
538*bb4ee6a4SAndroid Build Coastguard Worker                 error!(
539*bb4ee6a4SAndroid Build Coastguard Worker                     "{} failed creating vfio WaitContext: {}",
540*bb4ee6a4SAndroid Build Coastguard Worker                     self.name.clone(),
541*bb4ee6a4SAndroid Build Coastguard Worker                     e
542*bb4ee6a4SAndroid Build Coastguard Worker                 );
543*bb4ee6a4SAndroid Build Coastguard Worker                 return;
544*bb4ee6a4SAndroid Build Coastguard Worker             }
545*bb4ee6a4SAndroid Build Coastguard Worker         };
546*bb4ee6a4SAndroid Build Coastguard Worker 
547*bb4ee6a4SAndroid Build Coastguard Worker         for (index, msix_int) in msix_evt.iter().enumerate() {
548*bb4ee6a4SAndroid Build Coastguard Worker             wait_ctx
549*bb4ee6a4SAndroid Build Coastguard Worker                 .add(msix_int, Token::MsixIrqi { index })
550*bb4ee6a4SAndroid Build Coastguard Worker                 .expect("Failed to create vfio WaitContext for msix interrupt event")
551*bb4ee6a4SAndroid Build Coastguard Worker         }
552*bb4ee6a4SAndroid Build Coastguard Worker 
553*bb4ee6a4SAndroid Build Coastguard Worker         'wait: loop {
554*bb4ee6a4SAndroid Build Coastguard Worker             let events = match wait_ctx.wait() {
555*bb4ee6a4SAndroid Build Coastguard Worker                 Ok(v) => v,
556*bb4ee6a4SAndroid Build Coastguard Worker                 Err(e) => {
557*bb4ee6a4SAndroid Build Coastguard Worker                     error!("{} failed polling vfio events: {}", self.name.clone(), e);
558*bb4ee6a4SAndroid Build Coastguard Worker                     break;
559*bb4ee6a4SAndroid Build Coastguard Worker                 }
560*bb4ee6a4SAndroid Build Coastguard Worker             };
561*bb4ee6a4SAndroid Build Coastguard Worker 
562*bb4ee6a4SAndroid Build Coastguard Worker             for event in events.iter().filter(|e| e.is_readable) {
563*bb4ee6a4SAndroid Build Coastguard Worker                 match event.token {
564*bb4ee6a4SAndroid Build Coastguard Worker                     Token::MsixIrqi { index } => {
565*bb4ee6a4SAndroid Build Coastguard Worker                         if let Some(msix_cap) = &self.msix_cap {
566*bb4ee6a4SAndroid Build Coastguard Worker                             msix_cap.lock().trigger(index);
567*bb4ee6a4SAndroid Build Coastguard Worker                         }
568*bb4ee6a4SAndroid Build Coastguard Worker                     }
569*bb4ee6a4SAndroid Build Coastguard Worker                     Token::ReqIrq => {
570*bb4ee6a4SAndroid Build Coastguard Worker                         let device = HotPlugDeviceInfo {
571*bb4ee6a4SAndroid Build Coastguard Worker                             device_type: HotPlugDeviceType::EndPoint,
572*bb4ee6a4SAndroid Build Coastguard Worker                             path: self.sysfs_path.clone(),
573*bb4ee6a4SAndroid Build Coastguard Worker                             hp_interrupt: false,
574*bb4ee6a4SAndroid Build Coastguard Worker                         };
575*bb4ee6a4SAndroid Build Coastguard Worker 
576*bb4ee6a4SAndroid Build Coastguard Worker                         let request = VmRequest::HotPlugVfioCommand { device, add: false };
577*bb4ee6a4SAndroid Build Coastguard Worker                         if self.vm_socket.send(&request).is_ok() {
578*bb4ee6a4SAndroid Build Coastguard Worker                             if let Err(e) = self.vm_socket.recv::<VmResponse>() {
579*bb4ee6a4SAndroid Build Coastguard Worker                                 error!("{} failed to remove vfio_device: {}", self.name.clone(), e);
580*bb4ee6a4SAndroid Build Coastguard Worker                             } else {
581*bb4ee6a4SAndroid Build Coastguard Worker                                 break 'wait;
582*bb4ee6a4SAndroid Build Coastguard Worker                             }
583*bb4ee6a4SAndroid Build Coastguard Worker                         }
584*bb4ee6a4SAndroid Build Coastguard Worker                     }
585*bb4ee6a4SAndroid Build Coastguard Worker                     Token::WakeUp => {
586*bb4ee6a4SAndroid Build Coastguard Worker                         let _ = wakeup_evt.wait();
587*bb4ee6a4SAndroid Build Coastguard Worker 
588*bb4ee6a4SAndroid Build Coastguard Worker                         if *is_in_low_power.lock() {
589*bb4ee6a4SAndroid Build Coastguard Worker                             if let Some(pm_cap) = &self.pm_cap {
590*bb4ee6a4SAndroid Build Coastguard Worker                                 if pm_cap.lock().should_trigger_pme() {
591*bb4ee6a4SAndroid Build Coastguard Worker                                     let request =
592*bb4ee6a4SAndroid Build Coastguard Worker                                         VmRequest::PciPme(self.address.pme_requester_id());
593*bb4ee6a4SAndroid Build Coastguard Worker                                     if self.vm_socket.send(&request).is_ok() {
594*bb4ee6a4SAndroid Build Coastguard Worker                                         if let Err(e) = self.vm_socket.recv::<VmResponse>() {
595*bb4ee6a4SAndroid Build Coastguard Worker                                             error!(
596*bb4ee6a4SAndroid Build Coastguard Worker                                                 "{} failed to send PME: {}",
597*bb4ee6a4SAndroid Build Coastguard Worker                                                 self.name.clone(),
598*bb4ee6a4SAndroid Build Coastguard Worker                                                 e
599*bb4ee6a4SAndroid Build Coastguard Worker                                             );
600*bb4ee6a4SAndroid Build Coastguard Worker                                         }
601*bb4ee6a4SAndroid Build Coastguard Worker                                     }
602*bb4ee6a4SAndroid Build Coastguard Worker                                 }
603*bb4ee6a4SAndroid Build Coastguard Worker                             }
604*bb4ee6a4SAndroid Build Coastguard Worker                         }
605*bb4ee6a4SAndroid Build Coastguard Worker                     }
606*bb4ee6a4SAndroid Build Coastguard Worker                     Token::AcpiNotifyEvent => {
607*bb4ee6a4SAndroid Build Coastguard Worker                         if let Some(gpe) = gpe {
608*bb4ee6a4SAndroid Build Coastguard Worker                             if let Ok(val) = base::EventExt::read_count(&acpi_notify_evt) {
609*bb4ee6a4SAndroid Build Coastguard Worker                                 notification_val.lock().push(val as u32);
610*bb4ee6a4SAndroid Build Coastguard Worker                                 let request = VmRequest::Gpe {
611*bb4ee6a4SAndroid Build Coastguard Worker                                     gpe,
612*bb4ee6a4SAndroid Build Coastguard Worker                                     clear_evt: None,
613*bb4ee6a4SAndroid Build Coastguard Worker                                 };
614*bb4ee6a4SAndroid Build Coastguard Worker                                 if self.vm_socket.send(&request).is_ok() {
615*bb4ee6a4SAndroid Build Coastguard Worker                                     if let Err(e) = self.vm_socket.recv::<VmResponse>() {
616*bb4ee6a4SAndroid Build Coastguard Worker                                         error!("{} failed to send GPE: {}", self.name.clone(), e);
617*bb4ee6a4SAndroid Build Coastguard Worker                                     }
618*bb4ee6a4SAndroid Build Coastguard Worker                                 }
619*bb4ee6a4SAndroid Build Coastguard Worker                             } else {
620*bb4ee6a4SAndroid Build Coastguard Worker                                 error!("{} failed to read acpi_notify_evt", self.name.clone());
621*bb4ee6a4SAndroid Build Coastguard Worker                             }
622*bb4ee6a4SAndroid Build Coastguard Worker                         }
623*bb4ee6a4SAndroid Build Coastguard Worker                     }
624*bb4ee6a4SAndroid Build Coastguard Worker                     Token::Kill => break 'wait,
625*bb4ee6a4SAndroid Build Coastguard Worker                 }
626*bb4ee6a4SAndroid Build Coastguard Worker             }
627*bb4ee6a4SAndroid Build Coastguard Worker         }
628*bb4ee6a4SAndroid Build Coastguard Worker     }
629*bb4ee6a4SAndroid Build Coastguard Worker }
630*bb4ee6a4SAndroid Build Coastguard Worker 
get_next_from_extcap_header(cap_header: u32) -> u32631*bb4ee6a4SAndroid Build Coastguard Worker fn get_next_from_extcap_header(cap_header: u32) -> u32 {
632*bb4ee6a4SAndroid Build Coastguard Worker     (cap_header >> 20) & 0xffc
633*bb4ee6a4SAndroid Build Coastguard Worker }
634*bb4ee6a4SAndroid Build Coastguard Worker 
is_skipped_ext_cap(cap_id: u16) -> bool635*bb4ee6a4SAndroid Build Coastguard Worker fn is_skipped_ext_cap(cap_id: u16) -> bool {
636*bb4ee6a4SAndroid Build Coastguard Worker     matches!(
637*bb4ee6a4SAndroid Build Coastguard Worker         cap_id,
638*bb4ee6a4SAndroid Build Coastguard Worker         // SR-IOV/ARI/Resizable_BAR capabilities are not well handled and should not be exposed
639*bb4ee6a4SAndroid Build Coastguard Worker         PCI_EXT_CAP_ID_ARI | PCI_EXT_CAP_ID_SRIOV | PCI_EXT_CAP_ID_REBAR
640*bb4ee6a4SAndroid Build Coastguard Worker     )
641*bb4ee6a4SAndroid Build Coastguard Worker }
642*bb4ee6a4SAndroid Build Coastguard Worker 
643*bb4ee6a4SAndroid Build Coastguard Worker enum DeviceData {
644*bb4ee6a4SAndroid Build Coastguard Worker     IntelGfxData { opregion_index: u32 },
645*bb4ee6a4SAndroid Build Coastguard Worker }
646*bb4ee6a4SAndroid Build Coastguard Worker 
647*bb4ee6a4SAndroid Build Coastguard Worker /// PCI Express Extended Capabilities information
648*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Copy, Clone)]
649*bb4ee6a4SAndroid Build Coastguard Worker struct ExtCap {
650*bb4ee6a4SAndroid Build Coastguard Worker     /// cap offset in Configuration Space
651*bb4ee6a4SAndroid Build Coastguard Worker     offset: u32,
652*bb4ee6a4SAndroid Build Coastguard Worker     /// cap size
653*bb4ee6a4SAndroid Build Coastguard Worker     size: u32,
654*bb4ee6a4SAndroid Build Coastguard Worker     /// next offset, set next non-skipped offset for non-skipped ext cap
655*bb4ee6a4SAndroid Build Coastguard Worker     next: u16,
656*bb4ee6a4SAndroid Build Coastguard Worker     /// whether to be exposed to guest
657*bb4ee6a4SAndroid Build Coastguard Worker     is_skipped: bool,
658*bb4ee6a4SAndroid Build Coastguard Worker }
659*bb4ee6a4SAndroid Build Coastguard Worker 
660*bb4ee6a4SAndroid Build Coastguard Worker /// Implements the Vfio Pci device, then a pci device is added into vm
661*bb4ee6a4SAndroid Build Coastguard Worker pub struct VfioPciDevice {
662*bb4ee6a4SAndroid Build Coastguard Worker     device: Arc<VfioDevice>,
663*bb4ee6a4SAndroid Build Coastguard Worker     config: VfioPciConfig,
664*bb4ee6a4SAndroid Build Coastguard Worker     hotplug: bool,
665*bb4ee6a4SAndroid Build Coastguard Worker     hotplug_bus_number: Option<u8>,
666*bb4ee6a4SAndroid Build Coastguard Worker     preferred_address: PciAddress,
667*bb4ee6a4SAndroid Build Coastguard Worker     pci_address: Option<PciAddress>,
668*bb4ee6a4SAndroid Build Coastguard Worker     interrupt_evt: Option<IrqLevelEvent>,
669*bb4ee6a4SAndroid Build Coastguard Worker     acpi_notification_evt: Option<Event>,
670*bb4ee6a4SAndroid Build Coastguard Worker     mmio_regions: Vec<PciBarConfiguration>,
671*bb4ee6a4SAndroid Build Coastguard Worker     io_regions: Vec<PciBarConfiguration>,
672*bb4ee6a4SAndroid Build Coastguard Worker     pm_cap: Option<Arc<Mutex<VfioPmCap>>>,
673*bb4ee6a4SAndroid Build Coastguard Worker     msi_cap: Option<VfioMsiCap>,
674*bb4ee6a4SAndroid Build Coastguard Worker     msix_cap: Option<Arc<Mutex<VfioMsixCap>>>,
675*bb4ee6a4SAndroid Build Coastguard Worker     irq_type: Option<VfioIrqType>,
676*bb4ee6a4SAndroid Build Coastguard Worker     vm_memory_client: VmMemoryClient,
677*bb4ee6a4SAndroid Build Coastguard Worker     device_data: Option<DeviceData>,
678*bb4ee6a4SAndroid Build Coastguard Worker     pm_evt: Option<Event>,
679*bb4ee6a4SAndroid Build Coastguard Worker     is_in_low_power: Arc<Mutex<bool>>,
680*bb4ee6a4SAndroid Build Coastguard Worker     worker_thread: Option<WorkerThread<VfioPciWorker>>,
681*bb4ee6a4SAndroid Build Coastguard Worker     vm_socket_vm: Option<Tube>,
682*bb4ee6a4SAndroid Build Coastguard Worker     sysfs_path: PathBuf,
683*bb4ee6a4SAndroid Build Coastguard Worker     // PCI Express Extended Capabilities
684*bb4ee6a4SAndroid Build Coastguard Worker     ext_caps: Vec<ExtCap>,
685*bb4ee6a4SAndroid Build Coastguard Worker     vcfg_shm_mmap: Option<MemoryMapping>,
686*bb4ee6a4SAndroid Build Coastguard Worker     mapped_mmio_bars: BTreeMap<PciBarIndex, (u64, Vec<VmMemoryRegionId>)>,
687*bb4ee6a4SAndroid Build Coastguard Worker     activated: bool,
688*bb4ee6a4SAndroid Build Coastguard Worker     acpi_notifier_val: Arc<Mutex<Vec<u32>>>,
689*bb4ee6a4SAndroid Build Coastguard Worker     gpe: Option<u32>,
690*bb4ee6a4SAndroid Build Coastguard Worker     base_class_code: PciClassCode,
691*bb4ee6a4SAndroid Build Coastguard Worker }
692*bb4ee6a4SAndroid Build Coastguard Worker 
693*bb4ee6a4SAndroid Build Coastguard Worker impl VfioPciDevice {
694*bb4ee6a4SAndroid Build Coastguard Worker     /// Constructs a new Vfio Pci device for the give Vfio device
new( sysfs_path: &Path, device: VfioDevice, hotplug: bool, hotplug_bus_number: Option<u8>, guest_address: Option<PciAddress>, vfio_device_socket_msi: Tube, vfio_device_socket_msix: Tube, vm_memory_client: VmMemoryClient, vfio_device_socket_vm: Tube, ) -> Result<Self, PciDeviceError>695*bb4ee6a4SAndroid Build Coastguard Worker     pub fn new(
696*bb4ee6a4SAndroid Build Coastguard Worker         sysfs_path: &Path,
697*bb4ee6a4SAndroid Build Coastguard Worker         device: VfioDevice,
698*bb4ee6a4SAndroid Build Coastguard Worker         hotplug: bool,
699*bb4ee6a4SAndroid Build Coastguard Worker         hotplug_bus_number: Option<u8>,
700*bb4ee6a4SAndroid Build Coastguard Worker         guest_address: Option<PciAddress>,
701*bb4ee6a4SAndroid Build Coastguard Worker         vfio_device_socket_msi: Tube,
702*bb4ee6a4SAndroid Build Coastguard Worker         vfio_device_socket_msix: Tube,
703*bb4ee6a4SAndroid Build Coastguard Worker         vm_memory_client: VmMemoryClient,
704*bb4ee6a4SAndroid Build Coastguard Worker         vfio_device_socket_vm: Tube,
705*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Result<Self, PciDeviceError> {
706*bb4ee6a4SAndroid Build Coastguard Worker         let preferred_address = if let Some(bus_num) = hotplug_bus_number {
707*bb4ee6a4SAndroid Build Coastguard Worker             debug!("hotplug bus {}", bus_num);
708*bb4ee6a4SAndroid Build Coastguard Worker             PciAddress {
709*bb4ee6a4SAndroid Build Coastguard Worker                 // Caller specify pcie bus number for hotplug device
710*bb4ee6a4SAndroid Build Coastguard Worker                 bus: bus_num,
711*bb4ee6a4SAndroid Build Coastguard Worker                 // devfn should be 0, otherwise pcie root port couldn't detect it
712*bb4ee6a4SAndroid Build Coastguard Worker                 dev: 0,
713*bb4ee6a4SAndroid Build Coastguard Worker                 func: 0,
714*bb4ee6a4SAndroid Build Coastguard Worker             }
715*bb4ee6a4SAndroid Build Coastguard Worker         } else if let Some(guest_address) = guest_address {
716*bb4ee6a4SAndroid Build Coastguard Worker             debug!("guest PCI address {}", guest_address);
717*bb4ee6a4SAndroid Build Coastguard Worker             guest_address
718*bb4ee6a4SAndroid Build Coastguard Worker         } else {
719*bb4ee6a4SAndroid Build Coastguard Worker             let addr = PciAddress::from_str(device.device_name()).map_err(|e| {
720*bb4ee6a4SAndroid Build Coastguard Worker                 PciDeviceError::PciAddressParseFailure(device.device_name().clone(), e)
721*bb4ee6a4SAndroid Build Coastguard Worker             })?;
722*bb4ee6a4SAndroid Build Coastguard Worker             debug!("parsed device PCI address {}", addr);
723*bb4ee6a4SAndroid Build Coastguard Worker             addr
724*bb4ee6a4SAndroid Build Coastguard Worker         };
725*bb4ee6a4SAndroid Build Coastguard Worker 
726*bb4ee6a4SAndroid Build Coastguard Worker         let dev = Arc::new(device);
727*bb4ee6a4SAndroid Build Coastguard Worker         let config = VfioPciConfig::new(Arc::clone(&dev));
728*bb4ee6a4SAndroid Build Coastguard Worker         let mut msi_socket = Some(vfio_device_socket_msi);
729*bb4ee6a4SAndroid Build Coastguard Worker         let mut msix_socket = Some(vfio_device_socket_msix);
730*bb4ee6a4SAndroid Build Coastguard Worker         let mut msi_cap: Option<VfioMsiCap> = None;
731*bb4ee6a4SAndroid Build Coastguard Worker         let mut msix_cap: Option<Arc<Mutex<VfioMsixCap>>> = None;
732*bb4ee6a4SAndroid Build Coastguard Worker         let mut pm_cap: Option<Arc<Mutex<VfioPmCap>>> = None;
733*bb4ee6a4SAndroid Build Coastguard Worker 
734*bb4ee6a4SAndroid Build Coastguard Worker         let mut is_pcie = false;
735*bb4ee6a4SAndroid Build Coastguard Worker         let mut cap_next: u32 = config.read_config::<u8>(PCI_CAPABILITY_LIST).into();
736*bb4ee6a4SAndroid Build Coastguard Worker         let vendor_id: u16 = config.read_config(PCI_VENDOR_ID);
737*bb4ee6a4SAndroid Build Coastguard Worker         let device_id: u16 = config.read_config(PCI_DEVICE_ID);
738*bb4ee6a4SAndroid Build Coastguard Worker         let base_class_code = PciClassCode::try_from(config.read_config::<u8>(PCI_BASE_CLASS_CODE))
739*bb4ee6a4SAndroid Build Coastguard Worker             .unwrap_or(PciClassCode::Other);
740*bb4ee6a4SAndroid Build Coastguard Worker 
741*bb4ee6a4SAndroid Build Coastguard Worker         let pci_id = PciId::new(vendor_id, device_id);
742*bb4ee6a4SAndroid Build Coastguard Worker 
743*bb4ee6a4SAndroid Build Coastguard Worker         while cap_next != 0 {
744*bb4ee6a4SAndroid Build Coastguard Worker             let cap_id: u8 = config.read_config(cap_next);
745*bb4ee6a4SAndroid Build Coastguard Worker             if cap_id == PCI_CAP_ID_PM {
746*bb4ee6a4SAndroid Build Coastguard Worker                 pm_cap = Some(Arc::new(Mutex::new(VfioPmCap::new(&config, cap_next))));
747*bb4ee6a4SAndroid Build Coastguard Worker             } else if cap_id == PCI_CAP_ID_MSI {
748*bb4ee6a4SAndroid Build Coastguard Worker                 if let Some(msi_socket) = msi_socket.take() {
749*bb4ee6a4SAndroid Build Coastguard Worker                     msi_cap = Some(VfioMsiCap::new(
750*bb4ee6a4SAndroid Build Coastguard Worker                         &config,
751*bb4ee6a4SAndroid Build Coastguard Worker                         cap_next,
752*bb4ee6a4SAndroid Build Coastguard Worker                         msi_socket,
753*bb4ee6a4SAndroid Build Coastguard Worker                         pci_id.into(),
754*bb4ee6a4SAndroid Build Coastguard Worker                         dev.device_name().to_string(),
755*bb4ee6a4SAndroid Build Coastguard Worker                     ));
756*bb4ee6a4SAndroid Build Coastguard Worker                 }
757*bb4ee6a4SAndroid Build Coastguard Worker             } else if cap_id == PCI_CAP_ID_MSIX {
758*bb4ee6a4SAndroid Build Coastguard Worker                 if let Some(msix_socket) = msix_socket.take() {
759*bb4ee6a4SAndroid Build Coastguard Worker                     msix_cap = Some(Arc::new(Mutex::new(VfioMsixCap::new(
760*bb4ee6a4SAndroid Build Coastguard Worker                         &config,
761*bb4ee6a4SAndroid Build Coastguard Worker                         cap_next,
762*bb4ee6a4SAndroid Build Coastguard Worker                         msix_socket,
763*bb4ee6a4SAndroid Build Coastguard Worker                         pci_id.into(),
764*bb4ee6a4SAndroid Build Coastguard Worker                         dev.device_name().to_string(),
765*bb4ee6a4SAndroid Build Coastguard Worker                     ))));
766*bb4ee6a4SAndroid Build Coastguard Worker                 }
767*bb4ee6a4SAndroid Build Coastguard Worker             } else if cap_id == PciCapabilityID::PciExpress as u8 {
768*bb4ee6a4SAndroid Build Coastguard Worker                 is_pcie = true;
769*bb4ee6a4SAndroid Build Coastguard Worker             }
770*bb4ee6a4SAndroid Build Coastguard Worker             let offset = cap_next + PCI_MSI_NEXT_POINTER;
771*bb4ee6a4SAndroid Build Coastguard Worker             cap_next = config.read_config::<u8>(offset).into();
772*bb4ee6a4SAndroid Build Coastguard Worker         }
773*bb4ee6a4SAndroid Build Coastguard Worker 
774*bb4ee6a4SAndroid Build Coastguard Worker         let mut ext_caps: Vec<ExtCap> = Vec::new();
775*bb4ee6a4SAndroid Build Coastguard Worker         if is_pcie {
776*bb4ee6a4SAndroid Build Coastguard Worker             let mut ext_cap_next: u32 = PCI_CONFIG_SPACE_SIZE;
777*bb4ee6a4SAndroid Build Coastguard Worker             while ext_cap_next != 0 {
778*bb4ee6a4SAndroid Build Coastguard Worker                 let ext_cap_config: u32 = config.read_config::<u32>(ext_cap_next);
779*bb4ee6a4SAndroid Build Coastguard Worker                 if ext_cap_config == 0 {
780*bb4ee6a4SAndroid Build Coastguard Worker                     break;
781*bb4ee6a4SAndroid Build Coastguard Worker                 }
782*bb4ee6a4SAndroid Build Coastguard Worker                 ext_caps.push(ExtCap {
783*bb4ee6a4SAndroid Build Coastguard Worker                     offset: ext_cap_next,
784*bb4ee6a4SAndroid Build Coastguard Worker                     // Calculate the size later
785*bb4ee6a4SAndroid Build Coastguard Worker                     size: 0,
786*bb4ee6a4SAndroid Build Coastguard Worker                     // init as the real value
787*bb4ee6a4SAndroid Build Coastguard Worker                     next: get_next_from_extcap_header(ext_cap_config) as u16,
788*bb4ee6a4SAndroid Build Coastguard Worker                     is_skipped: is_skipped_ext_cap((ext_cap_config & 0xffff) as u16),
789*bb4ee6a4SAndroid Build Coastguard Worker                 });
790*bb4ee6a4SAndroid Build Coastguard Worker                 ext_cap_next = get_next_from_extcap_header(ext_cap_config);
791*bb4ee6a4SAndroid Build Coastguard Worker             }
792*bb4ee6a4SAndroid Build Coastguard Worker 
793*bb4ee6a4SAndroid Build Coastguard Worker             // Manage extended caps
794*bb4ee6a4SAndroid Build Coastguard Worker             //
795*bb4ee6a4SAndroid Build Coastguard Worker             // Extended capabilities are chained with each pointing to the next, so
796*bb4ee6a4SAndroid Build Coastguard Worker             // we can drop anything other than the head of the chain simply by
797*bb4ee6a4SAndroid Build Coastguard Worker             // modifying the previous next pointer. For the head of the chain, we
798*bb4ee6a4SAndroid Build Coastguard Worker             // can modify the capability ID to something that cannot match a valid
799*bb4ee6a4SAndroid Build Coastguard Worker             // capability. ID PCI_EXT_CAP_ID_CAC is for this since it is no longer
800*bb4ee6a4SAndroid Build Coastguard Worker             // supported.
801*bb4ee6a4SAndroid Build Coastguard Worker             //
802*bb4ee6a4SAndroid Build Coastguard Worker             // reverse order by offset
803*bb4ee6a4SAndroid Build Coastguard Worker             ext_caps.sort_by(|a, b| b.offset.cmp(&a.offset));
804*bb4ee6a4SAndroid Build Coastguard Worker             let mut next_offset: u32 = PCIE_CONFIG_SPACE_SIZE;
805*bb4ee6a4SAndroid Build Coastguard Worker             let mut non_skipped_next: u16 = 0;
806*bb4ee6a4SAndroid Build Coastguard Worker             for ext_cap in ext_caps.iter_mut() {
807*bb4ee6a4SAndroid Build Coastguard Worker                 if !ext_cap.is_skipped {
808*bb4ee6a4SAndroid Build Coastguard Worker                     ext_cap.next = non_skipped_next;
809*bb4ee6a4SAndroid Build Coastguard Worker                     non_skipped_next = ext_cap.offset as u16;
810*bb4ee6a4SAndroid Build Coastguard Worker                 } else if ext_cap.offset == PCI_CONFIG_SPACE_SIZE {
811*bb4ee6a4SAndroid Build Coastguard Worker                     ext_cap.next = non_skipped_next;
812*bb4ee6a4SAndroid Build Coastguard Worker                 }
813*bb4ee6a4SAndroid Build Coastguard Worker                 ext_cap.size = next_offset - ext_cap.offset;
814*bb4ee6a4SAndroid Build Coastguard Worker                 next_offset = ext_cap.offset;
815*bb4ee6a4SAndroid Build Coastguard Worker             }
816*bb4ee6a4SAndroid Build Coastguard Worker             // order by offset
817*bb4ee6a4SAndroid Build Coastguard Worker             ext_caps.reverse();
818*bb4ee6a4SAndroid Build Coastguard Worker         }
819*bb4ee6a4SAndroid Build Coastguard Worker 
820*bb4ee6a4SAndroid Build Coastguard Worker         let is_intel_gfx =
821*bb4ee6a4SAndroid Build Coastguard Worker             base_class_code == PciClassCode::DisplayController && vendor_id == PCI_VENDOR_ID_INTEL;
822*bb4ee6a4SAndroid Build Coastguard Worker         let device_data = if is_intel_gfx {
823*bb4ee6a4SAndroid Build Coastguard Worker             Some(DeviceData::IntelGfxData {
824*bb4ee6a4SAndroid Build Coastguard Worker                 opregion_index: u32::MAX,
825*bb4ee6a4SAndroid Build Coastguard Worker             })
826*bb4ee6a4SAndroid Build Coastguard Worker         } else {
827*bb4ee6a4SAndroid Build Coastguard Worker             None
828*bb4ee6a4SAndroid Build Coastguard Worker         };
829*bb4ee6a4SAndroid Build Coastguard Worker 
830*bb4ee6a4SAndroid Build Coastguard Worker         Ok(VfioPciDevice {
831*bb4ee6a4SAndroid Build Coastguard Worker             device: dev,
832*bb4ee6a4SAndroid Build Coastguard Worker             config,
833*bb4ee6a4SAndroid Build Coastguard Worker             hotplug,
834*bb4ee6a4SAndroid Build Coastguard Worker             hotplug_bus_number,
835*bb4ee6a4SAndroid Build Coastguard Worker             preferred_address,
836*bb4ee6a4SAndroid Build Coastguard Worker             pci_address: None,
837*bb4ee6a4SAndroid Build Coastguard Worker             interrupt_evt: None,
838*bb4ee6a4SAndroid Build Coastguard Worker             acpi_notification_evt: None,
839*bb4ee6a4SAndroid Build Coastguard Worker             mmio_regions: Vec::new(),
840*bb4ee6a4SAndroid Build Coastguard Worker             io_regions: Vec::new(),
841*bb4ee6a4SAndroid Build Coastguard Worker             pm_cap,
842*bb4ee6a4SAndroid Build Coastguard Worker             msi_cap,
843*bb4ee6a4SAndroid Build Coastguard Worker             msix_cap,
844*bb4ee6a4SAndroid Build Coastguard Worker             irq_type: None,
845*bb4ee6a4SAndroid Build Coastguard Worker             vm_memory_client,
846*bb4ee6a4SAndroid Build Coastguard Worker             device_data,
847*bb4ee6a4SAndroid Build Coastguard Worker             pm_evt: None,
848*bb4ee6a4SAndroid Build Coastguard Worker             is_in_low_power: Arc::new(Mutex::new(false)),
849*bb4ee6a4SAndroid Build Coastguard Worker             worker_thread: None,
850*bb4ee6a4SAndroid Build Coastguard Worker             vm_socket_vm: Some(vfio_device_socket_vm),
851*bb4ee6a4SAndroid Build Coastguard Worker             sysfs_path: sysfs_path.to_path_buf(),
852*bb4ee6a4SAndroid Build Coastguard Worker             ext_caps,
853*bb4ee6a4SAndroid Build Coastguard Worker             vcfg_shm_mmap: None,
854*bb4ee6a4SAndroid Build Coastguard Worker             mapped_mmio_bars: BTreeMap::new(),
855*bb4ee6a4SAndroid Build Coastguard Worker             activated: false,
856*bb4ee6a4SAndroid Build Coastguard Worker             acpi_notifier_val: Arc::new(Mutex::new(Vec::new())),
857*bb4ee6a4SAndroid Build Coastguard Worker             gpe: None,
858*bb4ee6a4SAndroid Build Coastguard Worker             base_class_code,
859*bb4ee6a4SAndroid Build Coastguard Worker         })
860*bb4ee6a4SAndroid Build Coastguard Worker     }
861*bb4ee6a4SAndroid Build Coastguard Worker 
862*bb4ee6a4SAndroid Build Coastguard Worker     /// Gets the pci address of the device, if one has already been allocated.
pci_address(&self) -> Option<PciAddress>863*bb4ee6a4SAndroid Build Coastguard Worker     pub fn pci_address(&self) -> Option<PciAddress> {
864*bb4ee6a4SAndroid Build Coastguard Worker         self.pci_address
865*bb4ee6a4SAndroid Build Coastguard Worker     }
866*bb4ee6a4SAndroid Build Coastguard Worker 
is_gfx(&self) -> bool867*bb4ee6a4SAndroid Build Coastguard Worker     pub fn is_gfx(&self) -> bool {
868*bb4ee6a4SAndroid Build Coastguard Worker         self.base_class_code == PciClassCode::DisplayController
869*bb4ee6a4SAndroid Build Coastguard Worker     }
870*bb4ee6a4SAndroid Build Coastguard Worker 
is_intel_gfx(&self) -> bool871*bb4ee6a4SAndroid Build Coastguard Worker     fn is_intel_gfx(&self) -> bool {
872*bb4ee6a4SAndroid Build Coastguard Worker         matches!(self.device_data, Some(DeviceData::IntelGfxData { .. }))
873*bb4ee6a4SAndroid Build Coastguard Worker     }
874*bb4ee6a4SAndroid Build Coastguard Worker 
enable_acpi_notification(&mut self) -> Result<(), PciDeviceError>875*bb4ee6a4SAndroid Build Coastguard Worker     fn enable_acpi_notification(&mut self) -> Result<(), PciDeviceError> {
876*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(ref acpi_notification_evt) = self.acpi_notification_evt {
877*bb4ee6a4SAndroid Build Coastguard Worker             return self
878*bb4ee6a4SAndroid Build Coastguard Worker                 .device
879*bb4ee6a4SAndroid Build Coastguard Worker                 .acpi_notification_evt_enable(acpi_notification_evt, VFIO_PCI_ACPI_NTFY_IRQ_INDEX)
880*bb4ee6a4SAndroid Build Coastguard Worker                 .map_err(|_| PciDeviceError::AcpiNotifySetupFailed);
881*bb4ee6a4SAndroid Build Coastguard Worker         }
882*bb4ee6a4SAndroid Build Coastguard Worker         Err(PciDeviceError::AcpiNotifySetupFailed)
883*bb4ee6a4SAndroid Build Coastguard Worker     }
884*bb4ee6a4SAndroid Build Coastguard Worker 
885*bb4ee6a4SAndroid Build Coastguard Worker     #[allow(dead_code)]
disable_acpi_notification(&mut self) -> Result<(), PciDeviceError>886*bb4ee6a4SAndroid Build Coastguard Worker     fn disable_acpi_notification(&mut self) -> Result<(), PciDeviceError> {
887*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(ref _acpi_notification_evt) = self.acpi_notification_evt {
888*bb4ee6a4SAndroid Build Coastguard Worker             return self
889*bb4ee6a4SAndroid Build Coastguard Worker                 .device
890*bb4ee6a4SAndroid Build Coastguard Worker                 .acpi_notification_disable(VFIO_PCI_ACPI_NTFY_IRQ_INDEX)
891*bb4ee6a4SAndroid Build Coastguard Worker                 .map_err(|_| PciDeviceError::AcpiNotifyDeactivationFailed);
892*bb4ee6a4SAndroid Build Coastguard Worker         }
893*bb4ee6a4SAndroid Build Coastguard Worker         Err(PciDeviceError::AcpiNotifyDeactivationFailed)
894*bb4ee6a4SAndroid Build Coastguard Worker     }
895*bb4ee6a4SAndroid Build Coastguard Worker 
896*bb4ee6a4SAndroid Build Coastguard Worker     #[allow(dead_code)]
test_acpi_notification(&mut self, val: u32) -> Result<(), PciDeviceError>897*bb4ee6a4SAndroid Build Coastguard Worker     fn test_acpi_notification(&mut self, val: u32) -> Result<(), PciDeviceError> {
898*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(ref _acpi_notification_evt) = self.acpi_notification_evt {
899*bb4ee6a4SAndroid Build Coastguard Worker             return self
900*bb4ee6a4SAndroid Build Coastguard Worker                 .device
901*bb4ee6a4SAndroid Build Coastguard Worker                 .acpi_notification_test(VFIO_PCI_ACPI_NTFY_IRQ_INDEX, val)
902*bb4ee6a4SAndroid Build Coastguard Worker                 .map_err(|_| PciDeviceError::AcpiNotifyTestFailed);
903*bb4ee6a4SAndroid Build Coastguard Worker         }
904*bb4ee6a4SAndroid Build Coastguard Worker         Err(PciDeviceError::AcpiNotifyTestFailed)
905*bb4ee6a4SAndroid Build Coastguard Worker     }
906*bb4ee6a4SAndroid Build Coastguard Worker 
enable_intx(&mut self)907*bb4ee6a4SAndroid Build Coastguard Worker     fn enable_intx(&mut self) {
908*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(ref interrupt_evt) = self.interrupt_evt {
909*bb4ee6a4SAndroid Build Coastguard Worker             if let Err(e) = self.device.irq_enable(
910*bb4ee6a4SAndroid Build Coastguard Worker                 &[Some(interrupt_evt.get_trigger())],
911*bb4ee6a4SAndroid Build Coastguard Worker                 VFIO_PCI_INTX_IRQ_INDEX,
912*bb4ee6a4SAndroid Build Coastguard Worker                 0,
913*bb4ee6a4SAndroid Build Coastguard Worker             ) {
914*bb4ee6a4SAndroid Build Coastguard Worker                 error!("{} Intx enable failed: {}", self.debug_label(), e);
915*bb4ee6a4SAndroid Build Coastguard Worker                 return;
916*bb4ee6a4SAndroid Build Coastguard Worker             }
917*bb4ee6a4SAndroid Build Coastguard Worker             if let Err(e) = self.device.irq_mask(VFIO_PCI_INTX_IRQ_INDEX) {
918*bb4ee6a4SAndroid Build Coastguard Worker                 error!("{} Intx mask failed: {}", self.debug_label(), e);
919*bb4ee6a4SAndroid Build Coastguard Worker                 self.disable_intx();
920*bb4ee6a4SAndroid Build Coastguard Worker                 return;
921*bb4ee6a4SAndroid Build Coastguard Worker             }
922*bb4ee6a4SAndroid Build Coastguard Worker             if let Err(e) = self
923*bb4ee6a4SAndroid Build Coastguard Worker                 .device
924*bb4ee6a4SAndroid Build Coastguard Worker                 .resample_virq_enable(interrupt_evt.get_resample(), VFIO_PCI_INTX_IRQ_INDEX)
925*bb4ee6a4SAndroid Build Coastguard Worker             {
926*bb4ee6a4SAndroid Build Coastguard Worker                 error!("{} resample enable failed: {}", self.debug_label(), e);
927*bb4ee6a4SAndroid Build Coastguard Worker                 self.disable_intx();
928*bb4ee6a4SAndroid Build Coastguard Worker                 return;
929*bb4ee6a4SAndroid Build Coastguard Worker             }
930*bb4ee6a4SAndroid Build Coastguard Worker             if let Err(e) = self.device.irq_unmask(VFIO_PCI_INTX_IRQ_INDEX) {
931*bb4ee6a4SAndroid Build Coastguard Worker                 error!("{} Intx unmask failed: {}", self.debug_label(), e);
932*bb4ee6a4SAndroid Build Coastguard Worker                 self.disable_intx();
933*bb4ee6a4SAndroid Build Coastguard Worker                 return;
934*bb4ee6a4SAndroid Build Coastguard Worker             }
935*bb4ee6a4SAndroid Build Coastguard Worker             self.irq_type = Some(VfioIrqType::Intx);
936*bb4ee6a4SAndroid Build Coastguard Worker         }
937*bb4ee6a4SAndroid Build Coastguard Worker     }
938*bb4ee6a4SAndroid Build Coastguard Worker 
disable_intx(&mut self)939*bb4ee6a4SAndroid Build Coastguard Worker     fn disable_intx(&mut self) {
940*bb4ee6a4SAndroid Build Coastguard Worker         if let Err(e) = self.device.irq_disable(VFIO_PCI_INTX_IRQ_INDEX) {
941*bb4ee6a4SAndroid Build Coastguard Worker             error!("{} Intx disable failed: {}", self.debug_label(), e);
942*bb4ee6a4SAndroid Build Coastguard Worker         }
943*bb4ee6a4SAndroid Build Coastguard Worker         self.irq_type = None;
944*bb4ee6a4SAndroid Build Coastguard Worker     }
945*bb4ee6a4SAndroid Build Coastguard Worker 
disable_irqs(&mut self)946*bb4ee6a4SAndroid Build Coastguard Worker     fn disable_irqs(&mut self) {
947*bb4ee6a4SAndroid Build Coastguard Worker         match self.irq_type {
948*bb4ee6a4SAndroid Build Coastguard Worker             Some(VfioIrqType::Msi) => self.disable_msi(),
949*bb4ee6a4SAndroid Build Coastguard Worker             Some(VfioIrqType::Msix) => self.disable_msix(),
950*bb4ee6a4SAndroid Build Coastguard Worker             _ => (),
951*bb4ee6a4SAndroid Build Coastguard Worker         }
952*bb4ee6a4SAndroid Build Coastguard Worker 
953*bb4ee6a4SAndroid Build Coastguard Worker         // Above disable_msi() or disable_msix() will enable intx again.
954*bb4ee6a4SAndroid Build Coastguard Worker         // so disable_intx here again.
955*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(VfioIrqType::Intx) = self.irq_type {
956*bb4ee6a4SAndroid Build Coastguard Worker             self.disable_intx();
957*bb4ee6a4SAndroid Build Coastguard Worker         }
958*bb4ee6a4SAndroid Build Coastguard Worker     }
959*bb4ee6a4SAndroid Build Coastguard Worker 
enable_msi(&mut self)960*bb4ee6a4SAndroid Build Coastguard Worker     fn enable_msi(&mut self) {
961*bb4ee6a4SAndroid Build Coastguard Worker         self.disable_irqs();
962*bb4ee6a4SAndroid Build Coastguard Worker 
963*bb4ee6a4SAndroid Build Coastguard Worker         let irqfd = match &self.msi_cap {
964*bb4ee6a4SAndroid Build Coastguard Worker             Some(cap) => {
965*bb4ee6a4SAndroid Build Coastguard Worker                 if let Some(fd) = cap.get_msi_irqfd() {
966*bb4ee6a4SAndroid Build Coastguard Worker                     fd
967*bb4ee6a4SAndroid Build Coastguard Worker                 } else {
968*bb4ee6a4SAndroid Build Coastguard Worker                     self.enable_intx();
969*bb4ee6a4SAndroid Build Coastguard Worker                     return;
970*bb4ee6a4SAndroid Build Coastguard Worker                 }
971*bb4ee6a4SAndroid Build Coastguard Worker             }
972*bb4ee6a4SAndroid Build Coastguard Worker             None => {
973*bb4ee6a4SAndroid Build Coastguard Worker                 self.enable_intx();
974*bb4ee6a4SAndroid Build Coastguard Worker                 return;
975*bb4ee6a4SAndroid Build Coastguard Worker             }
976*bb4ee6a4SAndroid Build Coastguard Worker         };
977*bb4ee6a4SAndroid Build Coastguard Worker 
978*bb4ee6a4SAndroid Build Coastguard Worker         if let Err(e) = self
979*bb4ee6a4SAndroid Build Coastguard Worker             .device
980*bb4ee6a4SAndroid Build Coastguard Worker             .irq_enable(&[Some(irqfd)], VFIO_PCI_MSI_IRQ_INDEX, 0)
981*bb4ee6a4SAndroid Build Coastguard Worker         {
982*bb4ee6a4SAndroid Build Coastguard Worker             error!("{} failed to enable msi: {}", self.debug_label(), e);
983*bb4ee6a4SAndroid Build Coastguard Worker             self.enable_intx();
984*bb4ee6a4SAndroid Build Coastguard Worker             return;
985*bb4ee6a4SAndroid Build Coastguard Worker         }
986*bb4ee6a4SAndroid Build Coastguard Worker 
987*bb4ee6a4SAndroid Build Coastguard Worker         self.irq_type = Some(VfioIrqType::Msi);
988*bb4ee6a4SAndroid Build Coastguard Worker     }
989*bb4ee6a4SAndroid Build Coastguard Worker 
disable_msi(&mut self)990*bb4ee6a4SAndroid Build Coastguard Worker     fn disable_msi(&mut self) {
991*bb4ee6a4SAndroid Build Coastguard Worker         if let Err(e) = self.device.irq_disable(VFIO_PCI_MSI_IRQ_INDEX) {
992*bb4ee6a4SAndroid Build Coastguard Worker             error!("{} failed to disable msi: {}", self.debug_label(), e);
993*bb4ee6a4SAndroid Build Coastguard Worker             return;
994*bb4ee6a4SAndroid Build Coastguard Worker         }
995*bb4ee6a4SAndroid Build Coastguard Worker         self.irq_type = None;
996*bb4ee6a4SAndroid Build Coastguard Worker 
997*bb4ee6a4SAndroid Build Coastguard Worker         self.enable_intx();
998*bb4ee6a4SAndroid Build Coastguard Worker     }
999*bb4ee6a4SAndroid Build Coastguard Worker 
enable_msix(&mut self)1000*bb4ee6a4SAndroid Build Coastguard Worker     fn enable_msix(&mut self) {
1001*bb4ee6a4SAndroid Build Coastguard Worker         if self.msix_cap.is_none() {
1002*bb4ee6a4SAndroid Build Coastguard Worker             return;
1003*bb4ee6a4SAndroid Build Coastguard Worker         }
1004*bb4ee6a4SAndroid Build Coastguard Worker 
1005*bb4ee6a4SAndroid Build Coastguard Worker         self.disable_irqs();
1006*bb4ee6a4SAndroid Build Coastguard Worker         let cap = self.msix_cap.as_ref().unwrap().lock();
1007*bb4ee6a4SAndroid Build Coastguard Worker         let vector_in_use = cap.get_msix_irqfds().iter().any(|&irq| irq.is_some());
1008*bb4ee6a4SAndroid Build Coastguard Worker 
1009*bb4ee6a4SAndroid Build Coastguard Worker         let mut failed = false;
1010*bb4ee6a4SAndroid Build Coastguard Worker         if !vector_in_use {
1011*bb4ee6a4SAndroid Build Coastguard Worker             // If there are no msix vectors currently in use, we explicitly assign a new eventfd
1012*bb4ee6a4SAndroid Build Coastguard Worker             // to vector 0. Then we enable it and immediately disable it, so that vfio will
1013*bb4ee6a4SAndroid Build Coastguard Worker             // activate physical device. If there are available msix vectors, just enable them
1014*bb4ee6a4SAndroid Build Coastguard Worker             // instead.
1015*bb4ee6a4SAndroid Build Coastguard Worker             let fd = Event::new().expect("failed to create event");
1016*bb4ee6a4SAndroid Build Coastguard Worker             let table_size = cap.table_size();
1017*bb4ee6a4SAndroid Build Coastguard Worker             let mut irqfds = vec![None; table_size];
1018*bb4ee6a4SAndroid Build Coastguard Worker             irqfds[0] = Some(&fd);
1019*bb4ee6a4SAndroid Build Coastguard Worker             for fd in irqfds.iter_mut().skip(1) {
1020*bb4ee6a4SAndroid Build Coastguard Worker                 *fd = None;
1021*bb4ee6a4SAndroid Build Coastguard Worker             }
1022*bb4ee6a4SAndroid Build Coastguard Worker             if let Err(e) = self.device.irq_enable(&irqfds, VFIO_PCI_MSIX_IRQ_INDEX, 0) {
1023*bb4ee6a4SAndroid Build Coastguard Worker                 error!("{} failed to enable msix: {}", self.debug_label(), e);
1024*bb4ee6a4SAndroid Build Coastguard Worker                 failed = true;
1025*bb4ee6a4SAndroid Build Coastguard Worker             }
1026*bb4ee6a4SAndroid Build Coastguard Worker             irqfds[0] = None;
1027*bb4ee6a4SAndroid Build Coastguard Worker             if let Err(e) = self.device.irq_enable(&irqfds, VFIO_PCI_MSIX_IRQ_INDEX, 0) {
1028*bb4ee6a4SAndroid Build Coastguard Worker                 error!("{} failed to enable msix: {}", self.debug_label(), e);
1029*bb4ee6a4SAndroid Build Coastguard Worker                 failed = true;
1030*bb4ee6a4SAndroid Build Coastguard Worker             }
1031*bb4ee6a4SAndroid Build Coastguard Worker         } else {
1032*bb4ee6a4SAndroid Build Coastguard Worker             let result = self
1033*bb4ee6a4SAndroid Build Coastguard Worker                 .device
1034*bb4ee6a4SAndroid Build Coastguard Worker                 .irq_enable(&cap.get_msix_irqfds(), VFIO_PCI_MSIX_IRQ_INDEX, 0);
1035*bb4ee6a4SAndroid Build Coastguard Worker             if let Err(e) = result {
1036*bb4ee6a4SAndroid Build Coastguard Worker                 error!("{} failed to enable msix: {}", self.debug_label(), e);
1037*bb4ee6a4SAndroid Build Coastguard Worker                 failed = true;
1038*bb4ee6a4SAndroid Build Coastguard Worker             }
1039*bb4ee6a4SAndroid Build Coastguard Worker         }
1040*bb4ee6a4SAndroid Build Coastguard Worker 
1041*bb4ee6a4SAndroid Build Coastguard Worker         std::mem::drop(cap);
1042*bb4ee6a4SAndroid Build Coastguard Worker         if failed {
1043*bb4ee6a4SAndroid Build Coastguard Worker             self.enable_intx();
1044*bb4ee6a4SAndroid Build Coastguard Worker             return;
1045*bb4ee6a4SAndroid Build Coastguard Worker         }
1046*bb4ee6a4SAndroid Build Coastguard Worker         self.irq_type = Some(VfioIrqType::Msix);
1047*bb4ee6a4SAndroid Build Coastguard Worker     }
1048*bb4ee6a4SAndroid Build Coastguard Worker 
disable_msix(&mut self)1049*bb4ee6a4SAndroid Build Coastguard Worker     fn disable_msix(&mut self) {
1050*bb4ee6a4SAndroid Build Coastguard Worker         if self.msix_cap.is_none() {
1051*bb4ee6a4SAndroid Build Coastguard Worker             return;
1052*bb4ee6a4SAndroid Build Coastguard Worker         }
1053*bb4ee6a4SAndroid Build Coastguard Worker         if let Err(e) = self.device.irq_disable(VFIO_PCI_MSIX_IRQ_INDEX) {
1054*bb4ee6a4SAndroid Build Coastguard Worker             error!("{} failed to disable msix: {}", self.debug_label(), e);
1055*bb4ee6a4SAndroid Build Coastguard Worker             return;
1056*bb4ee6a4SAndroid Build Coastguard Worker         }
1057*bb4ee6a4SAndroid Build Coastguard Worker         self.irq_type = None;
1058*bb4ee6a4SAndroid Build Coastguard Worker         self.enable_intx();
1059*bb4ee6a4SAndroid Build Coastguard Worker     }
1060*bb4ee6a4SAndroid Build Coastguard Worker 
msix_vectors_update(&self) -> Result<(), VfioError>1061*bb4ee6a4SAndroid Build Coastguard Worker     fn msix_vectors_update(&self) -> Result<(), VfioError> {
1062*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(cap) = &self.msix_cap {
1063*bb4ee6a4SAndroid Build Coastguard Worker             self.device
1064*bb4ee6a4SAndroid Build Coastguard Worker                 .irq_enable(&cap.lock().get_msix_irqfds(), VFIO_PCI_MSIX_IRQ_INDEX, 0)?;
1065*bb4ee6a4SAndroid Build Coastguard Worker         }
1066*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
1067*bb4ee6a4SAndroid Build Coastguard Worker     }
1068*bb4ee6a4SAndroid Build Coastguard Worker 
msix_vector_update(&self, index: usize, irqfd: Option<&Event>)1069*bb4ee6a4SAndroid Build Coastguard Worker     fn msix_vector_update(&self, index: usize, irqfd: Option<&Event>) {
1070*bb4ee6a4SAndroid Build Coastguard Worker         if let Err(e) = self
1071*bb4ee6a4SAndroid Build Coastguard Worker             .device
1072*bb4ee6a4SAndroid Build Coastguard Worker             .irq_enable(&[irqfd], VFIO_PCI_MSIX_IRQ_INDEX, index as u32)
1073*bb4ee6a4SAndroid Build Coastguard Worker         {
1074*bb4ee6a4SAndroid Build Coastguard Worker             error!(
1075*bb4ee6a4SAndroid Build Coastguard Worker                 "{} failed to update msix vector {}: {}",
1076*bb4ee6a4SAndroid Build Coastguard Worker                 self.debug_label(),
1077*bb4ee6a4SAndroid Build Coastguard Worker                 index,
1078*bb4ee6a4SAndroid Build Coastguard Worker                 e
1079*bb4ee6a4SAndroid Build Coastguard Worker             );
1080*bb4ee6a4SAndroid Build Coastguard Worker         }
1081*bb4ee6a4SAndroid Build Coastguard Worker     }
1082*bb4ee6a4SAndroid Build Coastguard Worker 
adjust_bar_mmap( &self, bar_mmaps: Vec<vfio_region_sparse_mmap_area>, remove_mmaps: &[AddressRange], ) -> Vec<vfio_region_sparse_mmap_area>1083*bb4ee6a4SAndroid Build Coastguard Worker     fn adjust_bar_mmap(
1084*bb4ee6a4SAndroid Build Coastguard Worker         &self,
1085*bb4ee6a4SAndroid Build Coastguard Worker         bar_mmaps: Vec<vfio_region_sparse_mmap_area>,
1086*bb4ee6a4SAndroid Build Coastguard Worker         remove_mmaps: &[AddressRange],
1087*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Vec<vfio_region_sparse_mmap_area> {
1088*bb4ee6a4SAndroid Build Coastguard Worker         let mut mmaps: Vec<vfio_region_sparse_mmap_area> = Vec::with_capacity(bar_mmaps.len());
1089*bb4ee6a4SAndroid Build Coastguard Worker         let pgmask = (pagesize() as u64) - 1;
1090*bb4ee6a4SAndroid Build Coastguard Worker 
1091*bb4ee6a4SAndroid Build Coastguard Worker         for mmap in bar_mmaps.iter() {
1092*bb4ee6a4SAndroid Build Coastguard Worker             let mmap_range = if let Some(mmap_range) =
1093*bb4ee6a4SAndroid Build Coastguard Worker                 AddressRange::from_start_and_size(mmap.offset, mmap.size)
1094*bb4ee6a4SAndroid Build Coastguard Worker             {
1095*bb4ee6a4SAndroid Build Coastguard Worker                 mmap_range
1096*bb4ee6a4SAndroid Build Coastguard Worker             } else {
1097*bb4ee6a4SAndroid Build Coastguard Worker                 continue;
1098*bb4ee6a4SAndroid Build Coastguard Worker             };
1099*bb4ee6a4SAndroid Build Coastguard Worker             let mut to_mmap = match VfioResourceAllocator::new(mmap_range) {
1100*bb4ee6a4SAndroid Build Coastguard Worker                 Ok(a) => a,
1101*bb4ee6a4SAndroid Build Coastguard Worker                 Err(e) => {
1102*bb4ee6a4SAndroid Build Coastguard Worker                     error!("{} adjust_bar_mmap failed: {}", self.debug_label(), e);
1103*bb4ee6a4SAndroid Build Coastguard Worker                     mmaps.clear();
1104*bb4ee6a4SAndroid Build Coastguard Worker                     return mmaps;
1105*bb4ee6a4SAndroid Build Coastguard Worker                 }
1106*bb4ee6a4SAndroid Build Coastguard Worker             };
1107*bb4ee6a4SAndroid Build Coastguard Worker 
1108*bb4ee6a4SAndroid Build Coastguard Worker             for &(mut remove_range) in remove_mmaps.iter() {
1109*bb4ee6a4SAndroid Build Coastguard Worker                 remove_range = remove_range.intersect(mmap_range);
1110*bb4ee6a4SAndroid Build Coastguard Worker                 if !remove_range.is_empty() {
1111*bb4ee6a4SAndroid Build Coastguard Worker                     // align offsets to page size
1112*bb4ee6a4SAndroid Build Coastguard Worker                     let begin = remove_range.start & !pgmask;
1113*bb4ee6a4SAndroid Build Coastguard Worker                     let end = ((remove_range.end + 1 + pgmask) & !pgmask) - 1;
1114*bb4ee6a4SAndroid Build Coastguard Worker                     let remove_range = AddressRange::from_start_and_end(begin, end);
1115*bb4ee6a4SAndroid Build Coastguard Worker                     if let Err(e) = to_mmap.allocate_at_can_overlap(remove_range) {
1116*bb4ee6a4SAndroid Build Coastguard Worker                         error!("{} adjust_bar_mmap failed: {}", self.debug_label(), e);
1117*bb4ee6a4SAndroid Build Coastguard Worker                     }
1118*bb4ee6a4SAndroid Build Coastguard Worker                 }
1119*bb4ee6a4SAndroid Build Coastguard Worker             }
1120*bb4ee6a4SAndroid Build Coastguard Worker 
1121*bb4ee6a4SAndroid Build Coastguard Worker             for mmap in to_mmap.regions {
1122*bb4ee6a4SAndroid Build Coastguard Worker                 mmaps.push(vfio_region_sparse_mmap_area {
1123*bb4ee6a4SAndroid Build Coastguard Worker                     offset: mmap.start,
1124*bb4ee6a4SAndroid Build Coastguard Worker                     size: mmap.end - mmap.start + 1,
1125*bb4ee6a4SAndroid Build Coastguard Worker                 });
1126*bb4ee6a4SAndroid Build Coastguard Worker             }
1127*bb4ee6a4SAndroid Build Coastguard Worker         }
1128*bb4ee6a4SAndroid Build Coastguard Worker 
1129*bb4ee6a4SAndroid Build Coastguard Worker         mmaps
1130*bb4ee6a4SAndroid Build Coastguard Worker     }
1131*bb4ee6a4SAndroid Build Coastguard Worker 
remove_bar_mmap_msix( &self, bar_index: PciBarIndex, bar_mmaps: Vec<vfio_region_sparse_mmap_area>, ) -> Vec<vfio_region_sparse_mmap_area>1132*bb4ee6a4SAndroid Build Coastguard Worker     fn remove_bar_mmap_msix(
1133*bb4ee6a4SAndroid Build Coastguard Worker         &self,
1134*bb4ee6a4SAndroid Build Coastguard Worker         bar_index: PciBarIndex,
1135*bb4ee6a4SAndroid Build Coastguard Worker         bar_mmaps: Vec<vfio_region_sparse_mmap_area>,
1136*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Vec<vfio_region_sparse_mmap_area> {
1137*bb4ee6a4SAndroid Build Coastguard Worker         let msix_cap = &self.msix_cap.as_ref().unwrap().lock();
1138*bb4ee6a4SAndroid Build Coastguard Worker         let mut msix_regions = Vec::new();
1139*bb4ee6a4SAndroid Build Coastguard Worker 
1140*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(t) = msix_cap.get_msix_table(bar_index) {
1141*bb4ee6a4SAndroid Build Coastguard Worker             msix_regions.push(t);
1142*bb4ee6a4SAndroid Build Coastguard Worker         }
1143*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(p) = msix_cap.get_msix_pba(bar_index) {
1144*bb4ee6a4SAndroid Build Coastguard Worker             msix_regions.push(p);
1145*bb4ee6a4SAndroid Build Coastguard Worker         }
1146*bb4ee6a4SAndroid Build Coastguard Worker 
1147*bb4ee6a4SAndroid Build Coastguard Worker         if msix_regions.is_empty() {
1148*bb4ee6a4SAndroid Build Coastguard Worker             return bar_mmaps;
1149*bb4ee6a4SAndroid Build Coastguard Worker         }
1150*bb4ee6a4SAndroid Build Coastguard Worker 
1151*bb4ee6a4SAndroid Build Coastguard Worker         self.adjust_bar_mmap(bar_mmaps, &msix_regions)
1152*bb4ee6a4SAndroid Build Coastguard Worker     }
1153*bb4ee6a4SAndroid Build Coastguard Worker 
add_bar_mmap(&self, index: PciBarIndex, bar_addr: u64) -> Vec<VmMemoryRegionId>1154*bb4ee6a4SAndroid Build Coastguard Worker     fn add_bar_mmap(&self, index: PciBarIndex, bar_addr: u64) -> Vec<VmMemoryRegionId> {
1155*bb4ee6a4SAndroid Build Coastguard Worker         let mut mmaps_ids: Vec<VmMemoryRegionId> = Vec::new();
1156*bb4ee6a4SAndroid Build Coastguard Worker         if self.device.get_region_flags(index) & VFIO_REGION_INFO_FLAG_MMAP != 0 {
1157*bb4ee6a4SAndroid Build Coastguard Worker             // the bar storing msix table and pba couldn't mmap.
1158*bb4ee6a4SAndroid Build Coastguard Worker             // these bars should be trapped, so that msix could be emulated.
1159*bb4ee6a4SAndroid Build Coastguard Worker             let mut mmaps = self.device.get_region_mmap(index);
1160*bb4ee6a4SAndroid Build Coastguard Worker 
1161*bb4ee6a4SAndroid Build Coastguard Worker             if self.msix_cap.is_some() {
1162*bb4ee6a4SAndroid Build Coastguard Worker                 mmaps = self.remove_bar_mmap_msix(index, mmaps);
1163*bb4ee6a4SAndroid Build Coastguard Worker             }
1164*bb4ee6a4SAndroid Build Coastguard Worker             if mmaps.is_empty() {
1165*bb4ee6a4SAndroid Build Coastguard Worker                 return mmaps_ids;
1166*bb4ee6a4SAndroid Build Coastguard Worker             }
1167*bb4ee6a4SAndroid Build Coastguard Worker 
1168*bb4ee6a4SAndroid Build Coastguard Worker             for mmap in mmaps.iter() {
1169*bb4ee6a4SAndroid Build Coastguard Worker                 let mmap_offset = mmap.offset;
1170*bb4ee6a4SAndroid Build Coastguard Worker                 let mmap_size = mmap.size;
1171*bb4ee6a4SAndroid Build Coastguard Worker                 let guest_map_start = bar_addr + mmap_offset;
1172*bb4ee6a4SAndroid Build Coastguard Worker                 let region_offset = self.device.get_region_offset(index);
1173*bb4ee6a4SAndroid Build Coastguard Worker                 let offset = region_offset + mmap_offset;
1174*bb4ee6a4SAndroid Build Coastguard Worker                 let descriptor = match self.device.device_file().try_clone() {
1175*bb4ee6a4SAndroid Build Coastguard Worker                     Ok(device_file) => device_file.into(),
1176*bb4ee6a4SAndroid Build Coastguard Worker                     Err(_) => break,
1177*bb4ee6a4SAndroid Build Coastguard Worker                 };
1178*bb4ee6a4SAndroid Build Coastguard Worker                 match self.vm_memory_client.register_memory(
1179*bb4ee6a4SAndroid Build Coastguard Worker                     VmMemorySource::Descriptor {
1180*bb4ee6a4SAndroid Build Coastguard Worker                         descriptor,
1181*bb4ee6a4SAndroid Build Coastguard Worker                         offset,
1182*bb4ee6a4SAndroid Build Coastguard Worker                         size: mmap_size,
1183*bb4ee6a4SAndroid Build Coastguard Worker                     },
1184*bb4ee6a4SAndroid Build Coastguard Worker                     VmMemoryDestination::GuestPhysicalAddress(guest_map_start),
1185*bb4ee6a4SAndroid Build Coastguard Worker                     Protection::read_write(),
1186*bb4ee6a4SAndroid Build Coastguard Worker                     MemCacheType::CacheCoherent,
1187*bb4ee6a4SAndroid Build Coastguard Worker                 ) {
1188*bb4ee6a4SAndroid Build Coastguard Worker                     Ok(id) => {
1189*bb4ee6a4SAndroid Build Coastguard Worker                         mmaps_ids.push(id);
1190*bb4ee6a4SAndroid Build Coastguard Worker                     }
1191*bb4ee6a4SAndroid Build Coastguard Worker                     Err(e) => {
1192*bb4ee6a4SAndroid Build Coastguard Worker                         error!("register_memory failed: {}", e);
1193*bb4ee6a4SAndroid Build Coastguard Worker                         break;
1194*bb4ee6a4SAndroid Build Coastguard Worker                     }
1195*bb4ee6a4SAndroid Build Coastguard Worker                 }
1196*bb4ee6a4SAndroid Build Coastguard Worker             }
1197*bb4ee6a4SAndroid Build Coastguard Worker         }
1198*bb4ee6a4SAndroid Build Coastguard Worker 
1199*bb4ee6a4SAndroid Build Coastguard Worker         mmaps_ids
1200*bb4ee6a4SAndroid Build Coastguard Worker     }
1201*bb4ee6a4SAndroid Build Coastguard Worker 
remove_bar_mmap(&self, mmap_ids: &[VmMemoryRegionId])1202*bb4ee6a4SAndroid Build Coastguard Worker     fn remove_bar_mmap(&self, mmap_ids: &[VmMemoryRegionId]) {
1203*bb4ee6a4SAndroid Build Coastguard Worker         for mmap_id in mmap_ids {
1204*bb4ee6a4SAndroid Build Coastguard Worker             if let Err(e) = self.vm_memory_client.unregister_memory(*mmap_id) {
1205*bb4ee6a4SAndroid Build Coastguard Worker                 error!("unregister_memory failed: {}", e);
1206*bb4ee6a4SAndroid Build Coastguard Worker             }
1207*bb4ee6a4SAndroid Build Coastguard Worker         }
1208*bb4ee6a4SAndroid Build Coastguard Worker     }
1209*bb4ee6a4SAndroid Build Coastguard Worker 
disable_bars_mmap(&mut self)1210*bb4ee6a4SAndroid Build Coastguard Worker     fn disable_bars_mmap(&mut self) {
1211*bb4ee6a4SAndroid Build Coastguard Worker         for (_, (_, mmap_ids)) in self.mapped_mmio_bars.iter() {
1212*bb4ee6a4SAndroid Build Coastguard Worker             self.remove_bar_mmap(mmap_ids);
1213*bb4ee6a4SAndroid Build Coastguard Worker         }
1214*bb4ee6a4SAndroid Build Coastguard Worker         self.mapped_mmio_bars.clear();
1215*bb4ee6a4SAndroid Build Coastguard Worker     }
1216*bb4ee6a4SAndroid Build Coastguard Worker 
commit_bars_mmap(&mut self)1217*bb4ee6a4SAndroid Build Coastguard Worker     fn commit_bars_mmap(&mut self) {
1218*bb4ee6a4SAndroid Build Coastguard Worker         // Unmap all bars before remapping bars, to prevent issues with overlap
1219*bb4ee6a4SAndroid Build Coastguard Worker         let mut needs_map = Vec::new();
1220*bb4ee6a4SAndroid Build Coastguard Worker         for mmio_info in self.mmio_regions.iter() {
1221*bb4ee6a4SAndroid Build Coastguard Worker             let bar_idx = mmio_info.bar_index();
1222*bb4ee6a4SAndroid Build Coastguard Worker             let addr = mmio_info.address();
1223*bb4ee6a4SAndroid Build Coastguard Worker 
1224*bb4ee6a4SAndroid Build Coastguard Worker             if let Some((cur_addr, ids)) = self.mapped_mmio_bars.remove(&bar_idx) {
1225*bb4ee6a4SAndroid Build Coastguard Worker                 if cur_addr == addr {
1226*bb4ee6a4SAndroid Build Coastguard Worker                     self.mapped_mmio_bars.insert(bar_idx, (cur_addr, ids));
1227*bb4ee6a4SAndroid Build Coastguard Worker                     continue;
1228*bb4ee6a4SAndroid Build Coastguard Worker                 } else {
1229*bb4ee6a4SAndroid Build Coastguard Worker                     self.remove_bar_mmap(&ids);
1230*bb4ee6a4SAndroid Build Coastguard Worker                 }
1231*bb4ee6a4SAndroid Build Coastguard Worker             }
1232*bb4ee6a4SAndroid Build Coastguard Worker 
1233*bb4ee6a4SAndroid Build Coastguard Worker             if addr != 0 {
1234*bb4ee6a4SAndroid Build Coastguard Worker                 needs_map.push((bar_idx, addr));
1235*bb4ee6a4SAndroid Build Coastguard Worker             }
1236*bb4ee6a4SAndroid Build Coastguard Worker         }
1237*bb4ee6a4SAndroid Build Coastguard Worker 
1238*bb4ee6a4SAndroid Build Coastguard Worker         for (bar_idx, addr) in needs_map.iter() {
1239*bb4ee6a4SAndroid Build Coastguard Worker             let ids = self.add_bar_mmap(*bar_idx, *addr);
1240*bb4ee6a4SAndroid Build Coastguard Worker             self.mapped_mmio_bars.insert(*bar_idx, (*addr, ids));
1241*bb4ee6a4SAndroid Build Coastguard Worker         }
1242*bb4ee6a4SAndroid Build Coastguard Worker     }
1243*bb4ee6a4SAndroid Build Coastguard Worker 
close(&mut self)1244*bb4ee6a4SAndroid Build Coastguard Worker     fn close(&mut self) {
1245*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(msi) = self.msi_cap.as_mut() {
1246*bb4ee6a4SAndroid Build Coastguard Worker             msi.destroy();
1247*bb4ee6a4SAndroid Build Coastguard Worker         }
1248*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(msix) = &self.msix_cap {
1249*bb4ee6a4SAndroid Build Coastguard Worker             msix.lock().destroy();
1250*bb4ee6a4SAndroid Build Coastguard Worker         }
1251*bb4ee6a4SAndroid Build Coastguard Worker         self.disable_bars_mmap();
1252*bb4ee6a4SAndroid Build Coastguard Worker         self.device.close();
1253*bb4ee6a4SAndroid Build Coastguard Worker     }
1254*bb4ee6a4SAndroid Build Coastguard Worker 
start_work_thread(&mut self)1255*bb4ee6a4SAndroid Build Coastguard Worker     fn start_work_thread(&mut self) {
1256*bb4ee6a4SAndroid Build Coastguard Worker         let vm_socket = match self.vm_socket_vm.take() {
1257*bb4ee6a4SAndroid Build Coastguard Worker             Some(socket) => socket,
1258*bb4ee6a4SAndroid Build Coastguard Worker             None => return,
1259*bb4ee6a4SAndroid Build Coastguard Worker         };
1260*bb4ee6a4SAndroid Build Coastguard Worker 
1261*bb4ee6a4SAndroid Build Coastguard Worker         let req_evt = match Event::new() {
1262*bb4ee6a4SAndroid Build Coastguard Worker             Ok(evt) => {
1263*bb4ee6a4SAndroid Build Coastguard Worker                 if let Err(e) = self
1264*bb4ee6a4SAndroid Build Coastguard Worker                     .device
1265*bb4ee6a4SAndroid Build Coastguard Worker                     .irq_enable(&[Some(&evt)], VFIO_PCI_REQ_IRQ_INDEX, 0)
1266*bb4ee6a4SAndroid Build Coastguard Worker                 {
1267*bb4ee6a4SAndroid Build Coastguard Worker                     error!("{} enable req_irq failed: {}", self.debug_label(), e);
1268*bb4ee6a4SAndroid Build Coastguard Worker                     return;
1269*bb4ee6a4SAndroid Build Coastguard Worker                 }
1270*bb4ee6a4SAndroid Build Coastguard Worker                 evt
1271*bb4ee6a4SAndroid Build Coastguard Worker             }
1272*bb4ee6a4SAndroid Build Coastguard Worker             Err(_) => return,
1273*bb4ee6a4SAndroid Build Coastguard Worker         };
1274*bb4ee6a4SAndroid Build Coastguard Worker 
1275*bb4ee6a4SAndroid Build Coastguard Worker         let (self_pm_evt, pm_evt) = match Event::new().and_then(|e| Ok((e.try_clone()?, e))) {
1276*bb4ee6a4SAndroid Build Coastguard Worker             Ok(v) => v,
1277*bb4ee6a4SAndroid Build Coastguard Worker             Err(e) => {
1278*bb4ee6a4SAndroid Build Coastguard Worker                 error!(
1279*bb4ee6a4SAndroid Build Coastguard Worker                     "{} failed creating PM Event pair: {}",
1280*bb4ee6a4SAndroid Build Coastguard Worker                     self.debug_label(),
1281*bb4ee6a4SAndroid Build Coastguard Worker                     e
1282*bb4ee6a4SAndroid Build Coastguard Worker                 );
1283*bb4ee6a4SAndroid Build Coastguard Worker                 return;
1284*bb4ee6a4SAndroid Build Coastguard Worker             }
1285*bb4ee6a4SAndroid Build Coastguard Worker         };
1286*bb4ee6a4SAndroid Build Coastguard Worker         self.pm_evt = Some(self_pm_evt);
1287*bb4ee6a4SAndroid Build Coastguard Worker 
1288*bb4ee6a4SAndroid Build Coastguard Worker         let (self_acpi_notify_evt, acpi_notify_evt) =
1289*bb4ee6a4SAndroid Build Coastguard Worker             match Event::new().and_then(|e| Ok((e.try_clone()?, e))) {
1290*bb4ee6a4SAndroid Build Coastguard Worker                 Ok(v) => v,
1291*bb4ee6a4SAndroid Build Coastguard Worker                 Err(e) => {
1292*bb4ee6a4SAndroid Build Coastguard Worker                     error!(
1293*bb4ee6a4SAndroid Build Coastguard Worker                         "{} failed creating ACPI Event pair: {}",
1294*bb4ee6a4SAndroid Build Coastguard Worker                         self.debug_label(),
1295*bb4ee6a4SAndroid Build Coastguard Worker                         e
1296*bb4ee6a4SAndroid Build Coastguard Worker                     );
1297*bb4ee6a4SAndroid Build Coastguard Worker                     return;
1298*bb4ee6a4SAndroid Build Coastguard Worker                 }
1299*bb4ee6a4SAndroid Build Coastguard Worker             };
1300*bb4ee6a4SAndroid Build Coastguard Worker         self.acpi_notification_evt = Some(self_acpi_notify_evt);
1301*bb4ee6a4SAndroid Build Coastguard Worker 
1302*bb4ee6a4SAndroid Build Coastguard Worker         if let Err(e) = self.enable_acpi_notification() {
1303*bb4ee6a4SAndroid Build Coastguard Worker             error!("{}: {}", self.debug_label(), e);
1304*bb4ee6a4SAndroid Build Coastguard Worker         }
1305*bb4ee6a4SAndroid Build Coastguard Worker 
1306*bb4ee6a4SAndroid Build Coastguard Worker         let mut msix_evt = Vec::new();
1307*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(msix_cap) = &self.msix_cap {
1308*bb4ee6a4SAndroid Build Coastguard Worker             msix_evt = msix_cap.lock().clone_msix_evt();
1309*bb4ee6a4SAndroid Build Coastguard Worker         }
1310*bb4ee6a4SAndroid Build Coastguard Worker 
1311*bb4ee6a4SAndroid Build Coastguard Worker         let name = self.device.device_name().to_string();
1312*bb4ee6a4SAndroid Build Coastguard Worker         let address = self.pci_address.expect("Unassigned PCI Address.");
1313*bb4ee6a4SAndroid Build Coastguard Worker         let sysfs_path = self.sysfs_path.clone();
1314*bb4ee6a4SAndroid Build Coastguard Worker         let pm_cap = self.pm_cap.clone();
1315*bb4ee6a4SAndroid Build Coastguard Worker         let msix_cap = self.msix_cap.clone();
1316*bb4ee6a4SAndroid Build Coastguard Worker         let is_in_low_power = self.is_in_low_power.clone();
1317*bb4ee6a4SAndroid Build Coastguard Worker         let gpe_nr = self.gpe;
1318*bb4ee6a4SAndroid Build Coastguard Worker         let notification_val = self.acpi_notifier_val.clone();
1319*bb4ee6a4SAndroid Build Coastguard Worker         self.worker_thread = Some(WorkerThread::start("vfio_pci", move |kill_evt| {
1320*bb4ee6a4SAndroid Build Coastguard Worker             let mut worker = VfioPciWorker {
1321*bb4ee6a4SAndroid Build Coastguard Worker                 address,
1322*bb4ee6a4SAndroid Build Coastguard Worker                 sysfs_path,
1323*bb4ee6a4SAndroid Build Coastguard Worker                 vm_socket,
1324*bb4ee6a4SAndroid Build Coastguard Worker                 name,
1325*bb4ee6a4SAndroid Build Coastguard Worker                 pm_cap,
1326*bb4ee6a4SAndroid Build Coastguard Worker                 msix_cap,
1327*bb4ee6a4SAndroid Build Coastguard Worker             };
1328*bb4ee6a4SAndroid Build Coastguard Worker             worker.run(
1329*bb4ee6a4SAndroid Build Coastguard Worker                 req_evt,
1330*bb4ee6a4SAndroid Build Coastguard Worker                 pm_evt,
1331*bb4ee6a4SAndroid Build Coastguard Worker                 acpi_notify_evt,
1332*bb4ee6a4SAndroid Build Coastguard Worker                 kill_evt,
1333*bb4ee6a4SAndroid Build Coastguard Worker                 msix_evt,
1334*bb4ee6a4SAndroid Build Coastguard Worker                 is_in_low_power,
1335*bb4ee6a4SAndroid Build Coastguard Worker                 gpe_nr,
1336*bb4ee6a4SAndroid Build Coastguard Worker                 notification_val,
1337*bb4ee6a4SAndroid Build Coastguard Worker             );
1338*bb4ee6a4SAndroid Build Coastguard Worker             worker
1339*bb4ee6a4SAndroid Build Coastguard Worker         }));
1340*bb4ee6a4SAndroid Build Coastguard Worker         self.activated = true;
1341*bb4ee6a4SAndroid Build Coastguard Worker     }
1342*bb4ee6a4SAndroid Build Coastguard Worker 
collect_bars(&mut self) -> Vec<PciBarConfiguration>1343*bb4ee6a4SAndroid Build Coastguard Worker     fn collect_bars(&mut self) -> Vec<PciBarConfiguration> {
1344*bb4ee6a4SAndroid Build Coastguard Worker         let mut i = VFIO_PCI_BAR0_REGION_INDEX;
1345*bb4ee6a4SAndroid Build Coastguard Worker         let mut mem_bars: Vec<PciBarConfiguration> = Vec::new();
1346*bb4ee6a4SAndroid Build Coastguard Worker 
1347*bb4ee6a4SAndroid Build Coastguard Worker         while i <= VFIO_PCI_ROM_REGION_INDEX {
1348*bb4ee6a4SAndroid Build Coastguard Worker             let mut low: u32 = 0xffffffff;
1349*bb4ee6a4SAndroid Build Coastguard Worker             let offset: u32 = if i == VFIO_PCI_ROM_REGION_INDEX {
1350*bb4ee6a4SAndroid Build Coastguard Worker                 0x30
1351*bb4ee6a4SAndroid Build Coastguard Worker             } else {
1352*bb4ee6a4SAndroid Build Coastguard Worker                 0x10 + i * 4
1353*bb4ee6a4SAndroid Build Coastguard Worker             };
1354*bb4ee6a4SAndroid Build Coastguard Worker             self.config.write_config(low, offset);
1355*bb4ee6a4SAndroid Build Coastguard Worker             low = self.config.read_config(offset);
1356*bb4ee6a4SAndroid Build Coastguard Worker 
1357*bb4ee6a4SAndroid Build Coastguard Worker             let low_flag = low & 0xf;
1358*bb4ee6a4SAndroid Build Coastguard Worker             let is_64bit = low_flag & 0x4 == 0x4;
1359*bb4ee6a4SAndroid Build Coastguard Worker             if (low_flag & 0x1 == 0 || i == VFIO_PCI_ROM_REGION_INDEX) && low != 0 {
1360*bb4ee6a4SAndroid Build Coastguard Worker                 let mut upper: u32 = 0xffffffff;
1361*bb4ee6a4SAndroid Build Coastguard Worker                 if is_64bit {
1362*bb4ee6a4SAndroid Build Coastguard Worker                     self.config.write_config(upper, offset + 4);
1363*bb4ee6a4SAndroid Build Coastguard Worker                     upper = self.config.read_config(offset + 4);
1364*bb4ee6a4SAndroid Build Coastguard Worker                 }
1365*bb4ee6a4SAndroid Build Coastguard Worker 
1366*bb4ee6a4SAndroid Build Coastguard Worker                 low &= 0xffff_fff0;
1367*bb4ee6a4SAndroid Build Coastguard Worker                 let mut size: u64 = u64::from(upper);
1368*bb4ee6a4SAndroid Build Coastguard Worker                 size <<= 32;
1369*bb4ee6a4SAndroid Build Coastguard Worker                 size |= u64::from(low);
1370*bb4ee6a4SAndroid Build Coastguard Worker                 size = !size + 1;
1371*bb4ee6a4SAndroid Build Coastguard Worker                 let region_type = if is_64bit {
1372*bb4ee6a4SAndroid Build Coastguard Worker                     PciBarRegionType::Memory64BitRegion
1373*bb4ee6a4SAndroid Build Coastguard Worker                 } else {
1374*bb4ee6a4SAndroid Build Coastguard Worker                     PciBarRegionType::Memory32BitRegion
1375*bb4ee6a4SAndroid Build Coastguard Worker                 };
1376*bb4ee6a4SAndroid Build Coastguard Worker                 let prefetch = if low_flag & 0x8 == 0x8 {
1377*bb4ee6a4SAndroid Build Coastguard Worker                     PciBarPrefetchable::Prefetchable
1378*bb4ee6a4SAndroid Build Coastguard Worker                 } else {
1379*bb4ee6a4SAndroid Build Coastguard Worker                     PciBarPrefetchable::NotPrefetchable
1380*bb4ee6a4SAndroid Build Coastguard Worker                 };
1381*bb4ee6a4SAndroid Build Coastguard Worker                 mem_bars.push(PciBarConfiguration::new(
1382*bb4ee6a4SAndroid Build Coastguard Worker                     i as usize,
1383*bb4ee6a4SAndroid Build Coastguard Worker                     size,
1384*bb4ee6a4SAndroid Build Coastguard Worker                     region_type,
1385*bb4ee6a4SAndroid Build Coastguard Worker                     prefetch,
1386*bb4ee6a4SAndroid Build Coastguard Worker                 ));
1387*bb4ee6a4SAndroid Build Coastguard Worker             } else if low_flag & 0x1 == 0x1 {
1388*bb4ee6a4SAndroid Build Coastguard Worker                 let size = !(low & 0xffff_fffc) + 1;
1389*bb4ee6a4SAndroid Build Coastguard Worker                 self.io_regions.push(PciBarConfiguration::new(
1390*bb4ee6a4SAndroid Build Coastguard Worker                     i as usize,
1391*bb4ee6a4SAndroid Build Coastguard Worker                     size.into(),
1392*bb4ee6a4SAndroid Build Coastguard Worker                     PciBarRegionType::IoRegion,
1393*bb4ee6a4SAndroid Build Coastguard Worker                     PciBarPrefetchable::NotPrefetchable,
1394*bb4ee6a4SAndroid Build Coastguard Worker                 ));
1395*bb4ee6a4SAndroid Build Coastguard Worker             }
1396*bb4ee6a4SAndroid Build Coastguard Worker 
1397*bb4ee6a4SAndroid Build Coastguard Worker             if is_64bit {
1398*bb4ee6a4SAndroid Build Coastguard Worker                 i += 2;
1399*bb4ee6a4SAndroid Build Coastguard Worker             } else {
1400*bb4ee6a4SAndroid Build Coastguard Worker                 i += 1;
1401*bb4ee6a4SAndroid Build Coastguard Worker             }
1402*bb4ee6a4SAndroid Build Coastguard Worker         }
1403*bb4ee6a4SAndroid Build Coastguard Worker         mem_bars
1404*bb4ee6a4SAndroid Build Coastguard Worker     }
1405*bb4ee6a4SAndroid Build Coastguard Worker 
configure_barmem(&mut self, bar_info: &PciBarConfiguration, bar_addr: u64)1406*bb4ee6a4SAndroid Build Coastguard Worker     fn configure_barmem(&mut self, bar_info: &PciBarConfiguration, bar_addr: u64) {
1407*bb4ee6a4SAndroid Build Coastguard Worker         let offset: u32 = bar_info.reg_index() as u32 * 4;
1408*bb4ee6a4SAndroid Build Coastguard Worker         let mmio_region = *bar_info;
1409*bb4ee6a4SAndroid Build Coastguard Worker         self.mmio_regions.push(mmio_region.set_address(bar_addr));
1410*bb4ee6a4SAndroid Build Coastguard Worker 
1411*bb4ee6a4SAndroid Build Coastguard Worker         let val: u32 = self.config.read_config(offset);
1412*bb4ee6a4SAndroid Build Coastguard Worker         let low = ((bar_addr & !0xf) as u32) | (val & 0xf);
1413*bb4ee6a4SAndroid Build Coastguard Worker         self.config.write_config(low, offset);
1414*bb4ee6a4SAndroid Build Coastguard Worker         if bar_info.is_64bit_memory() {
1415*bb4ee6a4SAndroid Build Coastguard Worker             let upper = (bar_addr >> 32) as u32;
1416*bb4ee6a4SAndroid Build Coastguard Worker             self.config.write_config(upper, offset + 4);
1417*bb4ee6a4SAndroid Build Coastguard Worker         }
1418*bb4ee6a4SAndroid Build Coastguard Worker     }
1419*bb4ee6a4SAndroid Build Coastguard Worker 
allocate_root_barmem( &mut self, mem_bars: &[PciBarConfiguration], resources: &mut SystemAllocator, ) -> Result<Vec<BarRange>, PciDeviceError>1420*bb4ee6a4SAndroid Build Coastguard Worker     fn allocate_root_barmem(
1421*bb4ee6a4SAndroid Build Coastguard Worker         &mut self,
1422*bb4ee6a4SAndroid Build Coastguard Worker         mem_bars: &[PciBarConfiguration],
1423*bb4ee6a4SAndroid Build Coastguard Worker         resources: &mut SystemAllocator,
1424*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Result<Vec<BarRange>, PciDeviceError> {
1425*bb4ee6a4SAndroid Build Coastguard Worker         let address = self.pci_address.unwrap();
1426*bb4ee6a4SAndroid Build Coastguard Worker         let mut ranges: Vec<BarRange> = Vec::new();
1427*bb4ee6a4SAndroid Build Coastguard Worker         for mem_bar in mem_bars {
1428*bb4ee6a4SAndroid Build Coastguard Worker             let bar_size = mem_bar.size();
1429*bb4ee6a4SAndroid Build Coastguard Worker             let mut bar_addr: u64 = 0;
1430*bb4ee6a4SAndroid Build Coastguard Worker             // Don't allocate mmio for hotplug device, OS will allocate it from
1431*bb4ee6a4SAndroid Build Coastguard Worker             // its parent's bridge window.
1432*bb4ee6a4SAndroid Build Coastguard Worker             if !self.hotplug {
1433*bb4ee6a4SAndroid Build Coastguard Worker                 bar_addr = resources
1434*bb4ee6a4SAndroid Build Coastguard Worker                     .allocate_mmio(
1435*bb4ee6a4SAndroid Build Coastguard Worker                         bar_size,
1436*bb4ee6a4SAndroid Build Coastguard Worker                         Alloc::PciBar {
1437*bb4ee6a4SAndroid Build Coastguard Worker                             bus: address.bus,
1438*bb4ee6a4SAndroid Build Coastguard Worker                             dev: address.dev,
1439*bb4ee6a4SAndroid Build Coastguard Worker                             func: address.func,
1440*bb4ee6a4SAndroid Build Coastguard Worker                             bar: mem_bar.bar_index() as u8,
1441*bb4ee6a4SAndroid Build Coastguard Worker                         },
1442*bb4ee6a4SAndroid Build Coastguard Worker                         "vfio_bar".to_string(),
1443*bb4ee6a4SAndroid Build Coastguard Worker                         AllocOptions::new()
1444*bb4ee6a4SAndroid Build Coastguard Worker                             .prefetchable(mem_bar.is_prefetchable())
1445*bb4ee6a4SAndroid Build Coastguard Worker                             .max_address(if mem_bar.is_64bit_memory() {
1446*bb4ee6a4SAndroid Build Coastguard Worker                                 u64::MAX
1447*bb4ee6a4SAndroid Build Coastguard Worker                             } else {
1448*bb4ee6a4SAndroid Build Coastguard Worker                                 u32::MAX.into()
1449*bb4ee6a4SAndroid Build Coastguard Worker                             })
1450*bb4ee6a4SAndroid Build Coastguard Worker                             .align(bar_size),
1451*bb4ee6a4SAndroid Build Coastguard Worker                     )
1452*bb4ee6a4SAndroid Build Coastguard Worker                     .map_err(|e| PciDeviceError::IoAllocationFailed(bar_size, e))?;
1453*bb4ee6a4SAndroid Build Coastguard Worker                 ranges.push(BarRange {
1454*bb4ee6a4SAndroid Build Coastguard Worker                     addr: bar_addr,
1455*bb4ee6a4SAndroid Build Coastguard Worker                     size: bar_size,
1456*bb4ee6a4SAndroid Build Coastguard Worker                     prefetchable: mem_bar.is_prefetchable(),
1457*bb4ee6a4SAndroid Build Coastguard Worker                 });
1458*bb4ee6a4SAndroid Build Coastguard Worker             }
1459*bb4ee6a4SAndroid Build Coastguard Worker             self.configure_barmem(mem_bar, bar_addr);
1460*bb4ee6a4SAndroid Build Coastguard Worker         }
1461*bb4ee6a4SAndroid Build Coastguard Worker         Ok(ranges)
1462*bb4ee6a4SAndroid Build Coastguard Worker     }
1463*bb4ee6a4SAndroid Build Coastguard Worker 
allocate_nonroot_barmem( &mut self, mem_bars: &mut [PciBarConfiguration], resources: &mut SystemAllocator, ) -> Result<Vec<BarRange>, PciDeviceError>1464*bb4ee6a4SAndroid Build Coastguard Worker     fn allocate_nonroot_barmem(
1465*bb4ee6a4SAndroid Build Coastguard Worker         &mut self,
1466*bb4ee6a4SAndroid Build Coastguard Worker         mem_bars: &mut [PciBarConfiguration],
1467*bb4ee6a4SAndroid Build Coastguard Worker         resources: &mut SystemAllocator,
1468*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Result<Vec<BarRange>, PciDeviceError> {
1469*bb4ee6a4SAndroid Build Coastguard Worker         const NON_PREFETCHABLE: usize = 0;
1470*bb4ee6a4SAndroid Build Coastguard Worker         const PREFETCHABLE: usize = 1;
1471*bb4ee6a4SAndroid Build Coastguard Worker         const ARRAY_SIZE: usize = 2;
1472*bb4ee6a4SAndroid Build Coastguard Worker         let mut membars: [Vec<PciBarConfiguration>; ARRAY_SIZE] = [Vec::new(), Vec::new()];
1473*bb4ee6a4SAndroid Build Coastguard Worker         let mut allocator: [VfioResourceAllocator; ARRAY_SIZE] = [
1474*bb4ee6a4SAndroid Build Coastguard Worker             match VfioResourceAllocator::new(AddressRange::from_start_and_end(0, u32::MAX as u64)) {
1475*bb4ee6a4SAndroid Build Coastguard Worker                 Ok(a) => a,
1476*bb4ee6a4SAndroid Build Coastguard Worker                 Err(e) => {
1477*bb4ee6a4SAndroid Build Coastguard Worker                     error!(
1478*bb4ee6a4SAndroid Build Coastguard Worker                         "{} init nonroot VfioResourceAllocator failed: {}",
1479*bb4ee6a4SAndroid Build Coastguard Worker                         self.debug_label(),
1480*bb4ee6a4SAndroid Build Coastguard Worker                         e
1481*bb4ee6a4SAndroid Build Coastguard Worker                     );
1482*bb4ee6a4SAndroid Build Coastguard Worker                     return Err(e);
1483*bb4ee6a4SAndroid Build Coastguard Worker                 }
1484*bb4ee6a4SAndroid Build Coastguard Worker             },
1485*bb4ee6a4SAndroid Build Coastguard Worker             match VfioResourceAllocator::new(AddressRange::from_start_and_end(0, u64::MAX)) {
1486*bb4ee6a4SAndroid Build Coastguard Worker                 Ok(a) => a,
1487*bb4ee6a4SAndroid Build Coastguard Worker                 Err(e) => {
1488*bb4ee6a4SAndroid Build Coastguard Worker                     error!(
1489*bb4ee6a4SAndroid Build Coastguard Worker                         "{} init nonroot VfioResourceAllocator failed: {}",
1490*bb4ee6a4SAndroid Build Coastguard Worker                         self.debug_label(),
1491*bb4ee6a4SAndroid Build Coastguard Worker                         e
1492*bb4ee6a4SAndroid Build Coastguard Worker                     );
1493*bb4ee6a4SAndroid Build Coastguard Worker                     return Err(e);
1494*bb4ee6a4SAndroid Build Coastguard Worker                 }
1495*bb4ee6a4SAndroid Build Coastguard Worker             },
1496*bb4ee6a4SAndroid Build Coastguard Worker         ];
1497*bb4ee6a4SAndroid Build Coastguard Worker         let mut memtype: [MmioType; ARRAY_SIZE] = [MmioType::Low, MmioType::High];
1498*bb4ee6a4SAndroid Build Coastguard Worker         // the window must be 1M-aligned as per the PCI spec
1499*bb4ee6a4SAndroid Build Coastguard Worker         let mut window_sz: [u64; ARRAY_SIZE] = [0; 2];
1500*bb4ee6a4SAndroid Build Coastguard Worker         let mut alignment: [u64; ARRAY_SIZE] = [0x100000; 2];
1501*bb4ee6a4SAndroid Build Coastguard Worker 
1502*bb4ee6a4SAndroid Build Coastguard Worker         // Descend by bar size, this could reduce allocated size for all the bars.
1503*bb4ee6a4SAndroid Build Coastguard Worker         mem_bars.sort_by_key(|a| Reverse(a.size()));
1504*bb4ee6a4SAndroid Build Coastguard Worker         for mem_bar in mem_bars {
1505*bb4ee6a4SAndroid Build Coastguard Worker             let prefetchable = mem_bar.is_prefetchable();
1506*bb4ee6a4SAndroid Build Coastguard Worker             let is_64bit = mem_bar.is_64bit_memory();
1507*bb4ee6a4SAndroid Build Coastguard Worker 
1508*bb4ee6a4SAndroid Build Coastguard Worker             // if one prefetchable bar is 32bit, all the prefetchable bars should be in Low MMIO,
1509*bb4ee6a4SAndroid Build Coastguard Worker             // as all the prefetchable bars should be in one region
1510*bb4ee6a4SAndroid Build Coastguard Worker             if prefetchable && !is_64bit {
1511*bb4ee6a4SAndroid Build Coastguard Worker                 memtype[PREFETCHABLE] = MmioType::Low;
1512*bb4ee6a4SAndroid Build Coastguard Worker             }
1513*bb4ee6a4SAndroid Build Coastguard Worker             let i = if prefetchable {
1514*bb4ee6a4SAndroid Build Coastguard Worker                 PREFETCHABLE
1515*bb4ee6a4SAndroid Build Coastguard Worker             } else {
1516*bb4ee6a4SAndroid Build Coastguard Worker                 NON_PREFETCHABLE
1517*bb4ee6a4SAndroid Build Coastguard Worker             };
1518*bb4ee6a4SAndroid Build Coastguard Worker             let bar_size = mem_bar.size();
1519*bb4ee6a4SAndroid Build Coastguard Worker             let start = match allocator[i].allocate_with_align(bar_size, bar_size) {
1520*bb4ee6a4SAndroid Build Coastguard Worker                 Ok(s) => s,
1521*bb4ee6a4SAndroid Build Coastguard Worker                 Err(e) => {
1522*bb4ee6a4SAndroid Build Coastguard Worker                     error!(
1523*bb4ee6a4SAndroid Build Coastguard Worker                         "{} nonroot allocate_wit_align failed: {}",
1524*bb4ee6a4SAndroid Build Coastguard Worker                         self.debug_label(),
1525*bb4ee6a4SAndroid Build Coastguard Worker                         e
1526*bb4ee6a4SAndroid Build Coastguard Worker                     );
1527*bb4ee6a4SAndroid Build Coastguard Worker                     return Err(e);
1528*bb4ee6a4SAndroid Build Coastguard Worker                 }
1529*bb4ee6a4SAndroid Build Coastguard Worker             };
1530*bb4ee6a4SAndroid Build Coastguard Worker             window_sz[i] = max(window_sz[i], start + bar_size);
1531*bb4ee6a4SAndroid Build Coastguard Worker             alignment[i] = max(alignment[i], bar_size);
1532*bb4ee6a4SAndroid Build Coastguard Worker             let mem_info = (*mem_bar).set_address(start);
1533*bb4ee6a4SAndroid Build Coastguard Worker             membars[i].push(mem_info);
1534*bb4ee6a4SAndroid Build Coastguard Worker         }
1535*bb4ee6a4SAndroid Build Coastguard Worker 
1536*bb4ee6a4SAndroid Build Coastguard Worker         let address = self.pci_address.unwrap();
1537*bb4ee6a4SAndroid Build Coastguard Worker         let mut ranges: Vec<BarRange> = Vec::new();
1538*bb4ee6a4SAndroid Build Coastguard Worker         for (index, bars) in membars.iter().enumerate() {
1539*bb4ee6a4SAndroid Build Coastguard Worker             if bars.is_empty() {
1540*bb4ee6a4SAndroid Build Coastguard Worker                 continue;
1541*bb4ee6a4SAndroid Build Coastguard Worker             }
1542*bb4ee6a4SAndroid Build Coastguard Worker 
1543*bb4ee6a4SAndroid Build Coastguard Worker             let i = if index == 1 {
1544*bb4ee6a4SAndroid Build Coastguard Worker                 PREFETCHABLE
1545*bb4ee6a4SAndroid Build Coastguard Worker             } else {
1546*bb4ee6a4SAndroid Build Coastguard Worker                 NON_PREFETCHABLE
1547*bb4ee6a4SAndroid Build Coastguard Worker             };
1548*bb4ee6a4SAndroid Build Coastguard Worker             let mut window_addr: u64 = 0;
1549*bb4ee6a4SAndroid Build Coastguard Worker             // Don't allocate mmio for hotplug device, OS will allocate it from
1550*bb4ee6a4SAndroid Build Coastguard Worker             // its parent's bridge window.
1551*bb4ee6a4SAndroid Build Coastguard Worker             if !self.hotplug {
1552*bb4ee6a4SAndroid Build Coastguard Worker                 window_sz[i] = (window_sz[i] + 0xfffff) & !0xfffff;
1553*bb4ee6a4SAndroid Build Coastguard Worker                 let alloc = if i == NON_PREFETCHABLE {
1554*bb4ee6a4SAndroid Build Coastguard Worker                     Alloc::PciBridgeWindow {
1555*bb4ee6a4SAndroid Build Coastguard Worker                         bus: address.bus,
1556*bb4ee6a4SAndroid Build Coastguard Worker                         dev: address.dev,
1557*bb4ee6a4SAndroid Build Coastguard Worker                         func: address.func,
1558*bb4ee6a4SAndroid Build Coastguard Worker                     }
1559*bb4ee6a4SAndroid Build Coastguard Worker                 } else {
1560*bb4ee6a4SAndroid Build Coastguard Worker                     Alloc::PciBridgePrefetchWindow {
1561*bb4ee6a4SAndroid Build Coastguard Worker                         bus: address.bus,
1562*bb4ee6a4SAndroid Build Coastguard Worker                         dev: address.dev,
1563*bb4ee6a4SAndroid Build Coastguard Worker                         func: address.func,
1564*bb4ee6a4SAndroid Build Coastguard Worker                     }
1565*bb4ee6a4SAndroid Build Coastguard Worker                 };
1566*bb4ee6a4SAndroid Build Coastguard Worker                 window_addr = resources
1567*bb4ee6a4SAndroid Build Coastguard Worker                     .mmio_allocator(memtype[i])
1568*bb4ee6a4SAndroid Build Coastguard Worker                     .allocate_with_align(
1569*bb4ee6a4SAndroid Build Coastguard Worker                         window_sz[i],
1570*bb4ee6a4SAndroid Build Coastguard Worker                         alloc,
1571*bb4ee6a4SAndroid Build Coastguard Worker                         "vfio_bar_window".to_string(),
1572*bb4ee6a4SAndroid Build Coastguard Worker                         alignment[i],
1573*bb4ee6a4SAndroid Build Coastguard Worker                     )
1574*bb4ee6a4SAndroid Build Coastguard Worker                     .map_err(|e| PciDeviceError::IoAllocationFailed(window_sz[i], e))?;
1575*bb4ee6a4SAndroid Build Coastguard Worker                 for mem_info in bars {
1576*bb4ee6a4SAndroid Build Coastguard Worker                     let bar_addr = window_addr + mem_info.address();
1577*bb4ee6a4SAndroid Build Coastguard Worker                     ranges.push(BarRange {
1578*bb4ee6a4SAndroid Build Coastguard Worker                         addr: bar_addr,
1579*bb4ee6a4SAndroid Build Coastguard Worker                         size: mem_info.size(),
1580*bb4ee6a4SAndroid Build Coastguard Worker                         prefetchable: mem_info.is_prefetchable(),
1581*bb4ee6a4SAndroid Build Coastguard Worker                     });
1582*bb4ee6a4SAndroid Build Coastguard Worker                 }
1583*bb4ee6a4SAndroid Build Coastguard Worker             }
1584*bb4ee6a4SAndroid Build Coastguard Worker 
1585*bb4ee6a4SAndroid Build Coastguard Worker             for mem_info in bars {
1586*bb4ee6a4SAndroid Build Coastguard Worker                 let bar_addr = window_addr + mem_info.address();
1587*bb4ee6a4SAndroid Build Coastguard Worker                 self.configure_barmem(mem_info, bar_addr);
1588*bb4ee6a4SAndroid Build Coastguard Worker             }
1589*bb4ee6a4SAndroid Build Coastguard Worker         }
1590*bb4ee6a4SAndroid Build Coastguard Worker         Ok(ranges)
1591*bb4ee6a4SAndroid Build Coastguard Worker     }
1592*bb4ee6a4SAndroid Build Coastguard Worker 
1593*bb4ee6a4SAndroid Build Coastguard Worker     /// Return the supported iova max address of the Vfio Pci device
get_max_iova(&self) -> u641594*bb4ee6a4SAndroid Build Coastguard Worker     pub fn get_max_iova(&self) -> u64 {
1595*bb4ee6a4SAndroid Build Coastguard Worker         self.device.get_max_addr()
1596*bb4ee6a4SAndroid Build Coastguard Worker     }
1597*bb4ee6a4SAndroid Build Coastguard Worker 
get_ext_cap_by_reg(&self, reg: u32) -> Option<ExtCap>1598*bb4ee6a4SAndroid Build Coastguard Worker     fn get_ext_cap_by_reg(&self, reg: u32) -> Option<ExtCap> {
1599*bb4ee6a4SAndroid Build Coastguard Worker         self.ext_caps
1600*bb4ee6a4SAndroid Build Coastguard Worker             .iter()
1601*bb4ee6a4SAndroid Build Coastguard Worker             .find(|ext_cap| reg >= ext_cap.offset && reg < ext_cap.offset + ext_cap.size)
1602*bb4ee6a4SAndroid Build Coastguard Worker             .cloned()
1603*bb4ee6a4SAndroid Build Coastguard Worker     }
1604*bb4ee6a4SAndroid Build Coastguard Worker 
is_skipped_reg(&self, reg: u32) -> bool1605*bb4ee6a4SAndroid Build Coastguard Worker     fn is_skipped_reg(&self, reg: u32) -> bool {
1606*bb4ee6a4SAndroid Build Coastguard Worker         // fast handle for pci config space
1607*bb4ee6a4SAndroid Build Coastguard Worker         if reg < PCI_CONFIG_SPACE_SIZE {
1608*bb4ee6a4SAndroid Build Coastguard Worker             return false;
1609*bb4ee6a4SAndroid Build Coastguard Worker         }
1610*bb4ee6a4SAndroid Build Coastguard Worker 
1611*bb4ee6a4SAndroid Build Coastguard Worker         self.get_ext_cap_by_reg(reg)
1612*bb4ee6a4SAndroid Build Coastguard Worker             .map_or(false, |cap| cap.is_skipped)
1613*bb4ee6a4SAndroid Build Coastguard Worker     }
1614*bb4ee6a4SAndroid Build Coastguard Worker }
1615*bb4ee6a4SAndroid Build Coastguard Worker 
1616*bb4ee6a4SAndroid Build Coastguard Worker impl PciDevice for VfioPciDevice {
debug_label(&self) -> String1617*bb4ee6a4SAndroid Build Coastguard Worker     fn debug_label(&self) -> String {
1618*bb4ee6a4SAndroid Build Coastguard Worker         format!("vfio {} device", self.device.device_name())
1619*bb4ee6a4SAndroid Build Coastguard Worker     }
1620*bb4ee6a4SAndroid Build Coastguard Worker 
preferred_address(&self) -> Option<PciAddress>1621*bb4ee6a4SAndroid Build Coastguard Worker     fn preferred_address(&self) -> Option<PciAddress> {
1622*bb4ee6a4SAndroid Build Coastguard Worker         Some(self.preferred_address)
1623*bb4ee6a4SAndroid Build Coastguard Worker     }
1624*bb4ee6a4SAndroid Build Coastguard Worker 
allocate_address( &mut self, resources: &mut SystemAllocator, ) -> Result<PciAddress, PciDeviceError>1625*bb4ee6a4SAndroid Build Coastguard Worker     fn allocate_address(
1626*bb4ee6a4SAndroid Build Coastguard Worker         &mut self,
1627*bb4ee6a4SAndroid Build Coastguard Worker         resources: &mut SystemAllocator,
1628*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Result<PciAddress, PciDeviceError> {
1629*bb4ee6a4SAndroid Build Coastguard Worker         if self.pci_address.is_none() {
1630*bb4ee6a4SAndroid Build Coastguard Worker             let mut address = self.preferred_address;
1631*bb4ee6a4SAndroid Build Coastguard Worker             while address.func < 8 {
1632*bb4ee6a4SAndroid Build Coastguard Worker                 if resources.reserve_pci(
1633*bb4ee6a4SAndroid Build Coastguard Worker                     Alloc::PciBar {
1634*bb4ee6a4SAndroid Build Coastguard Worker                         bus: address.bus,
1635*bb4ee6a4SAndroid Build Coastguard Worker                         dev: address.dev,
1636*bb4ee6a4SAndroid Build Coastguard Worker                         func: address.func,
1637*bb4ee6a4SAndroid Build Coastguard Worker                         bar: 0,
1638*bb4ee6a4SAndroid Build Coastguard Worker                     },
1639*bb4ee6a4SAndroid Build Coastguard Worker                     self.debug_label(),
1640*bb4ee6a4SAndroid Build Coastguard Worker                 ) {
1641*bb4ee6a4SAndroid Build Coastguard Worker                     self.pci_address = Some(address);
1642*bb4ee6a4SAndroid Build Coastguard Worker                     break;
1643*bb4ee6a4SAndroid Build Coastguard Worker                 } else if self.hotplug_bus_number.is_none() {
1644*bb4ee6a4SAndroid Build Coastguard Worker                     break;
1645*bb4ee6a4SAndroid Build Coastguard Worker                 } else {
1646*bb4ee6a4SAndroid Build Coastguard Worker                     address.func += 1;
1647*bb4ee6a4SAndroid Build Coastguard Worker                 }
1648*bb4ee6a4SAndroid Build Coastguard Worker             }
1649*bb4ee6a4SAndroid Build Coastguard Worker         }
1650*bb4ee6a4SAndroid Build Coastguard Worker         self.pci_address.ok_or(PciDeviceError::PciAllocationFailed)
1651*bb4ee6a4SAndroid Build Coastguard Worker     }
1652*bb4ee6a4SAndroid Build Coastguard Worker 
keep_rds(&self) -> Vec<RawDescriptor>1653*bb4ee6a4SAndroid Build Coastguard Worker     fn keep_rds(&self) -> Vec<RawDescriptor> {
1654*bb4ee6a4SAndroid Build Coastguard Worker         let mut rds = self.device.keep_rds();
1655*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(ref interrupt_evt) = self.interrupt_evt {
1656*bb4ee6a4SAndroid Build Coastguard Worker             rds.extend(interrupt_evt.as_raw_descriptors());
1657*bb4ee6a4SAndroid Build Coastguard Worker         }
1658*bb4ee6a4SAndroid Build Coastguard Worker         rds.push(self.vm_memory_client.as_raw_descriptor());
1659*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(vm_socket_vm) = &self.vm_socket_vm {
1660*bb4ee6a4SAndroid Build Coastguard Worker             rds.push(vm_socket_vm.as_raw_descriptor());
1661*bb4ee6a4SAndroid Build Coastguard Worker         }
1662*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(msi_cap) = &self.msi_cap {
1663*bb4ee6a4SAndroid Build Coastguard Worker             rds.push(msi_cap.config.get_msi_socket());
1664*bb4ee6a4SAndroid Build Coastguard Worker         }
1665*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(msix_cap) = &self.msix_cap {
1666*bb4ee6a4SAndroid Build Coastguard Worker             rds.push(msix_cap.lock().config.as_raw_descriptor());
1667*bb4ee6a4SAndroid Build Coastguard Worker         }
1668*bb4ee6a4SAndroid Build Coastguard Worker         rds
1669*bb4ee6a4SAndroid Build Coastguard Worker     }
1670*bb4ee6a4SAndroid Build Coastguard Worker 
preferred_irq(&self) -> PreferredIrq1671*bb4ee6a4SAndroid Build Coastguard Worker     fn preferred_irq(&self) -> PreferredIrq {
1672*bb4ee6a4SAndroid Build Coastguard Worker         // Is INTx configured?
1673*bb4ee6a4SAndroid Build Coastguard Worker         let pin = match self.config.read_config::<u8>(PCI_INTERRUPT_PIN) {
1674*bb4ee6a4SAndroid Build Coastguard Worker             1 => PciInterruptPin::IntA,
1675*bb4ee6a4SAndroid Build Coastguard Worker             2 => PciInterruptPin::IntB,
1676*bb4ee6a4SAndroid Build Coastguard Worker             3 => PciInterruptPin::IntC,
1677*bb4ee6a4SAndroid Build Coastguard Worker             4 => PciInterruptPin::IntD,
1678*bb4ee6a4SAndroid Build Coastguard Worker             _ => return PreferredIrq::None,
1679*bb4ee6a4SAndroid Build Coastguard Worker         };
1680*bb4ee6a4SAndroid Build Coastguard Worker 
1681*bb4ee6a4SAndroid Build Coastguard Worker         // TODO: replace sysfs/irq value parsing with vfio interface
1682*bb4ee6a4SAndroid Build Coastguard Worker         //       reporting host allocated interrupt number and type.
1683*bb4ee6a4SAndroid Build Coastguard Worker         let path = self.sysfs_path.join("irq");
1684*bb4ee6a4SAndroid Build Coastguard Worker         let gsi = fs::read_to_string(path)
1685*bb4ee6a4SAndroid Build Coastguard Worker             .map(|v| v.trim().parse::<u32>().unwrap_or(0))
1686*bb4ee6a4SAndroid Build Coastguard Worker             .unwrap_or(0);
1687*bb4ee6a4SAndroid Build Coastguard Worker 
1688*bb4ee6a4SAndroid Build Coastguard Worker         PreferredIrq::Fixed { pin, gsi }
1689*bb4ee6a4SAndroid Build Coastguard Worker     }
1690*bb4ee6a4SAndroid Build Coastguard Worker 
assign_irq(&mut self, irq_evt: IrqLevelEvent, pin: PciInterruptPin, irq_num: u32)1691*bb4ee6a4SAndroid Build Coastguard Worker     fn assign_irq(&mut self, irq_evt: IrqLevelEvent, pin: PciInterruptPin, irq_num: u32) {
1692*bb4ee6a4SAndroid Build Coastguard Worker         // Keep event/resample event references.
1693*bb4ee6a4SAndroid Build Coastguard Worker         self.interrupt_evt = Some(irq_evt);
1694*bb4ee6a4SAndroid Build Coastguard Worker 
1695*bb4ee6a4SAndroid Build Coastguard Worker         // enable INTX
1696*bb4ee6a4SAndroid Build Coastguard Worker         self.enable_intx();
1697*bb4ee6a4SAndroid Build Coastguard Worker 
1698*bb4ee6a4SAndroid Build Coastguard Worker         self.config
1699*bb4ee6a4SAndroid Build Coastguard Worker             .write_config(pin.to_mask() as u8, PCI_INTERRUPT_PIN);
1700*bb4ee6a4SAndroid Build Coastguard Worker         self.config.write_config(irq_num as u8, PCI_INTERRUPT_NUM);
1701*bb4ee6a4SAndroid Build Coastguard Worker     }
1702*bb4ee6a4SAndroid Build Coastguard Worker 
allocate_io_bars( &mut self, resources: &mut SystemAllocator, ) -> Result<Vec<BarRange>, PciDeviceError>1703*bb4ee6a4SAndroid Build Coastguard Worker     fn allocate_io_bars(
1704*bb4ee6a4SAndroid Build Coastguard Worker         &mut self,
1705*bb4ee6a4SAndroid Build Coastguard Worker         resources: &mut SystemAllocator,
1706*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Result<Vec<BarRange>, PciDeviceError> {
1707*bb4ee6a4SAndroid Build Coastguard Worker         let address = self
1708*bb4ee6a4SAndroid Build Coastguard Worker             .pci_address
1709*bb4ee6a4SAndroid Build Coastguard Worker             .expect("allocate_address must be called prior to allocate_device_bars");
1710*bb4ee6a4SAndroid Build Coastguard Worker 
1711*bb4ee6a4SAndroid Build Coastguard Worker         let mut mem_bars = self.collect_bars();
1712*bb4ee6a4SAndroid Build Coastguard Worker 
1713*bb4ee6a4SAndroid Build Coastguard Worker         let ranges = if address.bus == 0 {
1714*bb4ee6a4SAndroid Build Coastguard Worker             self.allocate_root_barmem(&mem_bars, resources)?
1715*bb4ee6a4SAndroid Build Coastguard Worker         } else {
1716*bb4ee6a4SAndroid Build Coastguard Worker             self.allocate_nonroot_barmem(&mut mem_bars, resources)?
1717*bb4ee6a4SAndroid Build Coastguard Worker         };
1718*bb4ee6a4SAndroid Build Coastguard Worker 
1719*bb4ee6a4SAndroid Build Coastguard Worker         // Quirk, enable igd memory for guest vga arbitrate, otherwise kernel vga arbitrate
1720*bb4ee6a4SAndroid Build Coastguard Worker         // driver doesn't claim this vga device, then xorg couldn't boot up.
1721*bb4ee6a4SAndroid Build Coastguard Worker         if self.is_intel_gfx() {
1722*bb4ee6a4SAndroid Build Coastguard Worker             let mut cmd = self.config.read_config::<u8>(PCI_COMMAND);
1723*bb4ee6a4SAndroid Build Coastguard Worker             cmd |= PCI_COMMAND_MEMORY;
1724*bb4ee6a4SAndroid Build Coastguard Worker             self.config.write_config(cmd, PCI_COMMAND);
1725*bb4ee6a4SAndroid Build Coastguard Worker         }
1726*bb4ee6a4SAndroid Build Coastguard Worker         Ok(ranges)
1727*bb4ee6a4SAndroid Build Coastguard Worker     }
1728*bb4ee6a4SAndroid Build Coastguard Worker 
allocate_device_bars( &mut self, resources: &mut SystemAllocator, ) -> Result<Vec<BarRange>, PciDeviceError>1729*bb4ee6a4SAndroid Build Coastguard Worker     fn allocate_device_bars(
1730*bb4ee6a4SAndroid Build Coastguard Worker         &mut self,
1731*bb4ee6a4SAndroid Build Coastguard Worker         resources: &mut SystemAllocator,
1732*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Result<Vec<BarRange>, PciDeviceError> {
1733*bb4ee6a4SAndroid Build Coastguard Worker         let mut ranges: Vec<BarRange> = Vec::new();
1734*bb4ee6a4SAndroid Build Coastguard Worker 
1735*bb4ee6a4SAndroid Build Coastguard Worker         if !self.is_intel_gfx() {
1736*bb4ee6a4SAndroid Build Coastguard Worker             return Ok(ranges);
1737*bb4ee6a4SAndroid Build Coastguard Worker         }
1738*bb4ee6a4SAndroid Build Coastguard Worker 
1739*bb4ee6a4SAndroid Build Coastguard Worker         // Make intel gfx's opregion as mmio bar, and allocate a gpa for it
1740*bb4ee6a4SAndroid Build Coastguard Worker         // then write this gpa into pci cfg register
1741*bb4ee6a4SAndroid Build Coastguard Worker         if let Some((index, size)) = self.device.get_cap_type_info(
1742*bb4ee6a4SAndroid Build Coastguard Worker             VFIO_REGION_TYPE_PCI_VENDOR_TYPE | (PCI_VENDOR_ID_INTEL as u32),
1743*bb4ee6a4SAndroid Build Coastguard Worker             VFIO_REGION_SUBTYPE_INTEL_IGD_OPREGION,
1744*bb4ee6a4SAndroid Build Coastguard Worker         ) {
1745*bb4ee6a4SAndroid Build Coastguard Worker             let address = self
1746*bb4ee6a4SAndroid Build Coastguard Worker                 .pci_address
1747*bb4ee6a4SAndroid Build Coastguard Worker                 .expect("allocate_address must be called prior to allocate_device_bars");
1748*bb4ee6a4SAndroid Build Coastguard Worker             let bar_addr = resources
1749*bb4ee6a4SAndroid Build Coastguard Worker                 .allocate_mmio(
1750*bb4ee6a4SAndroid Build Coastguard Worker                     size,
1751*bb4ee6a4SAndroid Build Coastguard Worker                     Alloc::PciBar {
1752*bb4ee6a4SAndroid Build Coastguard Worker                         bus: address.bus,
1753*bb4ee6a4SAndroid Build Coastguard Worker                         dev: address.dev,
1754*bb4ee6a4SAndroid Build Coastguard Worker                         func: address.func,
1755*bb4ee6a4SAndroid Build Coastguard Worker                         bar: (index * 4) as u8,
1756*bb4ee6a4SAndroid Build Coastguard Worker                     },
1757*bb4ee6a4SAndroid Build Coastguard Worker                     "vfio_bar".to_string(),
1758*bb4ee6a4SAndroid Build Coastguard Worker                     AllocOptions::new().max_address(u32::MAX.into()),
1759*bb4ee6a4SAndroid Build Coastguard Worker                 )
1760*bb4ee6a4SAndroid Build Coastguard Worker                 .map_err(|e| PciDeviceError::IoAllocationFailed(size, e))?;
1761*bb4ee6a4SAndroid Build Coastguard Worker             ranges.push(BarRange {
1762*bb4ee6a4SAndroid Build Coastguard Worker                 addr: bar_addr,
1763*bb4ee6a4SAndroid Build Coastguard Worker                 size,
1764*bb4ee6a4SAndroid Build Coastguard Worker                 prefetchable: false,
1765*bb4ee6a4SAndroid Build Coastguard Worker             });
1766*bb4ee6a4SAndroid Build Coastguard Worker             self.device_data = Some(DeviceData::IntelGfxData {
1767*bb4ee6a4SAndroid Build Coastguard Worker                 opregion_index: index,
1768*bb4ee6a4SAndroid Build Coastguard Worker             });
1769*bb4ee6a4SAndroid Build Coastguard Worker 
1770*bb4ee6a4SAndroid Build Coastguard Worker             self.mmio_regions.push(
1771*bb4ee6a4SAndroid Build Coastguard Worker                 PciBarConfiguration::new(
1772*bb4ee6a4SAndroid Build Coastguard Worker                     index as usize,
1773*bb4ee6a4SAndroid Build Coastguard Worker                     size,
1774*bb4ee6a4SAndroid Build Coastguard Worker                     PciBarRegionType::Memory32BitRegion,
1775*bb4ee6a4SAndroid Build Coastguard Worker                     PciBarPrefetchable::NotPrefetchable,
1776*bb4ee6a4SAndroid Build Coastguard Worker                 )
1777*bb4ee6a4SAndroid Build Coastguard Worker                 .set_address(bar_addr),
1778*bb4ee6a4SAndroid Build Coastguard Worker             );
1779*bb4ee6a4SAndroid Build Coastguard Worker             self.config.write_config(bar_addr as u32, 0xFC);
1780*bb4ee6a4SAndroid Build Coastguard Worker         }
1781*bb4ee6a4SAndroid Build Coastguard Worker 
1782*bb4ee6a4SAndroid Build Coastguard Worker         Ok(ranges)
1783*bb4ee6a4SAndroid Build Coastguard Worker     }
1784*bb4ee6a4SAndroid Build Coastguard Worker 
get_bar_configuration(&self, bar_num: usize) -> Option<PciBarConfiguration>1785*bb4ee6a4SAndroid Build Coastguard Worker     fn get_bar_configuration(&self, bar_num: usize) -> Option<PciBarConfiguration> {
1786*bb4ee6a4SAndroid Build Coastguard Worker         for region in self.mmio_regions.iter().chain(self.io_regions.iter()) {
1787*bb4ee6a4SAndroid Build Coastguard Worker             if region.bar_index() == bar_num {
1788*bb4ee6a4SAndroid Build Coastguard Worker                 let command: u8 = self.config.read_config(PCI_COMMAND);
1789*bb4ee6a4SAndroid Build Coastguard Worker                 if (region.is_memory() && (command & PCI_COMMAND_MEMORY == 0)) || region.is_io() {
1790*bb4ee6a4SAndroid Build Coastguard Worker                     return None;
1791*bb4ee6a4SAndroid Build Coastguard Worker                 } else {
1792*bb4ee6a4SAndroid Build Coastguard Worker                     return Some(*region);
1793*bb4ee6a4SAndroid Build Coastguard Worker                 }
1794*bb4ee6a4SAndroid Build Coastguard Worker             }
1795*bb4ee6a4SAndroid Build Coastguard Worker         }
1796*bb4ee6a4SAndroid Build Coastguard Worker 
1797*bb4ee6a4SAndroid Build Coastguard Worker         None
1798*bb4ee6a4SAndroid Build Coastguard Worker     }
1799*bb4ee6a4SAndroid Build Coastguard Worker 
register_device_capabilities(&mut self) -> Result<(), PciDeviceError>1800*bb4ee6a4SAndroid Build Coastguard Worker     fn register_device_capabilities(&mut self) -> Result<(), PciDeviceError> {
1801*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
1802*bb4ee6a4SAndroid Build Coastguard Worker     }
1803*bb4ee6a4SAndroid Build Coastguard Worker 
read_config_register(&self, reg_idx: usize) -> u321804*bb4ee6a4SAndroid Build Coastguard Worker     fn read_config_register(&self, reg_idx: usize) -> u32 {
1805*bb4ee6a4SAndroid Build Coastguard Worker         let reg: u32 = (reg_idx * 4) as u32;
1806*bb4ee6a4SAndroid Build Coastguard Worker         let mut config: u32 = self.config.read_config(reg);
1807*bb4ee6a4SAndroid Build Coastguard Worker 
1808*bb4ee6a4SAndroid Build Coastguard Worker         // See VfioPciDevice::new for details how extended caps are managed
1809*bb4ee6a4SAndroid Build Coastguard Worker         if reg >= PCI_CONFIG_SPACE_SIZE {
1810*bb4ee6a4SAndroid Build Coastguard Worker             let ext_cap = self.get_ext_cap_by_reg(reg);
1811*bb4ee6a4SAndroid Build Coastguard Worker             if let Some(ext_cap) = ext_cap {
1812*bb4ee6a4SAndroid Build Coastguard Worker                 if ext_cap.offset == reg {
1813*bb4ee6a4SAndroid Build Coastguard Worker                     config = (config & !(0xffc << 20)) | (((ext_cap.next & 0xffc) as u32) << 20);
1814*bb4ee6a4SAndroid Build Coastguard Worker                 }
1815*bb4ee6a4SAndroid Build Coastguard Worker 
1816*bb4ee6a4SAndroid Build Coastguard Worker                 if ext_cap.is_skipped {
1817*bb4ee6a4SAndroid Build Coastguard Worker                     if reg == PCI_CONFIG_SPACE_SIZE {
1818*bb4ee6a4SAndroid Build Coastguard Worker                         config = (config & (0xffc << 20)) | (PCI_EXT_CAP_ID_CAC as u32);
1819*bb4ee6a4SAndroid Build Coastguard Worker                     } else {
1820*bb4ee6a4SAndroid Build Coastguard Worker                         config = 0;
1821*bb4ee6a4SAndroid Build Coastguard Worker                     }
1822*bb4ee6a4SAndroid Build Coastguard Worker                 }
1823*bb4ee6a4SAndroid Build Coastguard Worker             }
1824*bb4ee6a4SAndroid Build Coastguard Worker         }
1825*bb4ee6a4SAndroid Build Coastguard Worker 
1826*bb4ee6a4SAndroid Build Coastguard Worker         // Ignore IO bar
1827*bb4ee6a4SAndroid Build Coastguard Worker         if (0x10..=0x24).contains(&reg) {
1828*bb4ee6a4SAndroid Build Coastguard Worker             let bar_idx = (reg as usize - 0x10) / 4;
1829*bb4ee6a4SAndroid Build Coastguard Worker             if let Some(bar) = self.get_bar_configuration(bar_idx) {
1830*bb4ee6a4SAndroid Build Coastguard Worker                 if bar.is_io() {
1831*bb4ee6a4SAndroid Build Coastguard Worker                     config = 0;
1832*bb4ee6a4SAndroid Build Coastguard Worker                 }
1833*bb4ee6a4SAndroid Build Coastguard Worker             }
1834*bb4ee6a4SAndroid Build Coastguard Worker         } else if let Some(msix_cap) = &self.msix_cap {
1835*bb4ee6a4SAndroid Build Coastguard Worker             let msix_cap = msix_cap.lock();
1836*bb4ee6a4SAndroid Build Coastguard Worker             if msix_cap.is_msix_control_reg(reg, 4) {
1837*bb4ee6a4SAndroid Build Coastguard Worker                 msix_cap.read_msix_control(&mut config);
1838*bb4ee6a4SAndroid Build Coastguard Worker             }
1839*bb4ee6a4SAndroid Build Coastguard Worker         } else if let Some(pm_cap) = &self.pm_cap {
1840*bb4ee6a4SAndroid Build Coastguard Worker             let pm_cap = pm_cap.lock();
1841*bb4ee6a4SAndroid Build Coastguard Worker             if pm_cap.is_pm_reg(reg) {
1842*bb4ee6a4SAndroid Build Coastguard Worker                 config = pm_cap.read(reg);
1843*bb4ee6a4SAndroid Build Coastguard Worker             }
1844*bb4ee6a4SAndroid Build Coastguard Worker         }
1845*bb4ee6a4SAndroid Build Coastguard Worker 
1846*bb4ee6a4SAndroid Build Coastguard Worker         // Quirk for intel graphic, set stolen memory size to 0 in pci_cfg[0x51]
1847*bb4ee6a4SAndroid Build Coastguard Worker         if self.is_intel_gfx() && reg == 0x50 {
1848*bb4ee6a4SAndroid Build Coastguard Worker             config &= 0xffff00ff;
1849*bb4ee6a4SAndroid Build Coastguard Worker         }
1850*bb4ee6a4SAndroid Build Coastguard Worker 
1851*bb4ee6a4SAndroid Build Coastguard Worker         config
1852*bb4ee6a4SAndroid Build Coastguard Worker     }
1853*bb4ee6a4SAndroid Build Coastguard Worker 
write_config_register(&mut self, reg_idx: usize, offset: u64, data: &[u8])1854*bb4ee6a4SAndroid Build Coastguard Worker     fn write_config_register(&mut self, reg_idx: usize, offset: u64, data: &[u8]) {
1855*bb4ee6a4SAndroid Build Coastguard Worker         // When guest write config register at the first time, start worker thread
1856*bb4ee6a4SAndroid Build Coastguard Worker         if self.worker_thread.is_none() && self.vm_socket_vm.is_some() {
1857*bb4ee6a4SAndroid Build Coastguard Worker             self.start_work_thread();
1858*bb4ee6a4SAndroid Build Coastguard Worker         };
1859*bb4ee6a4SAndroid Build Coastguard Worker 
1860*bb4ee6a4SAndroid Build Coastguard Worker         let start = (reg_idx * 4) as u64 + offset;
1861*bb4ee6a4SAndroid Build Coastguard Worker 
1862*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(pm_cap) = self.pm_cap.as_mut() {
1863*bb4ee6a4SAndroid Build Coastguard Worker             let mut pm_cap = pm_cap.lock();
1864*bb4ee6a4SAndroid Build Coastguard Worker             if pm_cap.is_pm_reg(start as u32) {
1865*bb4ee6a4SAndroid Build Coastguard Worker                 pm_cap.write(start, data);
1866*bb4ee6a4SAndroid Build Coastguard Worker             }
1867*bb4ee6a4SAndroid Build Coastguard Worker         }
1868*bb4ee6a4SAndroid Build Coastguard Worker 
1869*bb4ee6a4SAndroid Build Coastguard Worker         let mut msi_change: Option<VfioMsiChange> = None;
1870*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(msi_cap) = self.msi_cap.as_mut() {
1871*bb4ee6a4SAndroid Build Coastguard Worker             if msi_cap.is_msi_reg(start, data.len()) {
1872*bb4ee6a4SAndroid Build Coastguard Worker                 msi_change = msi_cap.write_msi_reg(start, data);
1873*bb4ee6a4SAndroid Build Coastguard Worker             }
1874*bb4ee6a4SAndroid Build Coastguard Worker         }
1875*bb4ee6a4SAndroid Build Coastguard Worker 
1876*bb4ee6a4SAndroid Build Coastguard Worker         match msi_change {
1877*bb4ee6a4SAndroid Build Coastguard Worker             Some(VfioMsiChange::Enable) => self.enable_msi(),
1878*bb4ee6a4SAndroid Build Coastguard Worker             Some(VfioMsiChange::Disable) => self.disable_msi(),
1879*bb4ee6a4SAndroid Build Coastguard Worker             _ => (),
1880*bb4ee6a4SAndroid Build Coastguard Worker         }
1881*bb4ee6a4SAndroid Build Coastguard Worker 
1882*bb4ee6a4SAndroid Build Coastguard Worker         msi_change = None;
1883*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(msix_cap) = &self.msix_cap {
1884*bb4ee6a4SAndroid Build Coastguard Worker             let mut msix_cap = msix_cap.lock();
1885*bb4ee6a4SAndroid Build Coastguard Worker             if msix_cap.is_msix_control_reg(start as u32, data.len() as u32) {
1886*bb4ee6a4SAndroid Build Coastguard Worker                 msi_change = msix_cap.write_msix_control(data);
1887*bb4ee6a4SAndroid Build Coastguard Worker             }
1888*bb4ee6a4SAndroid Build Coastguard Worker         }
1889*bb4ee6a4SAndroid Build Coastguard Worker 
1890*bb4ee6a4SAndroid Build Coastguard Worker         match msi_change {
1891*bb4ee6a4SAndroid Build Coastguard Worker             Some(VfioMsiChange::Enable) => self.enable_msix(),
1892*bb4ee6a4SAndroid Build Coastguard Worker             Some(VfioMsiChange::Disable) => self.disable_msix(),
1893*bb4ee6a4SAndroid Build Coastguard Worker             Some(VfioMsiChange::FunctionChanged) => {
1894*bb4ee6a4SAndroid Build Coastguard Worker                 if let Err(e) = self.msix_vectors_update() {
1895*bb4ee6a4SAndroid Build Coastguard Worker                     error!("update msix vectors failed: {}", e);
1896*bb4ee6a4SAndroid Build Coastguard Worker                 }
1897*bb4ee6a4SAndroid Build Coastguard Worker             }
1898*bb4ee6a4SAndroid Build Coastguard Worker             _ => (),
1899*bb4ee6a4SAndroid Build Coastguard Worker         }
1900*bb4ee6a4SAndroid Build Coastguard Worker 
1901*bb4ee6a4SAndroid Build Coastguard Worker         if !self.is_skipped_reg(start as u32) {
1902*bb4ee6a4SAndroid Build Coastguard Worker             self.device
1903*bb4ee6a4SAndroid Build Coastguard Worker                 .region_write(VFIO_PCI_CONFIG_REGION_INDEX as usize, data, start);
1904*bb4ee6a4SAndroid Build Coastguard Worker         }
1905*bb4ee6a4SAndroid Build Coastguard Worker 
1906*bb4ee6a4SAndroid Build Coastguard Worker         // if guest enable memory access, then enable bar mappable once
1907*bb4ee6a4SAndroid Build Coastguard Worker         if start == PCI_COMMAND as u64
1908*bb4ee6a4SAndroid Build Coastguard Worker             && data.len() == 2
1909*bb4ee6a4SAndroid Build Coastguard Worker             && data[0] & PCI_COMMAND_MEMORY == PCI_COMMAND_MEMORY
1910*bb4ee6a4SAndroid Build Coastguard Worker         {
1911*bb4ee6a4SAndroid Build Coastguard Worker             self.commit_bars_mmap();
1912*bb4ee6a4SAndroid Build Coastguard Worker         } else if (0x10..=0x24).contains(&start) && data.len() == 4 {
1913*bb4ee6a4SAndroid Build Coastguard Worker             let bar_idx = (start as u32 - 0x10) / 4;
1914*bb4ee6a4SAndroid Build Coastguard Worker             let value: [u8; 4] = [data[0], data[1], data[2], data[3]];
1915*bb4ee6a4SAndroid Build Coastguard Worker             let val = u32::from_le_bytes(value);
1916*bb4ee6a4SAndroid Build Coastguard Worker             let mut modify = false;
1917*bb4ee6a4SAndroid Build Coastguard Worker             for region in self.mmio_regions.iter_mut() {
1918*bb4ee6a4SAndroid Build Coastguard Worker                 if region.bar_index() == bar_idx as usize {
1919*bb4ee6a4SAndroid Build Coastguard Worker                     let old_addr = region.address();
1920*bb4ee6a4SAndroid Build Coastguard Worker                     let new_addr = val & 0xFFFFFFF0;
1921*bb4ee6a4SAndroid Build Coastguard Worker                     if !region.is_64bit_memory() && (old_addr as u32) != new_addr {
1922*bb4ee6a4SAndroid Build Coastguard Worker                         // Change 32bit bar address
1923*bb4ee6a4SAndroid Build Coastguard Worker                         *region = region.set_address(u64::from(new_addr));
1924*bb4ee6a4SAndroid Build Coastguard Worker                         modify = true;
1925*bb4ee6a4SAndroid Build Coastguard Worker                     } else if region.is_64bit_memory() && (old_addr as u32) != new_addr {
1926*bb4ee6a4SAndroid Build Coastguard Worker                         // Change 64bit bar low address
1927*bb4ee6a4SAndroid Build Coastguard Worker                         *region =
1928*bb4ee6a4SAndroid Build Coastguard Worker                             region.set_address(u64::from(new_addr) | ((old_addr >> 32) << 32));
1929*bb4ee6a4SAndroid Build Coastguard Worker                         modify = true;
1930*bb4ee6a4SAndroid Build Coastguard Worker                     }
1931*bb4ee6a4SAndroid Build Coastguard Worker                     break;
1932*bb4ee6a4SAndroid Build Coastguard Worker                 } else if region.is_64bit_memory()
1933*bb4ee6a4SAndroid Build Coastguard Worker                     && ((bar_idx % 2) == 1)
1934*bb4ee6a4SAndroid Build Coastguard Worker                     && (region.bar_index() + 1 == bar_idx as usize)
1935*bb4ee6a4SAndroid Build Coastguard Worker                 {
1936*bb4ee6a4SAndroid Build Coastguard Worker                     // Change 64bit bar high address
1937*bb4ee6a4SAndroid Build Coastguard Worker                     let old_addr = region.address();
1938*bb4ee6a4SAndroid Build Coastguard Worker                     if val != (old_addr >> 32) as u32 {
1939*bb4ee6a4SAndroid Build Coastguard Worker                         let mut new_addr = (u64::from(val)) << 32;
1940*bb4ee6a4SAndroid Build Coastguard Worker                         new_addr |= old_addr & 0xFFFFFFFF;
1941*bb4ee6a4SAndroid Build Coastguard Worker                         *region = region.set_address(new_addr);
1942*bb4ee6a4SAndroid Build Coastguard Worker                         modify = true;
1943*bb4ee6a4SAndroid Build Coastguard Worker                     }
1944*bb4ee6a4SAndroid Build Coastguard Worker                     break;
1945*bb4ee6a4SAndroid Build Coastguard Worker                 }
1946*bb4ee6a4SAndroid Build Coastguard Worker             }
1947*bb4ee6a4SAndroid Build Coastguard Worker             if modify {
1948*bb4ee6a4SAndroid Build Coastguard Worker                 // if bar is changed under memory enabled, mmap the
1949*bb4ee6a4SAndroid Build Coastguard Worker                 // new bar immediately.
1950*bb4ee6a4SAndroid Build Coastguard Worker                 let cmd = self.config.read_config::<u8>(PCI_COMMAND);
1951*bb4ee6a4SAndroid Build Coastguard Worker                 if cmd & PCI_COMMAND_MEMORY == PCI_COMMAND_MEMORY {
1952*bb4ee6a4SAndroid Build Coastguard Worker                     self.commit_bars_mmap();
1953*bb4ee6a4SAndroid Build Coastguard Worker                 }
1954*bb4ee6a4SAndroid Build Coastguard Worker             }
1955*bb4ee6a4SAndroid Build Coastguard Worker         }
1956*bb4ee6a4SAndroid Build Coastguard Worker     }
1957*bb4ee6a4SAndroid Build Coastguard Worker 
read_virtual_config_register(&self, reg_idx: usize) -> u321958*bb4ee6a4SAndroid Build Coastguard Worker     fn read_virtual_config_register(&self, reg_idx: usize) -> u32 {
1959*bb4ee6a4SAndroid Build Coastguard Worker         if reg_idx == PCI_VCFG_NOTY {
1960*bb4ee6a4SAndroid Build Coastguard Worker             let mut q = self.acpi_notifier_val.lock();
1961*bb4ee6a4SAndroid Build Coastguard Worker             let mut val = 0;
1962*bb4ee6a4SAndroid Build Coastguard Worker             if !q.is_empty() {
1963*bb4ee6a4SAndroid Build Coastguard Worker                 val = q.remove(0);
1964*bb4ee6a4SAndroid Build Coastguard Worker             }
1965*bb4ee6a4SAndroid Build Coastguard Worker             drop(q);
1966*bb4ee6a4SAndroid Build Coastguard Worker             return val;
1967*bb4ee6a4SAndroid Build Coastguard Worker         }
1968*bb4ee6a4SAndroid Build Coastguard Worker 
1969*bb4ee6a4SAndroid Build Coastguard Worker         warn!(
1970*bb4ee6a4SAndroid Build Coastguard Worker             "{} read unsupported vcfg register {}",
1971*bb4ee6a4SAndroid Build Coastguard Worker             self.debug_label(),
1972*bb4ee6a4SAndroid Build Coastguard Worker             reg_idx
1973*bb4ee6a4SAndroid Build Coastguard Worker         );
1974*bb4ee6a4SAndroid Build Coastguard Worker         0xFFFF_FFFF
1975*bb4ee6a4SAndroid Build Coastguard Worker     }
1976*bb4ee6a4SAndroid Build Coastguard Worker 
write_virtual_config_register(&mut self, reg_idx: usize, value: u32)1977*bb4ee6a4SAndroid Build Coastguard Worker     fn write_virtual_config_register(&mut self, reg_idx: usize, value: u32) {
1978*bb4ee6a4SAndroid Build Coastguard Worker         match reg_idx {
1979*bb4ee6a4SAndroid Build Coastguard Worker             PCI_VCFG_PM => {
1980*bb4ee6a4SAndroid Build Coastguard Worker                 match value {
1981*bb4ee6a4SAndroid Build Coastguard Worker                     0 => {
1982*bb4ee6a4SAndroid Build Coastguard Worker                         if let Some(pm_evt) =
1983*bb4ee6a4SAndroid Build Coastguard Worker                             self.pm_evt.as_ref().map(|evt| evt.try_clone().unwrap())
1984*bb4ee6a4SAndroid Build Coastguard Worker                         {
1985*bb4ee6a4SAndroid Build Coastguard Worker                             *self.is_in_low_power.lock() = true;
1986*bb4ee6a4SAndroid Build Coastguard Worker                             let _ = self.device.pm_low_power_enter_with_wakeup(pm_evt);
1987*bb4ee6a4SAndroid Build Coastguard Worker                         } else {
1988*bb4ee6a4SAndroid Build Coastguard Worker                             let _ = self.device.pm_low_power_enter();
1989*bb4ee6a4SAndroid Build Coastguard Worker                         }
1990*bb4ee6a4SAndroid Build Coastguard Worker                     }
1991*bb4ee6a4SAndroid Build Coastguard Worker                     _ => {
1992*bb4ee6a4SAndroid Build Coastguard Worker                         *self.is_in_low_power.lock() = false;
1993*bb4ee6a4SAndroid Build Coastguard Worker                         let _ = self.device.pm_low_power_exit();
1994*bb4ee6a4SAndroid Build Coastguard Worker                     }
1995*bb4ee6a4SAndroid Build Coastguard Worker                 };
1996*bb4ee6a4SAndroid Build Coastguard Worker             }
1997*bb4ee6a4SAndroid Build Coastguard Worker             PCI_VCFG_DSM => {
1998*bb4ee6a4SAndroid Build Coastguard Worker                 if let Some(shm) = &self.vcfg_shm_mmap {
1999*bb4ee6a4SAndroid Build Coastguard Worker                     let mut args = [0u8; 4096];
2000*bb4ee6a4SAndroid Build Coastguard Worker                     if let Err(e) = shm.read_slice(&mut args, 0) {
2001*bb4ee6a4SAndroid Build Coastguard Worker                         error!("failed to read DSM Args: {}", e);
2002*bb4ee6a4SAndroid Build Coastguard Worker                         return;
2003*bb4ee6a4SAndroid Build Coastguard Worker                     }
2004*bb4ee6a4SAndroid Build Coastguard Worker                     let res = match self.device.acpi_dsm(&args) {
2005*bb4ee6a4SAndroid Build Coastguard Worker                         Ok(r) => r,
2006*bb4ee6a4SAndroid Build Coastguard Worker                         Err(e) => {
2007*bb4ee6a4SAndroid Build Coastguard Worker                             error!("failed to call DSM: {}", e);
2008*bb4ee6a4SAndroid Build Coastguard Worker                             return;
2009*bb4ee6a4SAndroid Build Coastguard Worker                         }
2010*bb4ee6a4SAndroid Build Coastguard Worker                     };
2011*bb4ee6a4SAndroid Build Coastguard Worker                     if let Err(e) = shm.write_slice(&res, 0) {
2012*bb4ee6a4SAndroid Build Coastguard Worker                         error!("failed to write DSM result: {}", e);
2013*bb4ee6a4SAndroid Build Coastguard Worker                         return;
2014*bb4ee6a4SAndroid Build Coastguard Worker                     }
2015*bb4ee6a4SAndroid Build Coastguard Worker                     if let Err(e) = shm.msync() {
2016*bb4ee6a4SAndroid Build Coastguard Worker                         error!("failed to msync: {}", e)
2017*bb4ee6a4SAndroid Build Coastguard Worker                     }
2018*bb4ee6a4SAndroid Build Coastguard Worker                 }
2019*bb4ee6a4SAndroid Build Coastguard Worker             }
2020*bb4ee6a4SAndroid Build Coastguard Worker             _ => warn!(
2021*bb4ee6a4SAndroid Build Coastguard Worker                 "{} write unsupported vcfg register {}",
2022*bb4ee6a4SAndroid Build Coastguard Worker                 self.debug_label(),
2023*bb4ee6a4SAndroid Build Coastguard Worker                 reg_idx
2024*bb4ee6a4SAndroid Build Coastguard Worker             ),
2025*bb4ee6a4SAndroid Build Coastguard Worker         };
2026*bb4ee6a4SAndroid Build Coastguard Worker     }
2027*bb4ee6a4SAndroid Build Coastguard Worker 
read_bar(&mut self, bar_index: PciBarIndex, offset: u64, data: &mut [u8])2028*bb4ee6a4SAndroid Build Coastguard Worker     fn read_bar(&mut self, bar_index: PciBarIndex, offset: u64, data: &mut [u8]) {
2029*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(msix_cap) = &self.msix_cap {
2030*bb4ee6a4SAndroid Build Coastguard Worker             let msix_cap = msix_cap.lock();
2031*bb4ee6a4SAndroid Build Coastguard Worker             if msix_cap.is_msix_table(bar_index, offset) {
2032*bb4ee6a4SAndroid Build Coastguard Worker                 msix_cap.read_table(offset, data);
2033*bb4ee6a4SAndroid Build Coastguard Worker                 return;
2034*bb4ee6a4SAndroid Build Coastguard Worker             } else if msix_cap.is_msix_pba(bar_index, offset) {
2035*bb4ee6a4SAndroid Build Coastguard Worker                 msix_cap.read_pba(offset, data);
2036*bb4ee6a4SAndroid Build Coastguard Worker                 return;
2037*bb4ee6a4SAndroid Build Coastguard Worker             }
2038*bb4ee6a4SAndroid Build Coastguard Worker         }
2039*bb4ee6a4SAndroid Build Coastguard Worker         self.device.region_read(bar_index, data, offset);
2040*bb4ee6a4SAndroid Build Coastguard Worker     }
2041*bb4ee6a4SAndroid Build Coastguard Worker 
write_bar(&mut self, bar_index: PciBarIndex, offset: u64, data: &[u8])2042*bb4ee6a4SAndroid Build Coastguard Worker     fn write_bar(&mut self, bar_index: PciBarIndex, offset: u64, data: &[u8]) {
2043*bb4ee6a4SAndroid Build Coastguard Worker         // Ignore igd opregion's write
2044*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(device_data) = &self.device_data {
2045*bb4ee6a4SAndroid Build Coastguard Worker             match *device_data {
2046*bb4ee6a4SAndroid Build Coastguard Worker                 DeviceData::IntelGfxData { opregion_index } => {
2047*bb4ee6a4SAndroid Build Coastguard Worker                     if opregion_index == bar_index as u32 {
2048*bb4ee6a4SAndroid Build Coastguard Worker                         return;
2049*bb4ee6a4SAndroid Build Coastguard Worker                     }
2050*bb4ee6a4SAndroid Build Coastguard Worker                 }
2051*bb4ee6a4SAndroid Build Coastguard Worker             }
2052*bb4ee6a4SAndroid Build Coastguard Worker         }
2053*bb4ee6a4SAndroid Build Coastguard Worker 
2054*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(msix_cap) = &self.msix_cap {
2055*bb4ee6a4SAndroid Build Coastguard Worker             let mut msix_cap = msix_cap.lock();
2056*bb4ee6a4SAndroid Build Coastguard Worker             if msix_cap.is_msix_table(bar_index, offset) {
2057*bb4ee6a4SAndroid Build Coastguard Worker                 let behavior = msix_cap.write_table(offset, data);
2058*bb4ee6a4SAndroid Build Coastguard Worker                 if let MsixStatus::EntryChanged(index) = behavior {
2059*bb4ee6a4SAndroid Build Coastguard Worker                     let irqfd = msix_cap.get_msix_irqfd(index);
2060*bb4ee6a4SAndroid Build Coastguard Worker                     self.msix_vector_update(index, irqfd);
2061*bb4ee6a4SAndroid Build Coastguard Worker                 }
2062*bb4ee6a4SAndroid Build Coastguard Worker                 return;
2063*bb4ee6a4SAndroid Build Coastguard Worker             } else if msix_cap.is_msix_pba(bar_index, offset) {
2064*bb4ee6a4SAndroid Build Coastguard Worker                 msix_cap.write_pba(offset, data);
2065*bb4ee6a4SAndroid Build Coastguard Worker                 return;
2066*bb4ee6a4SAndroid Build Coastguard Worker             }
2067*bb4ee6a4SAndroid Build Coastguard Worker         }
2068*bb4ee6a4SAndroid Build Coastguard Worker 
2069*bb4ee6a4SAndroid Build Coastguard Worker         self.device.region_write(bar_index, data, offset);
2070*bb4ee6a4SAndroid Build Coastguard Worker     }
2071*bb4ee6a4SAndroid Build Coastguard Worker 
destroy_device(&mut self)2072*bb4ee6a4SAndroid Build Coastguard Worker     fn destroy_device(&mut self) {
2073*bb4ee6a4SAndroid Build Coastguard Worker         self.close();
2074*bb4ee6a4SAndroid Build Coastguard Worker     }
2075*bb4ee6a4SAndroid Build Coastguard Worker 
generate_acpi_methods(&mut self) -> (Vec<u8>, Option<(u32, MemoryMapping)>)2076*bb4ee6a4SAndroid Build Coastguard Worker     fn generate_acpi_methods(&mut self) -> (Vec<u8>, Option<(u32, MemoryMapping)>) {
2077*bb4ee6a4SAndroid Build Coastguard Worker         let mut amls = Vec::new();
2078*bb4ee6a4SAndroid Build Coastguard Worker         let mut shm = None;
2079*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(pci_address) = self.pci_address {
2080*bb4ee6a4SAndroid Build Coastguard Worker             let vcfg_offset = pci_address.to_config_address(0, 13);
2081*bb4ee6a4SAndroid Build Coastguard Worker             if let Ok(vcfg_register) = DeviceVcfgRegister::new(vcfg_offset) {
2082*bb4ee6a4SAndroid Build Coastguard Worker                 vcfg_register.to_aml_bytes(&mut amls);
2083*bb4ee6a4SAndroid Build Coastguard Worker                 shm = vcfg_register
2084*bb4ee6a4SAndroid Build Coastguard Worker                     .create_shm_mmap()
2085*bb4ee6a4SAndroid Build Coastguard Worker                     .map(|shm| (vcfg_offset + SHM_OFFSET, shm));
2086*bb4ee6a4SAndroid Build Coastguard Worker                 self.vcfg_shm_mmap = vcfg_register.create_shm_mmap();
2087*bb4ee6a4SAndroid Build Coastguard Worker                 // All vfio-pci devices should have virtual _PRx method, otherwise
2088*bb4ee6a4SAndroid Build Coastguard Worker                 // host couldn't know whether device has enter into suspend state,
2089*bb4ee6a4SAndroid Build Coastguard Worker                 // host would always think it is in active state, so its parent PCIe
2090*bb4ee6a4SAndroid Build Coastguard Worker                 // switch couldn't enter into suspend state.
2091*bb4ee6a4SAndroid Build Coastguard Worker                 PowerResourceMethod {}.to_aml_bytes(&mut amls);
2092*bb4ee6a4SAndroid Build Coastguard Worker                 // TODO: WIP: Ideally, we should generate DSM only if the physical
2093*bb4ee6a4SAndroid Build Coastguard Worker                 // device has a _DSM; however, such information is not provided by
2094*bb4ee6a4SAndroid Build Coastguard Worker                 // Linux. As a temporary workaround, we chech whether there is an
2095*bb4ee6a4SAndroid Build Coastguard Worker                 // associated ACPI companion device node and skip generating guest
2096*bb4ee6a4SAndroid Build Coastguard Worker                 // _DSM if there is none.
2097*bb4ee6a4SAndroid Build Coastguard Worker                 let acpi_path = self.sysfs_path.join("firmware_node/path");
2098*bb4ee6a4SAndroid Build Coastguard Worker                 if acpi_path.exists() {
2099*bb4ee6a4SAndroid Build Coastguard Worker                     DsmMethod {}.to_aml_bytes(&mut amls);
2100*bb4ee6a4SAndroid Build Coastguard Worker                 }
2101*bb4ee6a4SAndroid Build Coastguard Worker             }
2102*bb4ee6a4SAndroid Build Coastguard Worker         }
2103*bb4ee6a4SAndroid Build Coastguard Worker 
2104*bb4ee6a4SAndroid Build Coastguard Worker         (amls, shm)
2105*bb4ee6a4SAndroid Build Coastguard Worker     }
2106*bb4ee6a4SAndroid Build Coastguard Worker 
set_gpe(&mut self, resources: &mut SystemAllocator) -> Option<u32>2107*bb4ee6a4SAndroid Build Coastguard Worker     fn set_gpe(&mut self, resources: &mut SystemAllocator) -> Option<u32> {
2108*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(gpe_nr) = resources.allocate_gpe() {
2109*bb4ee6a4SAndroid Build Coastguard Worker             base::debug!("set_gpe: gpe-nr {} addr {:?}", gpe_nr, self.pci_address);
2110*bb4ee6a4SAndroid Build Coastguard Worker             self.gpe = Some(gpe_nr);
2111*bb4ee6a4SAndroid Build Coastguard Worker         }
2112*bb4ee6a4SAndroid Build Coastguard Worker         self.gpe
2113*bb4ee6a4SAndroid Build Coastguard Worker     }
2114*bb4ee6a4SAndroid Build Coastguard Worker }
2115*bb4ee6a4SAndroid Build Coastguard Worker 
2116*bb4ee6a4SAndroid Build Coastguard Worker impl Suspendable for VfioPciDevice {
sleep(&mut self) -> anyhow::Result<()>2117*bb4ee6a4SAndroid Build Coastguard Worker     fn sleep(&mut self) -> anyhow::Result<()> {
2118*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(worker_thread) = self.worker_thread.take() {
2119*bb4ee6a4SAndroid Build Coastguard Worker             let res = worker_thread.stop();
2120*bb4ee6a4SAndroid Build Coastguard Worker             self.pci_address = Some(res.address);
2121*bb4ee6a4SAndroid Build Coastguard Worker             self.sysfs_path = res.sysfs_path;
2122*bb4ee6a4SAndroid Build Coastguard Worker             self.pm_cap = res.pm_cap;
2123*bb4ee6a4SAndroid Build Coastguard Worker             self.msix_cap = res.msix_cap;
2124*bb4ee6a4SAndroid Build Coastguard Worker             self.vm_socket_vm = Some(res.vm_socket);
2125*bb4ee6a4SAndroid Build Coastguard Worker         }
2126*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
2127*bb4ee6a4SAndroid Build Coastguard Worker     }
2128*bb4ee6a4SAndroid Build Coastguard Worker 
wake(&mut self) -> anyhow::Result<()>2129*bb4ee6a4SAndroid Build Coastguard Worker     fn wake(&mut self) -> anyhow::Result<()> {
2130*bb4ee6a4SAndroid Build Coastguard Worker         if self.activated {
2131*bb4ee6a4SAndroid Build Coastguard Worker             self.start_work_thread();
2132*bb4ee6a4SAndroid Build Coastguard Worker         }
2133*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
2134*bb4ee6a4SAndroid Build Coastguard Worker     }
2135*bb4ee6a4SAndroid Build Coastguard Worker }
2136*bb4ee6a4SAndroid Build Coastguard Worker 
2137*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(test)]
2138*bb4ee6a4SAndroid Build Coastguard Worker mod tests {
2139*bb4ee6a4SAndroid Build Coastguard Worker     use resources::AddressRange;
2140*bb4ee6a4SAndroid Build Coastguard Worker 
2141*bb4ee6a4SAndroid Build Coastguard Worker     use super::VfioResourceAllocator;
2142*bb4ee6a4SAndroid Build Coastguard Worker 
2143*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
no_overlap()2144*bb4ee6a4SAndroid Build Coastguard Worker     fn no_overlap() {
2145*bb4ee6a4SAndroid Build Coastguard Worker         // regions [32, 95]
2146*bb4ee6a4SAndroid Build Coastguard Worker         let mut memory =
2147*bb4ee6a4SAndroid Build Coastguard Worker             VfioResourceAllocator::new(AddressRange::from_start_and_end(32, 95)).unwrap();
2148*bb4ee6a4SAndroid Build Coastguard Worker         memory
2149*bb4ee6a4SAndroid Build Coastguard Worker             .allocate_at_can_overlap(AddressRange::from_start_and_end(0, 15))
2150*bb4ee6a4SAndroid Build Coastguard Worker             .unwrap();
2151*bb4ee6a4SAndroid Build Coastguard Worker         memory
2152*bb4ee6a4SAndroid Build Coastguard Worker             .allocate_at_can_overlap(AddressRange::from_start_and_end(100, 115))
2153*bb4ee6a4SAndroid Build Coastguard Worker             .unwrap();
2154*bb4ee6a4SAndroid Build Coastguard Worker 
2155*bb4ee6a4SAndroid Build Coastguard Worker         let mut iter = memory.regions.iter();
2156*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(iter.next(), Some(&AddressRange::from_start_and_end(32, 95)));
2157*bb4ee6a4SAndroid Build Coastguard Worker     }
2158*bb4ee6a4SAndroid Build Coastguard Worker 
2159*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
complete_overlap()2160*bb4ee6a4SAndroid Build Coastguard Worker     fn complete_overlap() {
2161*bb4ee6a4SAndroid Build Coastguard Worker         // regions [32, 95]
2162*bb4ee6a4SAndroid Build Coastguard Worker         let mut memory =
2163*bb4ee6a4SAndroid Build Coastguard Worker             VfioResourceAllocator::new(AddressRange::from_start_and_end(32, 95)).unwrap();
2164*bb4ee6a4SAndroid Build Coastguard Worker         // regions [32, 47], [64, 95]
2165*bb4ee6a4SAndroid Build Coastguard Worker         memory
2166*bb4ee6a4SAndroid Build Coastguard Worker             .allocate_at_can_overlap(AddressRange::from_start_and_end(48, 63))
2167*bb4ee6a4SAndroid Build Coastguard Worker             .unwrap();
2168*bb4ee6a4SAndroid Build Coastguard Worker         // regions [64, 95]
2169*bb4ee6a4SAndroid Build Coastguard Worker         memory
2170*bb4ee6a4SAndroid Build Coastguard Worker             .allocate_at_can_overlap(AddressRange::from_start_and_end(32, 47))
2171*bb4ee6a4SAndroid Build Coastguard Worker             .unwrap();
2172*bb4ee6a4SAndroid Build Coastguard Worker 
2173*bb4ee6a4SAndroid Build Coastguard Worker         let mut iter = memory.regions.iter();
2174*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(iter.next(), Some(&AddressRange::from_start_and_end(64, 95)));
2175*bb4ee6a4SAndroid Build Coastguard Worker     }
2176*bb4ee6a4SAndroid Build Coastguard Worker 
2177*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
partial_overlap_one()2178*bb4ee6a4SAndroid Build Coastguard Worker     fn partial_overlap_one() {
2179*bb4ee6a4SAndroid Build Coastguard Worker         // regions [32, 95]
2180*bb4ee6a4SAndroid Build Coastguard Worker         let mut memory =
2181*bb4ee6a4SAndroid Build Coastguard Worker             VfioResourceAllocator::new(AddressRange::from_start_and_end(32, 95)).unwrap();
2182*bb4ee6a4SAndroid Build Coastguard Worker         // regions [32, 47], [64, 95]
2183*bb4ee6a4SAndroid Build Coastguard Worker         memory
2184*bb4ee6a4SAndroid Build Coastguard Worker             .allocate_at_can_overlap(AddressRange::from_start_and_end(48, 63))
2185*bb4ee6a4SAndroid Build Coastguard Worker             .unwrap();
2186*bb4ee6a4SAndroid Build Coastguard Worker         // regions [32, 39], [64, 95]
2187*bb4ee6a4SAndroid Build Coastguard Worker         memory
2188*bb4ee6a4SAndroid Build Coastguard Worker             .allocate_at_can_overlap(AddressRange::from_start_and_end(40, 55))
2189*bb4ee6a4SAndroid Build Coastguard Worker             .unwrap();
2190*bb4ee6a4SAndroid Build Coastguard Worker 
2191*bb4ee6a4SAndroid Build Coastguard Worker         let mut iter = memory.regions.iter();
2192*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(iter.next(), Some(&AddressRange::from_start_and_end(32, 39)));
2193*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(iter.next(), Some(&AddressRange::from_start_and_end(64, 95)));
2194*bb4ee6a4SAndroid Build Coastguard Worker     }
2195*bb4ee6a4SAndroid Build Coastguard Worker 
2196*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
partial_overlap_two()2197*bb4ee6a4SAndroid Build Coastguard Worker     fn partial_overlap_two() {
2198*bb4ee6a4SAndroid Build Coastguard Worker         // regions [32, 95]
2199*bb4ee6a4SAndroid Build Coastguard Worker         let mut memory =
2200*bb4ee6a4SAndroid Build Coastguard Worker             VfioResourceAllocator::new(AddressRange::from_start_and_end(32, 95)).unwrap();
2201*bb4ee6a4SAndroid Build Coastguard Worker         // regions [32, 47], [64, 95]
2202*bb4ee6a4SAndroid Build Coastguard Worker         memory
2203*bb4ee6a4SAndroid Build Coastguard Worker             .allocate_at_can_overlap(AddressRange::from_start_and_end(48, 63))
2204*bb4ee6a4SAndroid Build Coastguard Worker             .unwrap();
2205*bb4ee6a4SAndroid Build Coastguard Worker         // regions [32, 39], [72, 95]
2206*bb4ee6a4SAndroid Build Coastguard Worker         memory
2207*bb4ee6a4SAndroid Build Coastguard Worker             .allocate_at_can_overlap(AddressRange::from_start_and_end(40, 71))
2208*bb4ee6a4SAndroid Build Coastguard Worker             .unwrap();
2209*bb4ee6a4SAndroid Build Coastguard Worker 
2210*bb4ee6a4SAndroid Build Coastguard Worker         let mut iter = memory.regions.iter();
2211*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(iter.next(), Some(&AddressRange::from_start_and_end(32, 39)));
2212*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(iter.next(), Some(&AddressRange::from_start_and_end(72, 95)));
2213*bb4ee6a4SAndroid Build Coastguard Worker     }
2214*bb4ee6a4SAndroid Build Coastguard Worker 
2215*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
partial_overlap_three()2216*bb4ee6a4SAndroid Build Coastguard Worker     fn partial_overlap_three() {
2217*bb4ee6a4SAndroid Build Coastguard Worker         // regions [32, 95]
2218*bb4ee6a4SAndroid Build Coastguard Worker         let mut memory =
2219*bb4ee6a4SAndroid Build Coastguard Worker             VfioResourceAllocator::new(AddressRange::from_start_and_end(32, 95)).unwrap();
2220*bb4ee6a4SAndroid Build Coastguard Worker         // regions [32, 39], [48, 95]
2221*bb4ee6a4SAndroid Build Coastguard Worker         memory
2222*bb4ee6a4SAndroid Build Coastguard Worker             .allocate_at_can_overlap(AddressRange::from_start_and_end(40, 47))
2223*bb4ee6a4SAndroid Build Coastguard Worker             .unwrap();
2224*bb4ee6a4SAndroid Build Coastguard Worker         // regions [32, 39], [48, 63], [72, 95]
2225*bb4ee6a4SAndroid Build Coastguard Worker         memory
2226*bb4ee6a4SAndroid Build Coastguard Worker             .allocate_at_can_overlap(AddressRange::from_start_and_end(64, 71))
2227*bb4ee6a4SAndroid Build Coastguard Worker             .unwrap();
2228*bb4ee6a4SAndroid Build Coastguard Worker         // regions [32, 35], [76, 95]
2229*bb4ee6a4SAndroid Build Coastguard Worker         memory
2230*bb4ee6a4SAndroid Build Coastguard Worker             .allocate_at_can_overlap(AddressRange::from_start_and_end(36, 75))
2231*bb4ee6a4SAndroid Build Coastguard Worker             .unwrap();
2232*bb4ee6a4SAndroid Build Coastguard Worker 
2233*bb4ee6a4SAndroid Build Coastguard Worker         let mut iter = memory.regions.iter();
2234*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(iter.next(), Some(&AddressRange::from_start_and_end(32, 35)));
2235*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(iter.next(), Some(&AddressRange::from_start_and_end(76, 95)));
2236*bb4ee6a4SAndroid Build Coastguard Worker     }
2237*bb4ee6a4SAndroid Build Coastguard Worker }
2238