xref: /aosp_15_r20/external/crosvm/devices/src/pci/pci_root.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2018 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::collections::btree_map::Entry as BTreeMapEntry;
6*bb4ee6a4SAndroid Build Coastguard Worker use std::collections::BTreeMap;
7*bb4ee6a4SAndroid Build Coastguard Worker use std::convert::TryInto;
8*bb4ee6a4SAndroid Build Coastguard Worker use std::ops::Bound::Included;
9*bb4ee6a4SAndroid Build Coastguard Worker use std::ops::DerefMut;
10*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::Arc;
11*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::Weak;
12*bb4ee6a4SAndroid Build Coastguard Worker 
13*bb4ee6a4SAndroid Build Coastguard Worker use anyhow::Context;
14*bb4ee6a4SAndroid Build Coastguard Worker use base::error;
15*bb4ee6a4SAndroid Build Coastguard Worker use base::MemoryMapping;
16*bb4ee6a4SAndroid Build Coastguard Worker use base::MemoryMappingBuilder;
17*bb4ee6a4SAndroid Build Coastguard Worker use base::Protection;
18*bb4ee6a4SAndroid Build Coastguard Worker use base::RawDescriptor;
19*bb4ee6a4SAndroid Build Coastguard Worker use base::SendTube;
20*bb4ee6a4SAndroid Build Coastguard Worker use base::SharedMemory;
21*bb4ee6a4SAndroid Build Coastguard Worker use base::VmEventType;
22*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::MemCacheType;
23*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::Vm;
24*bb4ee6a4SAndroid Build Coastguard Worker use resources::SystemAllocator;
25*bb4ee6a4SAndroid Build Coastguard Worker use serde::Deserialize;
26*bb4ee6a4SAndroid Build Coastguard Worker use serde::Serialize;
27*bb4ee6a4SAndroid Build Coastguard Worker use sync::Mutex;
28*bb4ee6a4SAndroid Build Coastguard Worker use vm_memory::GuestAddress;
29*bb4ee6a4SAndroid Build Coastguard Worker 
30*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::pci_configuration::PciBarConfiguration;
31*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::pci_configuration::PciBridgeSubclass;
32*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::pci_configuration::PciClassCode;
33*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::pci_configuration::PciConfiguration;
34*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::pci_configuration::PciHeaderType;
35*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::pci_configuration::HEADER_TYPE_MULTIFUNCTION_MASK;
36*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::pci_configuration::HEADER_TYPE_REG;
37*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::pci_configuration::HEADER_TYPE_REG_OFFSET;
38*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::pci_device::Error;
39*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::pci_device::PciBus;
40*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::pci_device::PciDevice;
41*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::PciAddress;
42*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::PciBarIndex;
43*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::PciId;
44*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::PCI_VENDOR_ID_INTEL;
45*bb4ee6a4SAndroid Build Coastguard Worker use crate::Bus;
46*bb4ee6a4SAndroid Build Coastguard Worker use crate::BusAccessInfo;
47*bb4ee6a4SAndroid Build Coastguard Worker use crate::BusDevice;
48*bb4ee6a4SAndroid Build Coastguard Worker use crate::BusType;
49*bb4ee6a4SAndroid Build Coastguard Worker use crate::DeviceId;
50*bb4ee6a4SAndroid Build Coastguard Worker use crate::Suspendable;
51*bb4ee6a4SAndroid Build Coastguard Worker 
52*bb4ee6a4SAndroid Build Coastguard Worker // A PciDevice that holds the root hub's configuration.
53*bb4ee6a4SAndroid Build Coastguard Worker struct PciRootConfiguration {
54*bb4ee6a4SAndroid Build Coastguard Worker     config: PciConfiguration,
55*bb4ee6a4SAndroid Build Coastguard Worker }
56*bb4ee6a4SAndroid Build Coastguard Worker 
57*bb4ee6a4SAndroid Build Coastguard Worker impl PciDevice for PciRootConfiguration {
debug_label(&self) -> String58*bb4ee6a4SAndroid Build Coastguard Worker     fn debug_label(&self) -> String {
59*bb4ee6a4SAndroid Build Coastguard Worker         "pci root device".to_owned()
60*bb4ee6a4SAndroid Build Coastguard Worker     }
allocate_address(&mut self, _resources: &mut SystemAllocator) -> Result<PciAddress, Error>61*bb4ee6a4SAndroid Build Coastguard Worker     fn allocate_address(&mut self, _resources: &mut SystemAllocator) -> Result<PciAddress, Error> {
62*bb4ee6a4SAndroid Build Coastguard Worker         // PCI root fixed address.
63*bb4ee6a4SAndroid Build Coastguard Worker         Ok(PciAddress {
64*bb4ee6a4SAndroid Build Coastguard Worker             bus: 0,
65*bb4ee6a4SAndroid Build Coastguard Worker             dev: 0,
66*bb4ee6a4SAndroid Build Coastguard Worker             func: 0,
67*bb4ee6a4SAndroid Build Coastguard Worker         })
68*bb4ee6a4SAndroid Build Coastguard Worker     }
keep_rds(&self) -> Vec<RawDescriptor>69*bb4ee6a4SAndroid Build Coastguard Worker     fn keep_rds(&self) -> Vec<RawDescriptor> {
70*bb4ee6a4SAndroid Build Coastguard Worker         Vec::new()
71*bb4ee6a4SAndroid Build Coastguard Worker     }
read_config_register(&self, reg_idx: usize) -> u3272*bb4ee6a4SAndroid Build Coastguard Worker     fn read_config_register(&self, reg_idx: usize) -> u32 {
73*bb4ee6a4SAndroid Build Coastguard Worker         self.config.read_reg(reg_idx)
74*bb4ee6a4SAndroid Build Coastguard Worker     }
75*bb4ee6a4SAndroid Build Coastguard Worker 
write_config_register(&mut self, reg_idx: usize, offset: u64, data: &[u8])76*bb4ee6a4SAndroid Build Coastguard Worker     fn write_config_register(&mut self, reg_idx: usize, offset: u64, data: &[u8]) {
77*bb4ee6a4SAndroid Build Coastguard Worker         self.config.write_reg(reg_idx, offset, data);
78*bb4ee6a4SAndroid Build Coastguard Worker     }
79*bb4ee6a4SAndroid Build Coastguard Worker 
setup_pci_config_mapping( &mut self, shmem: &SharedMemory, base: usize, len: usize, ) -> Result<bool, Error>80*bb4ee6a4SAndroid Build Coastguard Worker     fn setup_pci_config_mapping(
81*bb4ee6a4SAndroid Build Coastguard Worker         &mut self,
82*bb4ee6a4SAndroid Build Coastguard Worker         shmem: &SharedMemory,
83*bb4ee6a4SAndroid Build Coastguard Worker         base: usize,
84*bb4ee6a4SAndroid Build Coastguard Worker         len: usize,
85*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Result<bool, Error> {
86*bb4ee6a4SAndroid Build Coastguard Worker         self.config
87*bb4ee6a4SAndroid Build Coastguard Worker             .setup_mapping(shmem, base, len)
88*bb4ee6a4SAndroid Build Coastguard Worker             .map(|_| true)
89*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(Error::MmioSetup)
90*bb4ee6a4SAndroid Build Coastguard Worker     }
91*bb4ee6a4SAndroid Build Coastguard Worker 
read_bar(&mut self, _bar_index: PciBarIndex, _offset: u64, _data: &mut [u8])92*bb4ee6a4SAndroid Build Coastguard Worker     fn read_bar(&mut self, _bar_index: PciBarIndex, _offset: u64, _data: &mut [u8]) {}
93*bb4ee6a4SAndroid Build Coastguard Worker 
write_bar(&mut self, _bar_index: PciBarIndex, _offset: u64, _data: &[u8])94*bb4ee6a4SAndroid Build Coastguard Worker     fn write_bar(&mut self, _bar_index: PciBarIndex, _offset: u64, _data: &[u8]) {}
95*bb4ee6a4SAndroid Build Coastguard Worker 
get_bar_configuration(&self, bar_num: usize) -> Option<PciBarConfiguration>96*bb4ee6a4SAndroid Build Coastguard Worker     fn get_bar_configuration(&self, bar_num: usize) -> Option<PciBarConfiguration> {
97*bb4ee6a4SAndroid Build Coastguard Worker         self.config.get_bar_configuration(bar_num)
98*bb4ee6a4SAndroid Build Coastguard Worker     }
99*bb4ee6a4SAndroid Build Coastguard Worker }
100*bb4ee6a4SAndroid Build Coastguard Worker 
101*bb4ee6a4SAndroid Build Coastguard Worker impl Suspendable for PciRootConfiguration {
102*bb4ee6a4SAndroid Build Coastguard Worker     // no thread to sleep, no change required.
sleep(&mut self) -> anyhow::Result<()>103*bb4ee6a4SAndroid Build Coastguard Worker     fn sleep(&mut self) -> anyhow::Result<()> {
104*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
105*bb4ee6a4SAndroid Build Coastguard Worker     }
106*bb4ee6a4SAndroid Build Coastguard Worker 
wake(&mut self) -> anyhow::Result<()>107*bb4ee6a4SAndroid Build Coastguard Worker     fn wake(&mut self) -> anyhow::Result<()> {
108*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
109*bb4ee6a4SAndroid Build Coastguard Worker     }
110*bb4ee6a4SAndroid Build Coastguard Worker 
snapshot(&mut self) -> anyhow::Result<serde_json::Value>111*bb4ee6a4SAndroid Build Coastguard Worker     fn snapshot(&mut self) -> anyhow::Result<serde_json::Value> {
112*bb4ee6a4SAndroid Build Coastguard Worker         self.config
113*bb4ee6a4SAndroid Build Coastguard Worker             .snapshot()
114*bb4ee6a4SAndroid Build Coastguard Worker             .with_context(|| format!("failed to serialize {}", PciDevice::debug_label(self)))
115*bb4ee6a4SAndroid Build Coastguard Worker     }
116*bb4ee6a4SAndroid Build Coastguard Worker 
restore(&mut self, data: serde_json::Value) -> anyhow::Result<()>117*bb4ee6a4SAndroid Build Coastguard Worker     fn restore(&mut self, data: serde_json::Value) -> anyhow::Result<()> {
118*bb4ee6a4SAndroid Build Coastguard Worker         self.config
119*bb4ee6a4SAndroid Build Coastguard Worker             .restore(data)
120*bb4ee6a4SAndroid Build Coastguard Worker             .context("failed to deserialize PciRootConfiguration")
121*bb4ee6a4SAndroid Build Coastguard Worker     }
122*bb4ee6a4SAndroid Build Coastguard Worker }
123*bb4ee6a4SAndroid Build Coastguard Worker 
124*bb4ee6a4SAndroid Build Coastguard Worker // Command send to pci root worker thread to add/remove device from pci root
125*bb4ee6a4SAndroid Build Coastguard Worker pub enum PciRootCommand {
126*bb4ee6a4SAndroid Build Coastguard Worker     Add(PciAddress, Arc<Mutex<dyn BusDevice>>),
127*bb4ee6a4SAndroid Build Coastguard Worker     AddBridge(Arc<Mutex<PciBus>>),
128*bb4ee6a4SAndroid Build Coastguard Worker     Remove(PciAddress),
129*bb4ee6a4SAndroid Build Coastguard Worker     Kill,
130*bb4ee6a4SAndroid Build Coastguard Worker }
131*bb4ee6a4SAndroid Build Coastguard Worker 
132*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Serialize)]
133*bb4ee6a4SAndroid Build Coastguard Worker struct PciRootMmioState {
134*bb4ee6a4SAndroid Build Coastguard Worker     /// Contains pages mapped read-only into the guest's MMIO space corresponding to
135*bb4ee6a4SAndroid Build Coastguard Worker     /// the PCI configuration space. Keys are the offset in number of pages from the
136*bb4ee6a4SAndroid Build Coastguard Worker     /// start of MMIO space. If a particular value is None, then at least one
137*bb4ee6a4SAndroid Build Coastguard Worker     /// attached device on that page does not support read-only mapped MMIO.
138*bb4ee6a4SAndroid Build Coastguard Worker     #[serde(skip_serializing)]
139*bb4ee6a4SAndroid Build Coastguard Worker     mappings: BTreeMap<u32, Option<(SharedMemory, MemoryMapping)>>,
140*bb4ee6a4SAndroid Build Coastguard Worker     /// Base address of the PCI configuration space's MMIO region.
141*bb4ee6a4SAndroid Build Coastguard Worker     base: GuestAddress,
142*bb4ee6a4SAndroid Build Coastguard Worker     /// Number of bits in the address space of a particular function's MMIO space.
143*bb4ee6a4SAndroid Build Coastguard Worker     register_bit_num: usize,
144*bb4ee6a4SAndroid Build Coastguard Worker }
145*bb4ee6a4SAndroid Build Coastguard Worker 
146*bb4ee6a4SAndroid Build Coastguard Worker /// Emulates the PCI Root bridge.
147*bb4ee6a4SAndroid Build Coastguard Worker #[allow(dead_code)] // TODO(b/174705596): remove once mmio_bus and io_bus are used
148*bb4ee6a4SAndroid Build Coastguard Worker pub struct PciRoot {
149*bb4ee6a4SAndroid Build Coastguard Worker     /// Memory (MMIO) bus.
150*bb4ee6a4SAndroid Build Coastguard Worker     mmio_bus: Weak<Bus>,
151*bb4ee6a4SAndroid Build Coastguard Worker     /// IO bus (x86 only - for non-x86 platforms, this is just an empty Bus).
152*bb4ee6a4SAndroid Build Coastguard Worker     io_bus: Weak<Bus>,
153*bb4ee6a4SAndroid Build Coastguard Worker     /// Root pci bus (bus 0)
154*bb4ee6a4SAndroid Build Coastguard Worker     root_bus: Arc<Mutex<PciBus>>,
155*bb4ee6a4SAndroid Build Coastguard Worker     /// Bus configuration for the root device.
156*bb4ee6a4SAndroid Build Coastguard Worker     root_configuration: PciRootConfiguration,
157*bb4ee6a4SAndroid Build Coastguard Worker     /// Devices attached to this bridge.
158*bb4ee6a4SAndroid Build Coastguard Worker     devices: BTreeMap<PciAddress, Arc<Mutex<dyn BusDevice>>>,
159*bb4ee6a4SAndroid Build Coastguard Worker     /// pcie enhanced configuration access mmio base
160*bb4ee6a4SAndroid Build Coastguard Worker     pcie_cfg_mmio: Option<u64>,
161*bb4ee6a4SAndroid Build Coastguard Worker     pci_mmio_state: PciRootMmioState,
162*bb4ee6a4SAndroid Build Coastguard Worker }
163*bb4ee6a4SAndroid Build Coastguard Worker 
164*bb4ee6a4SAndroid Build Coastguard Worker const PCI_DEVICE_ID_INTEL_82441: u16 = 0x1237;
165*bb4ee6a4SAndroid Build Coastguard Worker const PCIE_XBAR_BASE_ADDR: usize = 24;
166*bb4ee6a4SAndroid Build Coastguard Worker 
167*bb4ee6a4SAndroid Build Coastguard Worker /// Used to serialize relevant information to PciRoot
168*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Serialize, Deserialize)]
169*bb4ee6a4SAndroid Build Coastguard Worker struct PciRootSerializable {
170*bb4ee6a4SAndroid Build Coastguard Worker     root_configuration: serde_json::Value,
171*bb4ee6a4SAndroid Build Coastguard Worker     pcie_cfg_mmio: Option<u64>,
172*bb4ee6a4SAndroid Build Coastguard Worker }
173*bb4ee6a4SAndroid Build Coastguard Worker 
174*bb4ee6a4SAndroid Build Coastguard Worker impl PciRoot {
175*bb4ee6a4SAndroid Build Coastguard Worker     /// Create an empty PCI root bus.
new( vm: &mut impl Vm, mmio_bus: Weak<Bus>, mmio_base: GuestAddress, mmio_register_bit_num: usize, io_bus: Weak<Bus>, root_bus: Arc<Mutex<PciBus>>, ) -> anyhow::Result<Self>176*bb4ee6a4SAndroid Build Coastguard Worker     pub fn new(
177*bb4ee6a4SAndroid Build Coastguard Worker         vm: &mut impl Vm,
178*bb4ee6a4SAndroid Build Coastguard Worker         mmio_bus: Weak<Bus>,
179*bb4ee6a4SAndroid Build Coastguard Worker         mmio_base: GuestAddress,
180*bb4ee6a4SAndroid Build Coastguard Worker         mmio_register_bit_num: usize,
181*bb4ee6a4SAndroid Build Coastguard Worker         io_bus: Weak<Bus>,
182*bb4ee6a4SAndroid Build Coastguard Worker         root_bus: Arc<Mutex<PciBus>>,
183*bb4ee6a4SAndroid Build Coastguard Worker     ) -> anyhow::Result<Self> {
184*bb4ee6a4SAndroid Build Coastguard Worker         // mmio_mappings's implementation assumes each device's mmio registers
185*bb4ee6a4SAndroid Build Coastguard Worker         // can fit on a single page. Always true given existing specs.
186*bb4ee6a4SAndroid Build Coastguard Worker         assert!(base::pagesize() >= (1 << mmio_register_bit_num));
187*bb4ee6a4SAndroid Build Coastguard Worker         let mut root =
188*bb4ee6a4SAndroid Build Coastguard Worker             Self::create_for_test(mmio_bus, mmio_base, mmio_register_bit_num, io_bus, root_bus);
189*bb4ee6a4SAndroid Build Coastguard Worker         root.pci_mmio_state
190*bb4ee6a4SAndroid Build Coastguard Worker             .setup_mapping(
191*bb4ee6a4SAndroid Build Coastguard Worker                 &PciAddress::new(0, 0, 0, 0).unwrap(),
192*bb4ee6a4SAndroid Build Coastguard Worker                 &mut root.root_configuration,
193*bb4ee6a4SAndroid Build Coastguard Worker                 vm,
194*bb4ee6a4SAndroid Build Coastguard Worker             )
195*bb4ee6a4SAndroid Build Coastguard Worker             .context("failed to set up root configuration mapping")?;
196*bb4ee6a4SAndroid Build Coastguard Worker         Ok(root)
197*bb4ee6a4SAndroid Build Coastguard Worker     }
198*bb4ee6a4SAndroid Build Coastguard Worker 
create_for_test( mmio_bus: Weak<Bus>, mmio_base: GuestAddress, mmio_register_bit_num: usize, io_bus: Weak<Bus>, root_bus: Arc<Mutex<PciBus>>, ) -> Self199*bb4ee6a4SAndroid Build Coastguard Worker     fn create_for_test(
200*bb4ee6a4SAndroid Build Coastguard Worker         mmio_bus: Weak<Bus>,
201*bb4ee6a4SAndroid Build Coastguard Worker         mmio_base: GuestAddress,
202*bb4ee6a4SAndroid Build Coastguard Worker         mmio_register_bit_num: usize,
203*bb4ee6a4SAndroid Build Coastguard Worker         io_bus: Weak<Bus>,
204*bb4ee6a4SAndroid Build Coastguard Worker         root_bus: Arc<Mutex<PciBus>>,
205*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Self {
206*bb4ee6a4SAndroid Build Coastguard Worker         PciRoot {
207*bb4ee6a4SAndroid Build Coastguard Worker             mmio_bus,
208*bb4ee6a4SAndroid Build Coastguard Worker             io_bus,
209*bb4ee6a4SAndroid Build Coastguard Worker             root_bus,
210*bb4ee6a4SAndroid Build Coastguard Worker             root_configuration: PciRootConfiguration {
211*bb4ee6a4SAndroid Build Coastguard Worker                 config: PciConfiguration::new(
212*bb4ee6a4SAndroid Build Coastguard Worker                     PCI_VENDOR_ID_INTEL,
213*bb4ee6a4SAndroid Build Coastguard Worker                     PCI_DEVICE_ID_INTEL_82441,
214*bb4ee6a4SAndroid Build Coastguard Worker                     PciClassCode::BridgeDevice,
215*bb4ee6a4SAndroid Build Coastguard Worker                     &PciBridgeSubclass::HostBridge,
216*bb4ee6a4SAndroid Build Coastguard Worker                     None,
217*bb4ee6a4SAndroid Build Coastguard Worker                     PciHeaderType::Device,
218*bb4ee6a4SAndroid Build Coastguard Worker                     0,
219*bb4ee6a4SAndroid Build Coastguard Worker                     0,
220*bb4ee6a4SAndroid Build Coastguard Worker                     0,
221*bb4ee6a4SAndroid Build Coastguard Worker                 ),
222*bb4ee6a4SAndroid Build Coastguard Worker             },
223*bb4ee6a4SAndroid Build Coastguard Worker             devices: BTreeMap::new(),
224*bb4ee6a4SAndroid Build Coastguard Worker             pcie_cfg_mmio: None,
225*bb4ee6a4SAndroid Build Coastguard Worker             pci_mmio_state: PciRootMmioState {
226*bb4ee6a4SAndroid Build Coastguard Worker                 mappings: BTreeMap::new(),
227*bb4ee6a4SAndroid Build Coastguard Worker                 base: mmio_base,
228*bb4ee6a4SAndroid Build Coastguard Worker                 register_bit_num: mmio_register_bit_num,
229*bb4ee6a4SAndroid Build Coastguard Worker             },
230*bb4ee6a4SAndroid Build Coastguard Worker         }
231*bb4ee6a4SAndroid Build Coastguard Worker     }
232*bb4ee6a4SAndroid Build Coastguard Worker 
233*bb4ee6a4SAndroid Build Coastguard Worker     /// Get the root pci bus
get_root_bus(&self) -> Arc<Mutex<PciBus>>234*bb4ee6a4SAndroid Build Coastguard Worker     pub fn get_root_bus(&self) -> Arc<Mutex<PciBus>> {
235*bb4ee6a4SAndroid Build Coastguard Worker         self.root_bus.clone()
236*bb4ee6a4SAndroid Build Coastguard Worker     }
237*bb4ee6a4SAndroid Build Coastguard Worker 
238*bb4ee6a4SAndroid Build Coastguard Worker     /// Get the ACPI path to a PCI device
acpi_path(&self, address: &PciAddress) -> Option<String>239*bb4ee6a4SAndroid Build Coastguard Worker     pub fn acpi_path(&self, address: &PciAddress) -> Option<String> {
240*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(device) = self.devices.get(address) {
241*bb4ee6a4SAndroid Build Coastguard Worker             let path = self.root_bus.lock().path_to(address.bus);
242*bb4ee6a4SAndroid Build Coastguard Worker             if path.is_empty() {
243*bb4ee6a4SAndroid Build Coastguard Worker                 None
244*bb4ee6a4SAndroid Build Coastguard Worker             } else {
245*bb4ee6a4SAndroid Build Coastguard Worker                 Some(format!(
246*bb4ee6a4SAndroid Build Coastguard Worker                     "_SB_.{}.{}",
247*bb4ee6a4SAndroid Build Coastguard Worker                     path.iter()
248*bb4ee6a4SAndroid Build Coastguard Worker                         .map(|x| format!("PC{:02X}", x))
249*bb4ee6a4SAndroid Build Coastguard Worker                         .collect::<Vec<String>>()
250*bb4ee6a4SAndroid Build Coastguard Worker                         .join("."),
251*bb4ee6a4SAndroid Build Coastguard Worker                     match device.lock().is_bridge() {
252*bb4ee6a4SAndroid Build Coastguard Worker                         Some(bus_no) => format!("PC{:02X}", bus_no),
253*bb4ee6a4SAndroid Build Coastguard Worker                         None => format!("PE{:02X}", address.devfn()),
254*bb4ee6a4SAndroid Build Coastguard Worker                     }
255*bb4ee6a4SAndroid Build Coastguard Worker                 ))
256*bb4ee6a4SAndroid Build Coastguard Worker             }
257*bb4ee6a4SAndroid Build Coastguard Worker         } else {
258*bb4ee6a4SAndroid Build Coastguard Worker             None
259*bb4ee6a4SAndroid Build Coastguard Worker         }
260*bb4ee6a4SAndroid Build Coastguard Worker     }
261*bb4ee6a4SAndroid Build Coastguard Worker 
262*bb4ee6a4SAndroid Build Coastguard Worker     /// enable pcie enhanced configuration access and set base mmio
enable_pcie_cfg_mmio(&mut self, pcie_cfg_mmio: u64)263*bb4ee6a4SAndroid Build Coastguard Worker     pub fn enable_pcie_cfg_mmio(&mut self, pcie_cfg_mmio: u64) {
264*bb4ee6a4SAndroid Build Coastguard Worker         self.pcie_cfg_mmio = Some(pcie_cfg_mmio);
265*bb4ee6a4SAndroid Build Coastguard Worker         // Update the config space registers that depend on pcie_cfg_mmio.
266*bb4ee6a4SAndroid Build Coastguard Worker         self.root_configuration.config.set_reg(
267*bb4ee6a4SAndroid Build Coastguard Worker             PCIE_XBAR_BASE_ADDR,
268*bb4ee6a4SAndroid Build Coastguard Worker             self.pcie_cfg_mmio.unwrap() as u32 | 0x1,
269*bb4ee6a4SAndroid Build Coastguard Worker             0xffff_ffff,
270*bb4ee6a4SAndroid Build Coastguard Worker         );
271*bb4ee6a4SAndroid Build Coastguard Worker         self.root_configuration.config.set_reg(
272*bb4ee6a4SAndroid Build Coastguard Worker             PCIE_XBAR_BASE_ADDR + 1,
273*bb4ee6a4SAndroid Build Coastguard Worker             (self.pcie_cfg_mmio.unwrap() >> 32) as u32,
274*bb4ee6a4SAndroid Build Coastguard Worker             0xffff_ffff,
275*bb4ee6a4SAndroid Build Coastguard Worker         );
276*bb4ee6a4SAndroid Build Coastguard Worker     }
277*bb4ee6a4SAndroid Build Coastguard Worker 
278*bb4ee6a4SAndroid Build Coastguard Worker     /// Add a `device` to this root PCI bus.
add_device<T>( &mut self, address: PciAddress, device: Arc<Mutex<dyn BusDevice>>, mapper: &mut T, ) -> Result<(), Error> where T: PciMmioMapper,279*bb4ee6a4SAndroid Build Coastguard Worker     pub fn add_device<T>(
280*bb4ee6a4SAndroid Build Coastguard Worker         &mut self,
281*bb4ee6a4SAndroid Build Coastguard Worker         address: PciAddress,
282*bb4ee6a4SAndroid Build Coastguard Worker         device: Arc<Mutex<dyn BusDevice>>,
283*bb4ee6a4SAndroid Build Coastguard Worker         mapper: &mut T,
284*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Result<(), Error>
285*bb4ee6a4SAndroid Build Coastguard Worker     where
286*bb4ee6a4SAndroid Build Coastguard Worker         T: PciMmioMapper,
287*bb4ee6a4SAndroid Build Coastguard Worker     {
288*bb4ee6a4SAndroid Build Coastguard Worker         // Ignore attempt to replace PCI Root host bridge.
289*bb4ee6a4SAndroid Build Coastguard Worker         if !address.is_root() {
290*bb4ee6a4SAndroid Build Coastguard Worker             self.pci_mmio_state
291*bb4ee6a4SAndroid Build Coastguard Worker                 .setup_mapping(&address, device.lock().deref_mut(), mapper)
292*bb4ee6a4SAndroid Build Coastguard Worker                 .map_err(Error::MmioSetup)?;
293*bb4ee6a4SAndroid Build Coastguard Worker             self.devices.insert(address, device);
294*bb4ee6a4SAndroid Build Coastguard Worker             self.sync_multifunction_bit_to_mmio_mappings(&address, true);
295*bb4ee6a4SAndroid Build Coastguard Worker         }
296*bb4ee6a4SAndroid Build Coastguard Worker 
297*bb4ee6a4SAndroid Build Coastguard Worker         self.root_bus.lock().add_child_device(address)
298*bb4ee6a4SAndroid Build Coastguard Worker     }
299*bb4ee6a4SAndroid Build Coastguard Worker 
sync_multifunction_bit_to_mmio_mappings(&mut self, address: &PciAddress, on_add: bool)300*bb4ee6a4SAndroid Build Coastguard Worker     fn sync_multifunction_bit_to_mmio_mappings(&mut self, address: &PciAddress, on_add: bool) {
301*bb4ee6a4SAndroid Build Coastguard Worker         let num_mfd = self.num_multifunction_device(address);
302*bb4ee6a4SAndroid Build Coastguard Worker         let target_range = if (num_mfd == 1 && on_add) || (num_mfd == 0 && !on_add) {
303*bb4ee6a4SAndroid Build Coastguard Worker             // If we added the first mfd or removed the last mfd, update all functions' bits
304*bb4ee6a4SAndroid Build Coastguard Worker             0..8
305*bb4ee6a4SAndroid Build Coastguard Worker         } else if on_add && num_mfd > 0 {
306*bb4ee6a4SAndroid Build Coastguard Worker             // If we added a new function, set its bit if necessary
307*bb4ee6a4SAndroid Build Coastguard Worker             address.func..(address.func + 1)
308*bb4ee6a4SAndroid Build Coastguard Worker         } else {
309*bb4ee6a4SAndroid Build Coastguard Worker             return;
310*bb4ee6a4SAndroid Build Coastguard Worker         };
311*bb4ee6a4SAndroid Build Coastguard Worker         for i in target_range {
312*bb4ee6a4SAndroid Build Coastguard Worker             self.pci_mmio_state.set_mfd_bit(
313*bb4ee6a4SAndroid Build Coastguard Worker                 &PciAddress {
314*bb4ee6a4SAndroid Build Coastguard Worker                     func: i,
315*bb4ee6a4SAndroid Build Coastguard Worker                     ..*address
316*bb4ee6a4SAndroid Build Coastguard Worker                 },
317*bb4ee6a4SAndroid Build Coastguard Worker                 num_mfd > 0,
318*bb4ee6a4SAndroid Build Coastguard Worker             );
319*bb4ee6a4SAndroid Build Coastguard Worker         }
320*bb4ee6a4SAndroid Build Coastguard Worker     }
321*bb4ee6a4SAndroid Build Coastguard Worker 
add_bridge(&mut self, bridge_bus: Arc<Mutex<PciBus>>) -> Result<(), Error>322*bb4ee6a4SAndroid Build Coastguard Worker     pub fn add_bridge(&mut self, bridge_bus: Arc<Mutex<PciBus>>) -> Result<(), Error> {
323*bb4ee6a4SAndroid Build Coastguard Worker         self.root_bus.lock().add_child_bus(bridge_bus)
324*bb4ee6a4SAndroid Build Coastguard Worker     }
325*bb4ee6a4SAndroid Build Coastguard Worker 
remove_device(&mut self, address: PciAddress)326*bb4ee6a4SAndroid Build Coastguard Worker     pub fn remove_device(&mut self, address: PciAddress) {
327*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(d) = self.devices.remove(&address) {
328*bb4ee6a4SAndroid Build Coastguard Worker             for (range, bus_type) in d.lock().get_ranges() {
329*bb4ee6a4SAndroid Build Coastguard Worker                 let bus_ptr = if bus_type == BusType::Mmio {
330*bb4ee6a4SAndroid Build Coastguard Worker                     match self.mmio_bus.upgrade() {
331*bb4ee6a4SAndroid Build Coastguard Worker                         Some(m) => m,
332*bb4ee6a4SAndroid Build Coastguard Worker                         None => continue,
333*bb4ee6a4SAndroid Build Coastguard Worker                     }
334*bb4ee6a4SAndroid Build Coastguard Worker                 } else {
335*bb4ee6a4SAndroid Build Coastguard Worker                     match self.io_bus.upgrade() {
336*bb4ee6a4SAndroid Build Coastguard Worker                         Some(i) => i,
337*bb4ee6a4SAndroid Build Coastguard Worker                         None => continue,
338*bb4ee6a4SAndroid Build Coastguard Worker                     }
339*bb4ee6a4SAndroid Build Coastguard Worker                 };
340*bb4ee6a4SAndroid Build Coastguard Worker                 let _ = bus_ptr.remove(range.base, range.len);
341*bb4ee6a4SAndroid Build Coastguard Worker             }
342*bb4ee6a4SAndroid Build Coastguard Worker             // Remove the pci bus if this device is a pci bridge.
343*bb4ee6a4SAndroid Build Coastguard Worker             if let Some(bus_no) = d.lock().is_bridge() {
344*bb4ee6a4SAndroid Build Coastguard Worker                 let _ = self.root_bus.lock().remove_child_bus(bus_no);
345*bb4ee6a4SAndroid Build Coastguard Worker             }
346*bb4ee6a4SAndroid Build Coastguard Worker             d.lock().destroy_device();
347*bb4ee6a4SAndroid Build Coastguard Worker             let _ = self.root_bus.lock().remove_child_device(address);
348*bb4ee6a4SAndroid Build Coastguard Worker         }
349*bb4ee6a4SAndroid Build Coastguard Worker         self.sync_multifunction_bit_to_mmio_mappings(&address, false);
350*bb4ee6a4SAndroid Build Coastguard Worker     }
351*bb4ee6a4SAndroid Build Coastguard Worker 
config_space_read(&self, address: PciAddress, register: usize) -> u32352*bb4ee6a4SAndroid Build Coastguard Worker     pub fn config_space_read(&self, address: PciAddress, register: usize) -> u32 {
353*bb4ee6a4SAndroid Build Coastguard Worker         if address.is_root() {
354*bb4ee6a4SAndroid Build Coastguard Worker             if register == PCIE_XBAR_BASE_ADDR && self.pcie_cfg_mmio.is_some() {
355*bb4ee6a4SAndroid Build Coastguard Worker                 let pcie_mmio = self.pcie_cfg_mmio.unwrap() as u32;
356*bb4ee6a4SAndroid Build Coastguard Worker                 pcie_mmio | 0x1
357*bb4ee6a4SAndroid Build Coastguard Worker             } else if register == (PCIE_XBAR_BASE_ADDR + 1) && self.pcie_cfg_mmio.is_some() {
358*bb4ee6a4SAndroid Build Coastguard Worker                 (self.pcie_cfg_mmio.unwrap() >> 32) as u32
359*bb4ee6a4SAndroid Build Coastguard Worker             } else {
360*bb4ee6a4SAndroid Build Coastguard Worker                 self.root_configuration.config_register_read(register)
361*bb4ee6a4SAndroid Build Coastguard Worker             }
362*bb4ee6a4SAndroid Build Coastguard Worker         } else {
363*bb4ee6a4SAndroid Build Coastguard Worker             let mut data = self
364*bb4ee6a4SAndroid Build Coastguard Worker                 .devices
365*bb4ee6a4SAndroid Build Coastguard Worker                 .get(&address)
366*bb4ee6a4SAndroid Build Coastguard Worker                 .map_or(0xffff_ffff, |d| d.lock().config_register_read(register));
367*bb4ee6a4SAndroid Build Coastguard Worker 
368*bb4ee6a4SAndroid Build Coastguard Worker             if register == HEADER_TYPE_REG {
369*bb4ee6a4SAndroid Build Coastguard Worker                 // Set multifunction bit in header type if there are devices at non-zero functions
370*bb4ee6a4SAndroid Build Coastguard Worker                 // in this slot.
371*bb4ee6a4SAndroid Build Coastguard Worker                 if self.num_multifunction_device(&address) != 0 {
372*bb4ee6a4SAndroid Build Coastguard Worker                     data |= (HEADER_TYPE_MULTIFUNCTION_MASK as u32) << (HEADER_TYPE_REG_OFFSET * 8);
373*bb4ee6a4SAndroid Build Coastguard Worker                 }
374*bb4ee6a4SAndroid Build Coastguard Worker             }
375*bb4ee6a4SAndroid Build Coastguard Worker 
376*bb4ee6a4SAndroid Build Coastguard Worker             data
377*bb4ee6a4SAndroid Build Coastguard Worker         }
378*bb4ee6a4SAndroid Build Coastguard Worker     }
379*bb4ee6a4SAndroid Build Coastguard Worker 
config_space_write( &mut self, address: PciAddress, register: usize, offset: u64, data: &[u8], )380*bb4ee6a4SAndroid Build Coastguard Worker     pub fn config_space_write(
381*bb4ee6a4SAndroid Build Coastguard Worker         &mut self,
382*bb4ee6a4SAndroid Build Coastguard Worker         address: PciAddress,
383*bb4ee6a4SAndroid Build Coastguard Worker         register: usize,
384*bb4ee6a4SAndroid Build Coastguard Worker         offset: u64,
385*bb4ee6a4SAndroid Build Coastguard Worker         data: &[u8],
386*bb4ee6a4SAndroid Build Coastguard Worker     ) {
387*bb4ee6a4SAndroid Build Coastguard Worker         if offset as usize + data.len() > 4 {
388*bb4ee6a4SAndroid Build Coastguard Worker             return;
389*bb4ee6a4SAndroid Build Coastguard Worker         }
390*bb4ee6a4SAndroid Build Coastguard Worker         if address.is_root() {
391*bb4ee6a4SAndroid Build Coastguard Worker             self.root_configuration
392*bb4ee6a4SAndroid Build Coastguard Worker                 .config_register_write(register, offset, data);
393*bb4ee6a4SAndroid Build Coastguard Worker         } else if let Some(d) = self.devices.get(&address) {
394*bb4ee6a4SAndroid Build Coastguard Worker             let res = d.lock().config_register_write(register, offset, data);
395*bb4ee6a4SAndroid Build Coastguard Worker 
396*bb4ee6a4SAndroid Build Coastguard Worker             if !res.mmio_add.is_empty() || !res.mmio_remove.is_empty() {
397*bb4ee6a4SAndroid Build Coastguard Worker                 let mmio_bus = match self.mmio_bus.upgrade() {
398*bb4ee6a4SAndroid Build Coastguard Worker                     Some(m) => m,
399*bb4ee6a4SAndroid Build Coastguard Worker                     None => return,
400*bb4ee6a4SAndroid Build Coastguard Worker                 };
401*bb4ee6a4SAndroid Build Coastguard Worker                 for range in &res.mmio_remove {
402*bb4ee6a4SAndroid Build Coastguard Worker                     let _ = mmio_bus.remove(range.base, range.len);
403*bb4ee6a4SAndroid Build Coastguard Worker                 }
404*bb4ee6a4SAndroid Build Coastguard Worker                 for range in &res.mmio_add {
405*bb4ee6a4SAndroid Build Coastguard Worker                     let _ = mmio_bus.insert(d.clone(), range.base, range.len);
406*bb4ee6a4SAndroid Build Coastguard Worker                 }
407*bb4ee6a4SAndroid Build Coastguard Worker             }
408*bb4ee6a4SAndroid Build Coastguard Worker 
409*bb4ee6a4SAndroid Build Coastguard Worker             if !res.io_add.is_empty() || !res.io_remove.is_empty() {
410*bb4ee6a4SAndroid Build Coastguard Worker                 let io_bus = match self.io_bus.upgrade() {
411*bb4ee6a4SAndroid Build Coastguard Worker                     Some(i) => i,
412*bb4ee6a4SAndroid Build Coastguard Worker                     None => return,
413*bb4ee6a4SAndroid Build Coastguard Worker                 };
414*bb4ee6a4SAndroid Build Coastguard Worker                 for range in &res.io_remove {
415*bb4ee6a4SAndroid Build Coastguard Worker                     let _ = io_bus.remove(range.base, range.len);
416*bb4ee6a4SAndroid Build Coastguard Worker                 }
417*bb4ee6a4SAndroid Build Coastguard Worker                 for range in &res.io_add {
418*bb4ee6a4SAndroid Build Coastguard Worker                     let _ = io_bus.insert(d.clone(), range.base, range.len);
419*bb4ee6a4SAndroid Build Coastguard Worker                 }
420*bb4ee6a4SAndroid Build Coastguard Worker             }
421*bb4ee6a4SAndroid Build Coastguard Worker 
422*bb4ee6a4SAndroid Build Coastguard Worker             for remove_pci_device in res.removed_pci_devices.iter() {
423*bb4ee6a4SAndroid Build Coastguard Worker                 self.remove_device(*remove_pci_device);
424*bb4ee6a4SAndroid Build Coastguard Worker             }
425*bb4ee6a4SAndroid Build Coastguard Worker         }
426*bb4ee6a4SAndroid Build Coastguard Worker     }
427*bb4ee6a4SAndroid Build Coastguard Worker 
virtual_config_space_read(&self, address: PciAddress, register: usize) -> u32428*bb4ee6a4SAndroid Build Coastguard Worker     pub fn virtual_config_space_read(&self, address: PciAddress, register: usize) -> u32 {
429*bb4ee6a4SAndroid Build Coastguard Worker         if address.is_root() {
430*bb4ee6a4SAndroid Build Coastguard Worker             0u32
431*bb4ee6a4SAndroid Build Coastguard Worker         } else {
432*bb4ee6a4SAndroid Build Coastguard Worker             self.devices
433*bb4ee6a4SAndroid Build Coastguard Worker                 .get(&address)
434*bb4ee6a4SAndroid Build Coastguard Worker                 .map_or(0u32, |d| d.lock().virtual_config_register_read(register))
435*bb4ee6a4SAndroid Build Coastguard Worker         }
436*bb4ee6a4SAndroid Build Coastguard Worker     }
437*bb4ee6a4SAndroid Build Coastguard Worker 
virtual_config_space_write(&mut self, address: PciAddress, register: usize, value: u32)438*bb4ee6a4SAndroid Build Coastguard Worker     pub fn virtual_config_space_write(&mut self, address: PciAddress, register: usize, value: u32) {
439*bb4ee6a4SAndroid Build Coastguard Worker         if !address.is_root() {
440*bb4ee6a4SAndroid Build Coastguard Worker             if let Some(d) = self.devices.get(&address) {
441*bb4ee6a4SAndroid Build Coastguard Worker                 d.lock().virtual_config_register_write(register, value);
442*bb4ee6a4SAndroid Build Coastguard Worker             }
443*bb4ee6a4SAndroid Build Coastguard Worker         }
444*bb4ee6a4SAndroid Build Coastguard Worker     }
445*bb4ee6a4SAndroid Build Coastguard Worker 
snapshot(&mut self) -> anyhow::Result<serde_json::Value>446*bb4ee6a4SAndroid Build Coastguard Worker     pub fn snapshot(&mut self) -> anyhow::Result<serde_json::Value> {
447*bb4ee6a4SAndroid Build Coastguard Worker         serde_json::to_value(PciRootSerializable {
448*bb4ee6a4SAndroid Build Coastguard Worker             root_configuration: self
449*bb4ee6a4SAndroid Build Coastguard Worker                 .root_configuration
450*bb4ee6a4SAndroid Build Coastguard Worker                 .snapshot()
451*bb4ee6a4SAndroid Build Coastguard Worker                 .context("failed to serialize PciRoot.root_configuration")?,
452*bb4ee6a4SAndroid Build Coastguard Worker             pcie_cfg_mmio: self.pcie_cfg_mmio,
453*bb4ee6a4SAndroid Build Coastguard Worker         })
454*bb4ee6a4SAndroid Build Coastguard Worker         .context("failed to serialize PciRoot")
455*bb4ee6a4SAndroid Build Coastguard Worker     }
456*bb4ee6a4SAndroid Build Coastguard Worker 
restore(&mut self, data: serde_json::Value) -> anyhow::Result<()>457*bb4ee6a4SAndroid Build Coastguard Worker     pub fn restore(&mut self, data: serde_json::Value) -> anyhow::Result<()> {
458*bb4ee6a4SAndroid Build Coastguard Worker         let deser: PciRootSerializable =
459*bb4ee6a4SAndroid Build Coastguard Worker             serde_json::from_value(data).context("failed to deserialize PciRoot")?;
460*bb4ee6a4SAndroid Build Coastguard Worker         self.root_configuration.restore(deser.root_configuration)?;
461*bb4ee6a4SAndroid Build Coastguard Worker         self.pcie_cfg_mmio = deser.pcie_cfg_mmio;
462*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
463*bb4ee6a4SAndroid Build Coastguard Worker     }
464*bb4ee6a4SAndroid Build Coastguard Worker 
num_multifunction_device(&self, address: &PciAddress) -> usize465*bb4ee6a4SAndroid Build Coastguard Worker     fn num_multifunction_device(&self, address: &PciAddress) -> usize {
466*bb4ee6a4SAndroid Build Coastguard Worker         self.devices
467*bb4ee6a4SAndroid Build Coastguard Worker             .range((
468*bb4ee6a4SAndroid Build Coastguard Worker                 Included(&PciAddress {
469*bb4ee6a4SAndroid Build Coastguard Worker                     func: 1,
470*bb4ee6a4SAndroid Build Coastguard Worker                     ..*address
471*bb4ee6a4SAndroid Build Coastguard Worker                 }),
472*bb4ee6a4SAndroid Build Coastguard Worker                 Included(&PciAddress {
473*bb4ee6a4SAndroid Build Coastguard Worker                     func: 7,
474*bb4ee6a4SAndroid Build Coastguard Worker                     ..*address
475*bb4ee6a4SAndroid Build Coastguard Worker                 }),
476*bb4ee6a4SAndroid Build Coastguard Worker             ))
477*bb4ee6a4SAndroid Build Coastguard Worker             .count()
478*bb4ee6a4SAndroid Build Coastguard Worker     }
479*bb4ee6a4SAndroid Build Coastguard Worker }
480*bb4ee6a4SAndroid Build Coastguard Worker 
481*bb4ee6a4SAndroid Build Coastguard Worker impl PciRootMmioState {
setup_mapping<T>( &mut self, address: &PciAddress, device: &mut dyn BusDevice, mapper: &mut T, ) -> anyhow::Result<()> where T: PciMmioMapper,482*bb4ee6a4SAndroid Build Coastguard Worker     fn setup_mapping<T>(
483*bb4ee6a4SAndroid Build Coastguard Worker         &mut self,
484*bb4ee6a4SAndroid Build Coastguard Worker         address: &PciAddress,
485*bb4ee6a4SAndroid Build Coastguard Worker         device: &mut dyn BusDevice,
486*bb4ee6a4SAndroid Build Coastguard Worker         mapper: &mut T,
487*bb4ee6a4SAndroid Build Coastguard Worker     ) -> anyhow::Result<()>
488*bb4ee6a4SAndroid Build Coastguard Worker     where
489*bb4ee6a4SAndroid Build Coastguard Worker         T: PciMmioMapper,
490*bb4ee6a4SAndroid Build Coastguard Worker     {
491*bb4ee6a4SAndroid Build Coastguard Worker         // ANDROID(b/316956218): pKVM doesn't support readonly memslots, so return early from this
492*bb4ee6a4SAndroid Build Coastguard Worker         // function to opt-out of the optimizations that require readonly memslots. This will also
493*bb4ee6a4SAndroid Build Coastguard Worker         // affect aarch64 cuttlefish unforunately. Once we have a way to detect pKVM at runtime, we
494*bb4ee6a4SAndroid Build Coastguard Worker         // should move this check upstream.
495*bb4ee6a4SAndroid Build Coastguard Worker         if cfg!(target_arch = "aarch64") {
496*bb4ee6a4SAndroid Build Coastguard Worker             return Ok(());
497*bb4ee6a4SAndroid Build Coastguard Worker         }
498*bb4ee6a4SAndroid Build Coastguard Worker 
499*bb4ee6a4SAndroid Build Coastguard Worker         // The PCI spec requires that config writes are non-posted. This requires
500*bb4ee6a4SAndroid Build Coastguard Worker         // uncached mappings in the guest. 32-bit ARM does not support flushing to
501*bb4ee6a4SAndroid Build Coastguard Worker         // PoC from userspace. The cache maintance story for riscv is unclear, so
502*bb4ee6a4SAndroid Build Coastguard Worker         // that is also not implemmented.
503*bb4ee6a4SAndroid Build Coastguard Worker         if cfg!(not(any(target_arch = "x86_64", target_arch = "aarch64"))) {
504*bb4ee6a4SAndroid Build Coastguard Worker             return Ok(());
505*bb4ee6a4SAndroid Build Coastguard Worker         }
506*bb4ee6a4SAndroid Build Coastguard Worker 
507*bb4ee6a4SAndroid Build Coastguard Worker         // The optional optimizations below require the hypervisor to support read-only memory
508*bb4ee6a4SAndroid Build Coastguard Worker         // regions.
509*bb4ee6a4SAndroid Build Coastguard Worker         if !mapper.supports_readonly_mapping() {
510*bb4ee6a4SAndroid Build Coastguard Worker             return Ok(());
511*bb4ee6a4SAndroid Build Coastguard Worker         }
512*bb4ee6a4SAndroid Build Coastguard Worker 
513*bb4ee6a4SAndroid Build Coastguard Worker         let pagesize = base::pagesize();
514*bb4ee6a4SAndroid Build Coastguard Worker         let offset = address.to_config_address(0, self.register_bit_num);
515*bb4ee6a4SAndroid Build Coastguard Worker         let mmio_mapping_num = offset / pagesize as u32;
516*bb4ee6a4SAndroid Build Coastguard Worker         let (shmem, new_entry) = match self.mappings.entry(mmio_mapping_num) {
517*bb4ee6a4SAndroid Build Coastguard Worker             BTreeMapEntry::Vacant(e) => {
518*bb4ee6a4SAndroid Build Coastguard Worker                 let shmem = SharedMemory::new(
519*bb4ee6a4SAndroid Build Coastguard Worker                     format!("{:04x}_pci_cfg_mapping", mmio_mapping_num),
520*bb4ee6a4SAndroid Build Coastguard Worker                     pagesize as u64,
521*bb4ee6a4SAndroid Build Coastguard Worker                 )
522*bb4ee6a4SAndroid Build Coastguard Worker                 .context("failed to create shmem")?;
523*bb4ee6a4SAndroid Build Coastguard Worker                 let mapping = MemoryMappingBuilder::new(pagesize)
524*bb4ee6a4SAndroid Build Coastguard Worker                     .from_shared_memory(&shmem)
525*bb4ee6a4SAndroid Build Coastguard Worker                     .protection(Protection::read_write())
526*bb4ee6a4SAndroid Build Coastguard Worker                     .build()
527*bb4ee6a4SAndroid Build Coastguard Worker                     .context("failed to map shmem")?;
528*bb4ee6a4SAndroid Build Coastguard Worker                 let (shmem, _) = e.insert(Some((shmem, mapping))).as_ref().unwrap();
529*bb4ee6a4SAndroid Build Coastguard Worker                 (shmem, true)
530*bb4ee6a4SAndroid Build Coastguard Worker             }
531*bb4ee6a4SAndroid Build Coastguard Worker             BTreeMapEntry::Occupied(e) => {
532*bb4ee6a4SAndroid Build Coastguard Worker                 let Some((shmem, _)) = e.into_mut() else {
533*bb4ee6a4SAndroid Build Coastguard Worker                     // Another device sharing the page didn't support mapped mmio. Oh
534*bb4ee6a4SAndroid Build Coastguard Worker                     // well, we'll just have to fall back to vm-exit handling.
535*bb4ee6a4SAndroid Build Coastguard Worker                     return Ok(());
536*bb4ee6a4SAndroid Build Coastguard Worker                 };
537*bb4ee6a4SAndroid Build Coastguard Worker                 (&*shmem, false)
538*bb4ee6a4SAndroid Build Coastguard Worker             }
539*bb4ee6a4SAndroid Build Coastguard Worker         };
540*bb4ee6a4SAndroid Build Coastguard Worker 
541*bb4ee6a4SAndroid Build Coastguard Worker         if device.init_pci_config_mapping(
542*bb4ee6a4SAndroid Build Coastguard Worker             shmem,
543*bb4ee6a4SAndroid Build Coastguard Worker             offset as usize % pagesize,
544*bb4ee6a4SAndroid Build Coastguard Worker             1 << self.register_bit_num,
545*bb4ee6a4SAndroid Build Coastguard Worker         ) {
546*bb4ee6a4SAndroid Build Coastguard Worker             if new_entry {
547*bb4ee6a4SAndroid Build Coastguard Worker                 let mmio_address = self
548*bb4ee6a4SAndroid Build Coastguard Worker                     .base
549*bb4ee6a4SAndroid Build Coastguard Worker                     .unchecked_add(mmio_mapping_num as u64 * pagesize as u64);
550*bb4ee6a4SAndroid Build Coastguard Worker                 match mapper.add_mapping(mmio_address, shmem) {
551*bb4ee6a4SAndroid Build Coastguard Worker                     // We never unmap the mapping, so we don't need the id
552*bb4ee6a4SAndroid Build Coastguard Worker                     Ok(_) => (),
553*bb4ee6a4SAndroid Build Coastguard Worker                     // If this fails, mmio handling via vm-exit will work fine. Devices
554*bb4ee6a4SAndroid Build Coastguard Worker                     // will be doing some pointless work keeping the unused mapping up
555*bb4ee6a4SAndroid Build Coastguard Worker                     // to date, but addressing that isn't worth the implementation cost.
556*bb4ee6a4SAndroid Build Coastguard Worker                     Err(e) => error!("Failed to map mmio page; {:?}", e),
557*bb4ee6a4SAndroid Build Coastguard Worker                 }
558*bb4ee6a4SAndroid Build Coastguard Worker             }
559*bb4ee6a4SAndroid Build Coastguard Worker         } else {
560*bb4ee6a4SAndroid Build Coastguard Worker             self.mappings.insert(mmio_mapping_num, None);
561*bb4ee6a4SAndroid Build Coastguard Worker         }
562*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
563*bb4ee6a4SAndroid Build Coastguard Worker     }
564*bb4ee6a4SAndroid Build Coastguard Worker 
set_mfd_bit(&mut self, address: &PciAddress, is_mfd: bool)565*bb4ee6a4SAndroid Build Coastguard Worker     fn set_mfd_bit(&mut self, address: &PciAddress, is_mfd: bool) {
566*bb4ee6a4SAndroid Build Coastguard Worker         let pagesize = base::pagesize();
567*bb4ee6a4SAndroid Build Coastguard Worker         let offset = address.to_config_address(0, self.register_bit_num);
568*bb4ee6a4SAndroid Build Coastguard Worker         let mapping_num = offset / pagesize as u32;
569*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(Some((_, mapping))) = self.mappings.get_mut(&mapping_num) {
570*bb4ee6a4SAndroid Build Coastguard Worker             let mapping_base = offset as usize % pagesize;
571*bb4ee6a4SAndroid Build Coastguard Worker             let reg_offset = mapping_base + (HEADER_TYPE_REG * 4) + HEADER_TYPE_REG_OFFSET;
572*bb4ee6a4SAndroid Build Coastguard Worker 
573*bb4ee6a4SAndroid Build Coastguard Worker             let mut val = mapping.read_obj::<u8>(reg_offset).expect("memcpy failed");
574*bb4ee6a4SAndroid Build Coastguard Worker             val = if is_mfd {
575*bb4ee6a4SAndroid Build Coastguard Worker                 val | HEADER_TYPE_MULTIFUNCTION_MASK
576*bb4ee6a4SAndroid Build Coastguard Worker             } else {
577*bb4ee6a4SAndroid Build Coastguard Worker                 val & !HEADER_TYPE_MULTIFUNCTION_MASK
578*bb4ee6a4SAndroid Build Coastguard Worker             };
579*bb4ee6a4SAndroid Build Coastguard Worker             mapping
580*bb4ee6a4SAndroid Build Coastguard Worker                 .write_obj_volatile(val, reg_offset)
581*bb4ee6a4SAndroid Build Coastguard Worker                 .expect("memcpy failed");
582*bb4ee6a4SAndroid Build Coastguard Worker             if let Err(err) = mapping.flush_region(reg_offset, 4) {
583*bb4ee6a4SAndroid Build Coastguard Worker                 error!("failed to flush write to mfd bit: {}", err);
584*bb4ee6a4SAndroid Build Coastguard Worker             }
585*bb4ee6a4SAndroid Build Coastguard Worker         }
586*bb4ee6a4SAndroid Build Coastguard Worker     }
587*bb4ee6a4SAndroid Build Coastguard Worker }
588*bb4ee6a4SAndroid Build Coastguard Worker 
589*bb4ee6a4SAndroid Build Coastguard Worker pub trait PciMmioMapper {
supports_readonly_mapping(&self) -> bool590*bb4ee6a4SAndroid Build Coastguard Worker     fn supports_readonly_mapping(&self) -> bool;
add_mapping(&mut self, addr: GuestAddress, shmem: &SharedMemory) -> anyhow::Result<u32>591*bb4ee6a4SAndroid Build Coastguard Worker     fn add_mapping(&mut self, addr: GuestAddress, shmem: &SharedMemory) -> anyhow::Result<u32>;
592*bb4ee6a4SAndroid Build Coastguard Worker }
593*bb4ee6a4SAndroid Build Coastguard Worker 
594*bb4ee6a4SAndroid Build Coastguard Worker impl<T: Vm> PciMmioMapper for T {
supports_readonly_mapping(&self) -> bool595*bb4ee6a4SAndroid Build Coastguard Worker     fn supports_readonly_mapping(&self) -> bool {
596*bb4ee6a4SAndroid Build Coastguard Worker         self.check_capability(hypervisor::VmCap::ReadOnlyMemoryRegion)
597*bb4ee6a4SAndroid Build Coastguard Worker     }
598*bb4ee6a4SAndroid Build Coastguard Worker 
add_mapping(&mut self, addr: GuestAddress, shmem: &SharedMemory) -> anyhow::Result<u32>599*bb4ee6a4SAndroid Build Coastguard Worker     fn add_mapping(&mut self, addr: GuestAddress, shmem: &SharedMemory) -> anyhow::Result<u32> {
600*bb4ee6a4SAndroid Build Coastguard Worker         let mapping = MemoryMappingBuilder::new(base::pagesize())
601*bb4ee6a4SAndroid Build Coastguard Worker             .from_shared_memory(shmem)
602*bb4ee6a4SAndroid Build Coastguard Worker             .protection(Protection::read())
603*bb4ee6a4SAndroid Build Coastguard Worker             .build()
604*bb4ee6a4SAndroid Build Coastguard Worker             .context("failed to map shmem")?;
605*bb4ee6a4SAndroid Build Coastguard Worker         self.add_memory_region(
606*bb4ee6a4SAndroid Build Coastguard Worker             addr,
607*bb4ee6a4SAndroid Build Coastguard Worker             Box::new(mapping),
608*bb4ee6a4SAndroid Build Coastguard Worker             true,
609*bb4ee6a4SAndroid Build Coastguard Worker             false,
610*bb4ee6a4SAndroid Build Coastguard Worker             MemCacheType::CacheCoherent,
611*bb4ee6a4SAndroid Build Coastguard Worker         )
612*bb4ee6a4SAndroid Build Coastguard Worker         .context("failed to create vm mapping")
613*bb4ee6a4SAndroid Build Coastguard Worker     }
614*bb4ee6a4SAndroid Build Coastguard Worker }
615*bb4ee6a4SAndroid Build Coastguard Worker 
616*bb4ee6a4SAndroid Build Coastguard Worker /// Emulates PCI configuration access mechanism #1 (I/O ports 0xcf8 and 0xcfc).
617*bb4ee6a4SAndroid Build Coastguard Worker pub struct PciConfigIo {
618*bb4ee6a4SAndroid Build Coastguard Worker     /// PCI root bridge.
619*bb4ee6a4SAndroid Build Coastguard Worker     pci_root: Arc<Mutex<PciRoot>>,
620*bb4ee6a4SAndroid Build Coastguard Worker     /// Current address to read/write from (0xcf8 register, litte endian).
621*bb4ee6a4SAndroid Build Coastguard Worker     config_address: u32,
622*bb4ee6a4SAndroid Build Coastguard Worker     /// Whether or not to actually function.
623*bb4ee6a4SAndroid Build Coastguard Worker     break_linux_pci_config_io: bool,
624*bb4ee6a4SAndroid Build Coastguard Worker     /// Tube to signal that the guest requested reset via writing to 0xcf9 register.
625*bb4ee6a4SAndroid Build Coastguard Worker     reset_evt_wrtube: SendTube,
626*bb4ee6a4SAndroid Build Coastguard Worker }
627*bb4ee6a4SAndroid Build Coastguard Worker 
628*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Serialize, Deserialize)]
629*bb4ee6a4SAndroid Build Coastguard Worker struct PciConfigIoSerializable {
630*bb4ee6a4SAndroid Build Coastguard Worker     pci_root: serde_json::Value,
631*bb4ee6a4SAndroid Build Coastguard Worker     config_address: u32,
632*bb4ee6a4SAndroid Build Coastguard Worker }
633*bb4ee6a4SAndroid Build Coastguard Worker 
634*bb4ee6a4SAndroid Build Coastguard Worker impl PciConfigIo {
635*bb4ee6a4SAndroid Build Coastguard Worker     const REGISTER_BITS_NUM: usize = 8;
636*bb4ee6a4SAndroid Build Coastguard Worker 
new( pci_root: Arc<Mutex<PciRoot>>, break_linux_pci_config_io: bool, reset_evt_wrtube: SendTube, ) -> Self637*bb4ee6a4SAndroid Build Coastguard Worker     pub fn new(
638*bb4ee6a4SAndroid Build Coastguard Worker         pci_root: Arc<Mutex<PciRoot>>,
639*bb4ee6a4SAndroid Build Coastguard Worker         break_linux_pci_config_io: bool,
640*bb4ee6a4SAndroid Build Coastguard Worker         reset_evt_wrtube: SendTube,
641*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Self {
642*bb4ee6a4SAndroid Build Coastguard Worker         PciConfigIo {
643*bb4ee6a4SAndroid Build Coastguard Worker             pci_root,
644*bb4ee6a4SAndroid Build Coastguard Worker             config_address: 0,
645*bb4ee6a4SAndroid Build Coastguard Worker             break_linux_pci_config_io,
646*bb4ee6a4SAndroid Build Coastguard Worker             reset_evt_wrtube,
647*bb4ee6a4SAndroid Build Coastguard Worker         }
648*bb4ee6a4SAndroid Build Coastguard Worker     }
649*bb4ee6a4SAndroid Build Coastguard Worker 
config_space_read(&self) -> u32650*bb4ee6a4SAndroid Build Coastguard Worker     fn config_space_read(&self) -> u32 {
651*bb4ee6a4SAndroid Build Coastguard Worker         let enabled = (self.config_address & 0x8000_0000) != 0;
652*bb4ee6a4SAndroid Build Coastguard Worker         if !enabled {
653*bb4ee6a4SAndroid Build Coastguard Worker             return 0xffff_ffff;
654*bb4ee6a4SAndroid Build Coastguard Worker         }
655*bb4ee6a4SAndroid Build Coastguard Worker 
656*bb4ee6a4SAndroid Build Coastguard Worker         let (address, register) =
657*bb4ee6a4SAndroid Build Coastguard Worker             PciAddress::from_config_address(self.config_address, Self::REGISTER_BITS_NUM);
658*bb4ee6a4SAndroid Build Coastguard Worker         self.pci_root.lock().config_space_read(address, register)
659*bb4ee6a4SAndroid Build Coastguard Worker     }
660*bb4ee6a4SAndroid Build Coastguard Worker 
config_space_write(&mut self, offset: u64, data: &[u8])661*bb4ee6a4SAndroid Build Coastguard Worker     fn config_space_write(&mut self, offset: u64, data: &[u8]) {
662*bb4ee6a4SAndroid Build Coastguard Worker         let enabled = (self.config_address & 0x8000_0000) != 0;
663*bb4ee6a4SAndroid Build Coastguard Worker         if !enabled {
664*bb4ee6a4SAndroid Build Coastguard Worker             return;
665*bb4ee6a4SAndroid Build Coastguard Worker         }
666*bb4ee6a4SAndroid Build Coastguard Worker 
667*bb4ee6a4SAndroid Build Coastguard Worker         let (address, register) =
668*bb4ee6a4SAndroid Build Coastguard Worker             PciAddress::from_config_address(self.config_address, Self::REGISTER_BITS_NUM);
669*bb4ee6a4SAndroid Build Coastguard Worker         self.pci_root
670*bb4ee6a4SAndroid Build Coastguard Worker             .lock()
671*bb4ee6a4SAndroid Build Coastguard Worker             .config_space_write(address, register, offset, data)
672*bb4ee6a4SAndroid Build Coastguard Worker     }
673*bb4ee6a4SAndroid Build Coastguard Worker 
set_config_address(&mut self, offset: u64, data: &[u8])674*bb4ee6a4SAndroid Build Coastguard Worker     fn set_config_address(&mut self, offset: u64, data: &[u8]) {
675*bb4ee6a4SAndroid Build Coastguard Worker         if offset as usize + data.len() > 4 {
676*bb4ee6a4SAndroid Build Coastguard Worker             return;
677*bb4ee6a4SAndroid Build Coastguard Worker         }
678*bb4ee6a4SAndroid Build Coastguard Worker         let (mask, value): (u32, u32) = match data.len() {
679*bb4ee6a4SAndroid Build Coastguard Worker             1 => (
680*bb4ee6a4SAndroid Build Coastguard Worker                 0x0000_00ff << (offset * 8),
681*bb4ee6a4SAndroid Build Coastguard Worker                 (data[0] as u32) << (offset * 8),
682*bb4ee6a4SAndroid Build Coastguard Worker             ),
683*bb4ee6a4SAndroid Build Coastguard Worker             2 => (
684*bb4ee6a4SAndroid Build Coastguard Worker                 0x0000_ffff << (offset * 8),
685*bb4ee6a4SAndroid Build Coastguard Worker                 u32::from(u16::from_le_bytes(data.try_into().unwrap())) << (offset * 8),
686*bb4ee6a4SAndroid Build Coastguard Worker             ),
687*bb4ee6a4SAndroid Build Coastguard Worker             4 => (0xffff_ffff, u32::from_le_bytes(data.try_into().unwrap())),
688*bb4ee6a4SAndroid Build Coastguard Worker             _ => return,
689*bb4ee6a4SAndroid Build Coastguard Worker         };
690*bb4ee6a4SAndroid Build Coastguard Worker         self.config_address = (self.config_address & !mask) | value;
691*bb4ee6a4SAndroid Build Coastguard Worker     }
692*bb4ee6a4SAndroid Build Coastguard Worker }
693*bb4ee6a4SAndroid Build Coastguard Worker 
694*bb4ee6a4SAndroid Build Coastguard Worker const PCI_RESET_CPU_BIT: u8 = 1 << 2;
695*bb4ee6a4SAndroid Build Coastguard Worker 
696*bb4ee6a4SAndroid Build Coastguard Worker impl BusDevice for PciConfigIo {
debug_label(&self) -> String697*bb4ee6a4SAndroid Build Coastguard Worker     fn debug_label(&self) -> String {
698*bb4ee6a4SAndroid Build Coastguard Worker         "pci config io-port".to_string()
699*bb4ee6a4SAndroid Build Coastguard Worker     }
700*bb4ee6a4SAndroid Build Coastguard Worker 
device_id(&self) -> DeviceId701*bb4ee6a4SAndroid Build Coastguard Worker     fn device_id(&self) -> DeviceId {
702*bb4ee6a4SAndroid Build Coastguard Worker         PciId::new(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441).into()
703*bb4ee6a4SAndroid Build Coastguard Worker     }
704*bb4ee6a4SAndroid Build Coastguard Worker 
read(&mut self, info: BusAccessInfo, data: &mut [u8])705*bb4ee6a4SAndroid Build Coastguard Worker     fn read(&mut self, info: BusAccessInfo, data: &mut [u8]) {
706*bb4ee6a4SAndroid Build Coastguard Worker         if self.break_linux_pci_config_io {
707*bb4ee6a4SAndroid Build Coastguard Worker             for d in data {
708*bb4ee6a4SAndroid Build Coastguard Worker                 *d = 0xff;
709*bb4ee6a4SAndroid Build Coastguard Worker             }
710*bb4ee6a4SAndroid Build Coastguard Worker             return;
711*bb4ee6a4SAndroid Build Coastguard Worker         }
712*bb4ee6a4SAndroid Build Coastguard Worker         // `offset` is relative to 0xcf8
713*bb4ee6a4SAndroid Build Coastguard Worker         let value = match info.offset {
714*bb4ee6a4SAndroid Build Coastguard Worker             0..=3 => self.config_address,
715*bb4ee6a4SAndroid Build Coastguard Worker             4..=7 => self.config_space_read(),
716*bb4ee6a4SAndroid Build Coastguard Worker             _ => 0xffff_ffff,
717*bb4ee6a4SAndroid Build Coastguard Worker         };
718*bb4ee6a4SAndroid Build Coastguard Worker 
719*bb4ee6a4SAndroid Build Coastguard Worker         // Only allow reads to the register boundary.
720*bb4ee6a4SAndroid Build Coastguard Worker         let start = info.offset as usize % 4;
721*bb4ee6a4SAndroid Build Coastguard Worker         let end = start + data.len();
722*bb4ee6a4SAndroid Build Coastguard Worker         if end <= 4 {
723*bb4ee6a4SAndroid Build Coastguard Worker             for i in start..end {
724*bb4ee6a4SAndroid Build Coastguard Worker                 data[i - start] = (value >> (i * 8)) as u8;
725*bb4ee6a4SAndroid Build Coastguard Worker             }
726*bb4ee6a4SAndroid Build Coastguard Worker         } else {
727*bb4ee6a4SAndroid Build Coastguard Worker             for d in data {
728*bb4ee6a4SAndroid Build Coastguard Worker                 *d = 0xff;
729*bb4ee6a4SAndroid Build Coastguard Worker             }
730*bb4ee6a4SAndroid Build Coastguard Worker         }
731*bb4ee6a4SAndroid Build Coastguard Worker     }
732*bb4ee6a4SAndroid Build Coastguard Worker 
write(&mut self, info: BusAccessInfo, data: &[u8])733*bb4ee6a4SAndroid Build Coastguard Worker     fn write(&mut self, info: BusAccessInfo, data: &[u8]) {
734*bb4ee6a4SAndroid Build Coastguard Worker         // `offset` is relative to 0xcf8
735*bb4ee6a4SAndroid Build Coastguard Worker         match info.offset {
736*bb4ee6a4SAndroid Build Coastguard Worker             _o @ 1 if data.len() == 1 && data[0] & PCI_RESET_CPU_BIT != 0 => {
737*bb4ee6a4SAndroid Build Coastguard Worker                 if let Err(e) = self
738*bb4ee6a4SAndroid Build Coastguard Worker                     .reset_evt_wrtube
739*bb4ee6a4SAndroid Build Coastguard Worker                     .send::<VmEventType>(&VmEventType::Reset)
740*bb4ee6a4SAndroid Build Coastguard Worker                 {
741*bb4ee6a4SAndroid Build Coastguard Worker                     error!("failed to trigger PCI 0xcf9 reset event: {}", e);
742*bb4ee6a4SAndroid Build Coastguard Worker                 }
743*bb4ee6a4SAndroid Build Coastguard Worker             }
744*bb4ee6a4SAndroid Build Coastguard Worker             o @ 0..=3 => self.set_config_address(o, data),
745*bb4ee6a4SAndroid Build Coastguard Worker             o @ 4..=7 => self.config_space_write(o - 4, data),
746*bb4ee6a4SAndroid Build Coastguard Worker             _ => (),
747*bb4ee6a4SAndroid Build Coastguard Worker         };
748*bb4ee6a4SAndroid Build Coastguard Worker     }
749*bb4ee6a4SAndroid Build Coastguard Worker }
750*bb4ee6a4SAndroid Build Coastguard Worker 
751*bb4ee6a4SAndroid Build Coastguard Worker impl Suspendable for PciConfigIo {
752*bb4ee6a4SAndroid Build Coastguard Worker     // no thread to sleep, no change required.
sleep(&mut self) -> anyhow::Result<()>753*bb4ee6a4SAndroid Build Coastguard Worker     fn sleep(&mut self) -> anyhow::Result<()> {
754*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
755*bb4ee6a4SAndroid Build Coastguard Worker     }
756*bb4ee6a4SAndroid Build Coastguard Worker 
wake(&mut self) -> anyhow::Result<()>757*bb4ee6a4SAndroid Build Coastguard Worker     fn wake(&mut self) -> anyhow::Result<()> {
758*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
759*bb4ee6a4SAndroid Build Coastguard Worker     }
760*bb4ee6a4SAndroid Build Coastguard Worker 
snapshot(&mut self) -> anyhow::Result<serde_json::Value>761*bb4ee6a4SAndroid Build Coastguard Worker     fn snapshot(&mut self) -> anyhow::Result<serde_json::Value> {
762*bb4ee6a4SAndroid Build Coastguard Worker         serde_json::to_value(PciConfigIoSerializable {
763*bb4ee6a4SAndroid Build Coastguard Worker             pci_root: self
764*bb4ee6a4SAndroid Build Coastguard Worker                 .pci_root
765*bb4ee6a4SAndroid Build Coastguard Worker                 .lock()
766*bb4ee6a4SAndroid Build Coastguard Worker                 .snapshot()
767*bb4ee6a4SAndroid Build Coastguard Worker                 .context("failed to snapshot root")?,
768*bb4ee6a4SAndroid Build Coastguard Worker             config_address: self.config_address,
769*bb4ee6a4SAndroid Build Coastguard Worker         })
770*bb4ee6a4SAndroid Build Coastguard Worker         .with_context(|| format!("failed to serialize {}", self.debug_label()))
771*bb4ee6a4SAndroid Build Coastguard Worker     }
772*bb4ee6a4SAndroid Build Coastguard Worker 
restore(&mut self, data: serde_json::Value) -> anyhow::Result<()>773*bb4ee6a4SAndroid Build Coastguard Worker     fn restore(&mut self, data: serde_json::Value) -> anyhow::Result<()> {
774*bb4ee6a4SAndroid Build Coastguard Worker         let mut root = self.pci_root.lock();
775*bb4ee6a4SAndroid Build Coastguard Worker         let deser: PciConfigIoSerializable = serde_json::from_value(data)
776*bb4ee6a4SAndroid Build Coastguard Worker             .context(format!("failed to deserialize {}", self.debug_label()))?;
777*bb4ee6a4SAndroid Build Coastguard Worker         root.restore(deser.pci_root)?;
778*bb4ee6a4SAndroid Build Coastguard Worker         self.config_address = deser.config_address;
779*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
780*bb4ee6a4SAndroid Build Coastguard Worker     }
781*bb4ee6a4SAndroid Build Coastguard Worker }
782*bb4ee6a4SAndroid Build Coastguard Worker 
783*bb4ee6a4SAndroid Build Coastguard Worker /// Emulates PCI memory-mapped configuration access mechanism.
784*bb4ee6a4SAndroid Build Coastguard Worker pub struct PciConfigMmio {
785*bb4ee6a4SAndroid Build Coastguard Worker     /// PCI root bridge.
786*bb4ee6a4SAndroid Build Coastguard Worker     pci_root: Arc<Mutex<PciRoot>>,
787*bb4ee6a4SAndroid Build Coastguard Worker     /// Register bit number in config address.
788*bb4ee6a4SAndroid Build Coastguard Worker     register_bit_num: usize,
789*bb4ee6a4SAndroid Build Coastguard Worker }
790*bb4ee6a4SAndroid Build Coastguard Worker 
791*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Serialize, Deserialize)]
792*bb4ee6a4SAndroid Build Coastguard Worker struct PciConfigMmioSerializable {
793*bb4ee6a4SAndroid Build Coastguard Worker     pci_root: serde_json::Value,
794*bb4ee6a4SAndroid Build Coastguard Worker     register_bit_num: usize,
795*bb4ee6a4SAndroid Build Coastguard Worker }
796*bb4ee6a4SAndroid Build Coastguard Worker 
797*bb4ee6a4SAndroid Build Coastguard Worker impl PciConfigMmio {
new(pci_root: Arc<Mutex<PciRoot>>, register_bit_num: usize) -> Self798*bb4ee6a4SAndroid Build Coastguard Worker     pub fn new(pci_root: Arc<Mutex<PciRoot>>, register_bit_num: usize) -> Self {
799*bb4ee6a4SAndroid Build Coastguard Worker         PciConfigMmio {
800*bb4ee6a4SAndroid Build Coastguard Worker             pci_root,
801*bb4ee6a4SAndroid Build Coastguard Worker             register_bit_num,
802*bb4ee6a4SAndroid Build Coastguard Worker         }
803*bb4ee6a4SAndroid Build Coastguard Worker     }
804*bb4ee6a4SAndroid Build Coastguard Worker 
config_space_read(&self, config_address: u32) -> u32805*bb4ee6a4SAndroid Build Coastguard Worker     fn config_space_read(&self, config_address: u32) -> u32 {
806*bb4ee6a4SAndroid Build Coastguard Worker         let (address, register) =
807*bb4ee6a4SAndroid Build Coastguard Worker             PciAddress::from_config_address(config_address, self.register_bit_num);
808*bb4ee6a4SAndroid Build Coastguard Worker         self.pci_root.lock().config_space_read(address, register)
809*bb4ee6a4SAndroid Build Coastguard Worker     }
810*bb4ee6a4SAndroid Build Coastguard Worker 
config_space_write(&mut self, config_address: u32, offset: u64, data: &[u8])811*bb4ee6a4SAndroid Build Coastguard Worker     fn config_space_write(&mut self, config_address: u32, offset: u64, data: &[u8]) {
812*bb4ee6a4SAndroid Build Coastguard Worker         let (address, register) =
813*bb4ee6a4SAndroid Build Coastguard Worker             PciAddress::from_config_address(config_address, self.register_bit_num);
814*bb4ee6a4SAndroid Build Coastguard Worker         self.pci_root
815*bb4ee6a4SAndroid Build Coastguard Worker             .lock()
816*bb4ee6a4SAndroid Build Coastguard Worker             .config_space_write(address, register, offset, data)
817*bb4ee6a4SAndroid Build Coastguard Worker     }
818*bb4ee6a4SAndroid Build Coastguard Worker }
819*bb4ee6a4SAndroid Build Coastguard Worker 
820*bb4ee6a4SAndroid Build Coastguard Worker impl BusDevice for PciConfigMmio {
debug_label(&self) -> String821*bb4ee6a4SAndroid Build Coastguard Worker     fn debug_label(&self) -> String {
822*bb4ee6a4SAndroid Build Coastguard Worker         "pci config mmio".to_owned()
823*bb4ee6a4SAndroid Build Coastguard Worker     }
824*bb4ee6a4SAndroid Build Coastguard Worker 
device_id(&self) -> DeviceId825*bb4ee6a4SAndroid Build Coastguard Worker     fn device_id(&self) -> DeviceId {
826*bb4ee6a4SAndroid Build Coastguard Worker         PciId::new(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441).into()
827*bb4ee6a4SAndroid Build Coastguard Worker     }
828*bb4ee6a4SAndroid Build Coastguard Worker 
read(&mut self, info: BusAccessInfo, data: &mut [u8])829*bb4ee6a4SAndroid Build Coastguard Worker     fn read(&mut self, info: BusAccessInfo, data: &mut [u8]) {
830*bb4ee6a4SAndroid Build Coastguard Worker         // Only allow reads to the register boundary.
831*bb4ee6a4SAndroid Build Coastguard Worker         let start = info.offset as usize % 4;
832*bb4ee6a4SAndroid Build Coastguard Worker         let end = start + data.len();
833*bb4ee6a4SAndroid Build Coastguard Worker         if end > 4 || info.offset > u32::MAX as u64 {
834*bb4ee6a4SAndroid Build Coastguard Worker             for d in data {
835*bb4ee6a4SAndroid Build Coastguard Worker                 *d = 0xff;
836*bb4ee6a4SAndroid Build Coastguard Worker             }
837*bb4ee6a4SAndroid Build Coastguard Worker             return;
838*bb4ee6a4SAndroid Build Coastguard Worker         }
839*bb4ee6a4SAndroid Build Coastguard Worker 
840*bb4ee6a4SAndroid Build Coastguard Worker         let value = self.config_space_read(info.offset as u32);
841*bb4ee6a4SAndroid Build Coastguard Worker         for i in start..end {
842*bb4ee6a4SAndroid Build Coastguard Worker             data[i - start] = (value >> (i * 8)) as u8;
843*bb4ee6a4SAndroid Build Coastguard Worker         }
844*bb4ee6a4SAndroid Build Coastguard Worker     }
845*bb4ee6a4SAndroid Build Coastguard Worker 
write(&mut self, info: BusAccessInfo, data: &[u8])846*bb4ee6a4SAndroid Build Coastguard Worker     fn write(&mut self, info: BusAccessInfo, data: &[u8]) {
847*bb4ee6a4SAndroid Build Coastguard Worker         if info.offset > u32::MAX as u64 {
848*bb4ee6a4SAndroid Build Coastguard Worker             return;
849*bb4ee6a4SAndroid Build Coastguard Worker         }
850*bb4ee6a4SAndroid Build Coastguard Worker         self.config_space_write(info.offset as u32, info.offset % 4, data)
851*bb4ee6a4SAndroid Build Coastguard Worker     }
852*bb4ee6a4SAndroid Build Coastguard Worker }
853*bb4ee6a4SAndroid Build Coastguard Worker 
854*bb4ee6a4SAndroid Build Coastguard Worker impl Suspendable for PciConfigMmio {
855*bb4ee6a4SAndroid Build Coastguard Worker     // no thread to sleep, no change required.
sleep(&mut self) -> anyhow::Result<()>856*bb4ee6a4SAndroid Build Coastguard Worker     fn sleep(&mut self) -> anyhow::Result<()> {
857*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
858*bb4ee6a4SAndroid Build Coastguard Worker     }
859*bb4ee6a4SAndroid Build Coastguard Worker 
wake(&mut self) -> anyhow::Result<()>860*bb4ee6a4SAndroid Build Coastguard Worker     fn wake(&mut self) -> anyhow::Result<()> {
861*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
862*bb4ee6a4SAndroid Build Coastguard Worker     }
863*bb4ee6a4SAndroid Build Coastguard Worker 
snapshot(&mut self) -> anyhow::Result<serde_json::Value>864*bb4ee6a4SAndroid Build Coastguard Worker     fn snapshot(&mut self) -> anyhow::Result<serde_json::Value> {
865*bb4ee6a4SAndroid Build Coastguard Worker         serde_json::to_value(PciConfigMmioSerializable {
866*bb4ee6a4SAndroid Build Coastguard Worker             pci_root: self
867*bb4ee6a4SAndroid Build Coastguard Worker                 .pci_root
868*bb4ee6a4SAndroid Build Coastguard Worker                 .lock()
869*bb4ee6a4SAndroid Build Coastguard Worker                 .snapshot()
870*bb4ee6a4SAndroid Build Coastguard Worker                 .context("failed to snapshot root")?,
871*bb4ee6a4SAndroid Build Coastguard Worker             register_bit_num: self.register_bit_num,
872*bb4ee6a4SAndroid Build Coastguard Worker         })
873*bb4ee6a4SAndroid Build Coastguard Worker         .with_context(|| format!("failed to serialize {}", self.debug_label()))
874*bb4ee6a4SAndroid Build Coastguard Worker     }
875*bb4ee6a4SAndroid Build Coastguard Worker 
restore(&mut self, data: serde_json::Value) -> anyhow::Result<()>876*bb4ee6a4SAndroid Build Coastguard Worker     fn restore(&mut self, data: serde_json::Value) -> anyhow::Result<()> {
877*bb4ee6a4SAndroid Build Coastguard Worker         let mut root = self.pci_root.lock();
878*bb4ee6a4SAndroid Build Coastguard Worker         let deser: PciConfigMmioSerializable = serde_json::from_value(data)
879*bb4ee6a4SAndroid Build Coastguard Worker             .context(format!("failed to deserialize {}", self.debug_label()))?;
880*bb4ee6a4SAndroid Build Coastguard Worker         root.restore(deser.pci_root)?;
881*bb4ee6a4SAndroid Build Coastguard Worker         self.register_bit_num = deser.register_bit_num;
882*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
883*bb4ee6a4SAndroid Build Coastguard Worker     }
884*bb4ee6a4SAndroid Build Coastguard Worker }
885*bb4ee6a4SAndroid Build Coastguard Worker 
886*bb4ee6a4SAndroid Build Coastguard Worker /// Inspired by PCI configuration space, CrosVM provides 2048 dword virtual registers (8KiB in
887*bb4ee6a4SAndroid Build Coastguard Worker /// total) for each PCI device. The guest can use these registers to exchange device-specific
888*bb4ee6a4SAndroid Build Coastguard Worker /// information with crosvm. The first 4kB is trapped by crosvm and crosvm supplies these
889*bb4ee6a4SAndroid Build Coastguard Worker /// register's emulation. The second 4KB is mapped into guest directly as shared memory, so
890*bb4ee6a4SAndroid Build Coastguard Worker /// when guest access this 4KB, vm exit doesn't happen.
891*bb4ee6a4SAndroid Build Coastguard Worker /// All these virtual registers from all PCI devices locate in a contiguous memory region.
892*bb4ee6a4SAndroid Build Coastguard Worker /// The base address of this memory region is provided by an IntObj named VCFG in the ACPI DSDT.
893*bb4ee6a4SAndroid Build Coastguard Worker /// Bit 12 is used to select the first trapped page or the second directly mapped page
894*bb4ee6a4SAndroid Build Coastguard Worker /// The offset of each register is calculated in the same way as PCIe ECAM;
895*bb4ee6a4SAndroid Build Coastguard Worker /// i.e. offset = (bus << 21) | (device << 16) | (function << 13) | (page_select << 12) |
896*bb4ee6a4SAndroid Build Coastguard Worker /// (register_index << 2)
897*bb4ee6a4SAndroid Build Coastguard Worker pub struct PciVirtualConfigMmio {
898*bb4ee6a4SAndroid Build Coastguard Worker     /// PCI root bridge.
899*bb4ee6a4SAndroid Build Coastguard Worker     pci_root: Arc<Mutex<PciRoot>>,
900*bb4ee6a4SAndroid Build Coastguard Worker     /// Register bit number in config address.
901*bb4ee6a4SAndroid Build Coastguard Worker     register_bit_num: usize,
902*bb4ee6a4SAndroid Build Coastguard Worker }
903*bb4ee6a4SAndroid Build Coastguard Worker 
904*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Serialize, Deserialize)]
905*bb4ee6a4SAndroid Build Coastguard Worker struct PciVirtualConfigMmioSerializable {
906*bb4ee6a4SAndroid Build Coastguard Worker     pci_root: serde_json::Value,
907*bb4ee6a4SAndroid Build Coastguard Worker     register_bit_num: usize,
908*bb4ee6a4SAndroid Build Coastguard Worker }
909*bb4ee6a4SAndroid Build Coastguard Worker 
910*bb4ee6a4SAndroid Build Coastguard Worker impl PciVirtualConfigMmio {
new(pci_root: Arc<Mutex<PciRoot>>, register_bit_num: usize) -> Self911*bb4ee6a4SAndroid Build Coastguard Worker     pub fn new(pci_root: Arc<Mutex<PciRoot>>, register_bit_num: usize) -> Self {
912*bb4ee6a4SAndroid Build Coastguard Worker         PciVirtualConfigMmio {
913*bb4ee6a4SAndroid Build Coastguard Worker             pci_root,
914*bb4ee6a4SAndroid Build Coastguard Worker             register_bit_num,
915*bb4ee6a4SAndroid Build Coastguard Worker         }
916*bb4ee6a4SAndroid Build Coastguard Worker     }
917*bb4ee6a4SAndroid Build Coastguard Worker }
918*bb4ee6a4SAndroid Build Coastguard Worker 
919*bb4ee6a4SAndroid Build Coastguard Worker impl BusDevice for PciVirtualConfigMmio {
debug_label(&self) -> String920*bb4ee6a4SAndroid Build Coastguard Worker     fn debug_label(&self) -> String {
921*bb4ee6a4SAndroid Build Coastguard Worker         "pci virtual config mmio".to_owned()
922*bb4ee6a4SAndroid Build Coastguard Worker     }
923*bb4ee6a4SAndroid Build Coastguard Worker 
device_id(&self) -> DeviceId924*bb4ee6a4SAndroid Build Coastguard Worker     fn device_id(&self) -> DeviceId {
925*bb4ee6a4SAndroid Build Coastguard Worker         PciId::new(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441).into()
926*bb4ee6a4SAndroid Build Coastguard Worker     }
927*bb4ee6a4SAndroid Build Coastguard Worker 
read(&mut self, info: BusAccessInfo, data: &mut [u8])928*bb4ee6a4SAndroid Build Coastguard Worker     fn read(&mut self, info: BusAccessInfo, data: &mut [u8]) {
929*bb4ee6a4SAndroid Build Coastguard Worker         let value = if info.offset % 4 != 0 || data.len() != 4 {
930*bb4ee6a4SAndroid Build Coastguard Worker             error!(
931*bb4ee6a4SAndroid Build Coastguard Worker                 "{} unexpected read at offset = {}, len = {}",
932*bb4ee6a4SAndroid Build Coastguard Worker                 self.debug_label(),
933*bb4ee6a4SAndroid Build Coastguard Worker                 info.offset,
934*bb4ee6a4SAndroid Build Coastguard Worker                 data.len()
935*bb4ee6a4SAndroid Build Coastguard Worker             );
936*bb4ee6a4SAndroid Build Coastguard Worker             0u32
937*bb4ee6a4SAndroid Build Coastguard Worker         } else {
938*bb4ee6a4SAndroid Build Coastguard Worker             let (address, register) =
939*bb4ee6a4SAndroid Build Coastguard Worker                 PciAddress::from_config_address(info.offset as u32, self.register_bit_num);
940*bb4ee6a4SAndroid Build Coastguard Worker             self.pci_root
941*bb4ee6a4SAndroid Build Coastguard Worker                 .lock()
942*bb4ee6a4SAndroid Build Coastguard Worker                 .virtual_config_space_read(address, register)
943*bb4ee6a4SAndroid Build Coastguard Worker         };
944*bb4ee6a4SAndroid Build Coastguard Worker         data[0..4].copy_from_slice(&value.to_le_bytes()[..]);
945*bb4ee6a4SAndroid Build Coastguard Worker     }
946*bb4ee6a4SAndroid Build Coastguard Worker 
write(&mut self, info: BusAccessInfo, data: &[u8])947*bb4ee6a4SAndroid Build Coastguard Worker     fn write(&mut self, info: BusAccessInfo, data: &[u8]) {
948*bb4ee6a4SAndroid Build Coastguard Worker         if info.offset % 4 != 0 || data.len() != 4 {
949*bb4ee6a4SAndroid Build Coastguard Worker             error!(
950*bb4ee6a4SAndroid Build Coastguard Worker                 "{} unexpected write at offset = {}, len = {}",
951*bb4ee6a4SAndroid Build Coastguard Worker                 self.debug_label(),
952*bb4ee6a4SAndroid Build Coastguard Worker                 info.offset,
953*bb4ee6a4SAndroid Build Coastguard Worker                 data.len()
954*bb4ee6a4SAndroid Build Coastguard Worker             );
955*bb4ee6a4SAndroid Build Coastguard Worker             return;
956*bb4ee6a4SAndroid Build Coastguard Worker         }
957*bb4ee6a4SAndroid Build Coastguard Worker         // Unwrap is safe as we verified length above
958*bb4ee6a4SAndroid Build Coastguard Worker         let value = u32::from_le_bytes(data.try_into().unwrap());
959*bb4ee6a4SAndroid Build Coastguard Worker         let (address, register) =
960*bb4ee6a4SAndroid Build Coastguard Worker             PciAddress::from_config_address(info.offset as u32, self.register_bit_num);
961*bb4ee6a4SAndroid Build Coastguard Worker         self.pci_root
962*bb4ee6a4SAndroid Build Coastguard Worker             .lock()
963*bb4ee6a4SAndroid Build Coastguard Worker             .virtual_config_space_write(address, register, value)
964*bb4ee6a4SAndroid Build Coastguard Worker     }
965*bb4ee6a4SAndroid Build Coastguard Worker }
966*bb4ee6a4SAndroid Build Coastguard Worker 
967*bb4ee6a4SAndroid Build Coastguard Worker impl Suspendable for PciVirtualConfigMmio {
968*bb4ee6a4SAndroid Build Coastguard Worker     // no thread to sleep, no change required.
sleep(&mut self) -> anyhow::Result<()>969*bb4ee6a4SAndroid Build Coastguard Worker     fn sleep(&mut self) -> anyhow::Result<()> {
970*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
971*bb4ee6a4SAndroid Build Coastguard Worker     }
972*bb4ee6a4SAndroid Build Coastguard Worker 
wake(&mut self) -> anyhow::Result<()>973*bb4ee6a4SAndroid Build Coastguard Worker     fn wake(&mut self) -> anyhow::Result<()> {
974*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
975*bb4ee6a4SAndroid Build Coastguard Worker     }
976*bb4ee6a4SAndroid Build Coastguard Worker 
snapshot(&mut self) -> anyhow::Result<serde_json::Value>977*bb4ee6a4SAndroid Build Coastguard Worker     fn snapshot(&mut self) -> anyhow::Result<serde_json::Value> {
978*bb4ee6a4SAndroid Build Coastguard Worker         serde_json::to_value(PciVirtualConfigMmioSerializable {
979*bb4ee6a4SAndroid Build Coastguard Worker             pci_root: self
980*bb4ee6a4SAndroid Build Coastguard Worker                 .pci_root
981*bb4ee6a4SAndroid Build Coastguard Worker                 .lock()
982*bb4ee6a4SAndroid Build Coastguard Worker                 .snapshot()
983*bb4ee6a4SAndroid Build Coastguard Worker                 .context("failed to snapshot root")?,
984*bb4ee6a4SAndroid Build Coastguard Worker             register_bit_num: self.register_bit_num,
985*bb4ee6a4SAndroid Build Coastguard Worker         })
986*bb4ee6a4SAndroid Build Coastguard Worker         .with_context(|| format!("failed to serialize {}", self.debug_label()))
987*bb4ee6a4SAndroid Build Coastguard Worker     }
988*bb4ee6a4SAndroid Build Coastguard Worker 
restore(&mut self, data: serde_json::Value) -> anyhow::Result<()>989*bb4ee6a4SAndroid Build Coastguard Worker     fn restore(&mut self, data: serde_json::Value) -> anyhow::Result<()> {
990*bb4ee6a4SAndroid Build Coastguard Worker         let mut root = self.pci_root.lock();
991*bb4ee6a4SAndroid Build Coastguard Worker         let deser: PciVirtualConfigMmioSerializable = serde_json::from_value(data)
992*bb4ee6a4SAndroid Build Coastguard Worker             .context(format!("failed to deserialize {}", self.debug_label()))?;
993*bb4ee6a4SAndroid Build Coastguard Worker         root.restore(deser.pci_root)?;
994*bb4ee6a4SAndroid Build Coastguard Worker         self.register_bit_num = deser.register_bit_num;
995*bb4ee6a4SAndroid Build Coastguard Worker 
996*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
997*bb4ee6a4SAndroid Build Coastguard Worker     }
998*bb4ee6a4SAndroid Build Coastguard Worker }
999*bb4ee6a4SAndroid Build Coastguard Worker 
1000*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(test)]
1001*bb4ee6a4SAndroid Build Coastguard Worker mod tests {
1002*bb4ee6a4SAndroid Build Coastguard Worker     use base::Tube;
1003*bb4ee6a4SAndroid Build Coastguard Worker 
1004*bb4ee6a4SAndroid Build Coastguard Worker     use super::*;
1005*bb4ee6a4SAndroid Build Coastguard Worker     use crate::suspendable_tests;
1006*bb4ee6a4SAndroid Build Coastguard Worker 
create_pci_root() -> Arc<Mutex<PciRoot>>1007*bb4ee6a4SAndroid Build Coastguard Worker     fn create_pci_root() -> Arc<Mutex<PciRoot>> {
1008*bb4ee6a4SAndroid Build Coastguard Worker         let io_bus = Arc::new(Bus::new(BusType::Io));
1009*bb4ee6a4SAndroid Build Coastguard Worker         let mmio_bus = Arc::new(Bus::new(BusType::Mmio));
1010*bb4ee6a4SAndroid Build Coastguard Worker         let root_bus = Arc::new(Mutex::new(PciBus::new(0, 0, false)));
1011*bb4ee6a4SAndroid Build Coastguard Worker 
1012*bb4ee6a4SAndroid Build Coastguard Worker         Arc::new(Mutex::new(PciRoot::create_for_test(
1013*bb4ee6a4SAndroid Build Coastguard Worker             Arc::downgrade(&mmio_bus),
1014*bb4ee6a4SAndroid Build Coastguard Worker             GuestAddress(0),
1015*bb4ee6a4SAndroid Build Coastguard Worker             0,
1016*bb4ee6a4SAndroid Build Coastguard Worker             Arc::downgrade(&io_bus),
1017*bb4ee6a4SAndroid Build Coastguard Worker             root_bus,
1018*bb4ee6a4SAndroid Build Coastguard Worker         )))
1019*bb4ee6a4SAndroid Build Coastguard Worker     }
1020*bb4ee6a4SAndroid Build Coastguard Worker 
create_pci_io_config(pci_root: Arc<Mutex<PciRoot>>) -> PciConfigIo1021*bb4ee6a4SAndroid Build Coastguard Worker     fn create_pci_io_config(pci_root: Arc<Mutex<PciRoot>>) -> PciConfigIo {
1022*bb4ee6a4SAndroid Build Coastguard Worker         let (reset_evt_wrtube, _) = Tube::directional_pair().unwrap();
1023*bb4ee6a4SAndroid Build Coastguard Worker         PciConfigIo::new(pci_root, false, reset_evt_wrtube)
1024*bb4ee6a4SAndroid Build Coastguard Worker     }
1025*bb4ee6a4SAndroid Build Coastguard Worker 
modify_pci_io_config(pci_config: &mut PciConfigIo)1026*bb4ee6a4SAndroid Build Coastguard Worker     fn modify_pci_io_config(pci_config: &mut PciConfigIo) {
1027*bb4ee6a4SAndroid Build Coastguard Worker         pci_config.config_address += 1;
1028*bb4ee6a4SAndroid Build Coastguard Worker     }
create_pci_mmio_config(pci_root: Arc<Mutex<PciRoot>>) -> PciConfigMmio1029*bb4ee6a4SAndroid Build Coastguard Worker     fn create_pci_mmio_config(pci_root: Arc<Mutex<PciRoot>>) -> PciConfigMmio {
1030*bb4ee6a4SAndroid Build Coastguard Worker         PciConfigMmio::new(pci_root, 0)
1031*bb4ee6a4SAndroid Build Coastguard Worker     }
1032*bb4ee6a4SAndroid Build Coastguard Worker 
modify_pci_mmio_config(pci_config: &mut PciConfigMmio)1033*bb4ee6a4SAndroid Build Coastguard Worker     fn modify_pci_mmio_config(pci_config: &mut PciConfigMmio) {
1034*bb4ee6a4SAndroid Build Coastguard Worker         pci_config.register_bit_num += 1;
1035*bb4ee6a4SAndroid Build Coastguard Worker     }
1036*bb4ee6a4SAndroid Build Coastguard Worker 
create_pci_virtual_config_mmio(pci_root: Arc<Mutex<PciRoot>>) -> PciVirtualConfigMmio1037*bb4ee6a4SAndroid Build Coastguard Worker     fn create_pci_virtual_config_mmio(pci_root: Arc<Mutex<PciRoot>>) -> PciVirtualConfigMmio {
1038*bb4ee6a4SAndroid Build Coastguard Worker         PciVirtualConfigMmio::new(pci_root, 0)
1039*bb4ee6a4SAndroid Build Coastguard Worker     }
1040*bb4ee6a4SAndroid Build Coastguard Worker 
modify_pci_virtual_config_mmio(pci_config: &mut PciVirtualConfigMmio)1041*bb4ee6a4SAndroid Build Coastguard Worker     fn modify_pci_virtual_config_mmio(pci_config: &mut PciVirtualConfigMmio) {
1042*bb4ee6a4SAndroid Build Coastguard Worker         pci_config.register_bit_num += 1;
1043*bb4ee6a4SAndroid Build Coastguard Worker     }
1044*bb4ee6a4SAndroid Build Coastguard Worker 
1045*bb4ee6a4SAndroid Build Coastguard Worker     suspendable_tests!(
1046*bb4ee6a4SAndroid Build Coastguard Worker         pci_io_config,
1047*bb4ee6a4SAndroid Build Coastguard Worker         create_pci_io_config(create_pci_root()),
1048*bb4ee6a4SAndroid Build Coastguard Worker         modify_pci_io_config
1049*bb4ee6a4SAndroid Build Coastguard Worker     );
1050*bb4ee6a4SAndroid Build Coastguard Worker     suspendable_tests!(
1051*bb4ee6a4SAndroid Build Coastguard Worker         pcie_mmio_config,
1052*bb4ee6a4SAndroid Build Coastguard Worker         create_pci_mmio_config(create_pci_root()),
1053*bb4ee6a4SAndroid Build Coastguard Worker         modify_pci_mmio_config
1054*bb4ee6a4SAndroid Build Coastguard Worker     );
1055*bb4ee6a4SAndroid Build Coastguard Worker     suspendable_tests!(
1056*bb4ee6a4SAndroid Build Coastguard Worker         pci_virtual_config_mmio,
1057*bb4ee6a4SAndroid Build Coastguard Worker         create_pci_virtual_config_mmio(create_pci_root()),
1058*bb4ee6a4SAndroid Build Coastguard Worker         modify_pci_virtual_config_mmio
1059*bb4ee6a4SAndroid Build Coastguard Worker     );
1060*bb4ee6a4SAndroid Build Coastguard Worker 
1061*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
pci_set_config_address_word()1062*bb4ee6a4SAndroid Build Coastguard Worker     fn pci_set_config_address_word() {
1063*bb4ee6a4SAndroid Build Coastguard Worker         let mut pci_io_config = create_pci_io_config(create_pci_root());
1064*bb4ee6a4SAndroid Build Coastguard Worker 
1065*bb4ee6a4SAndroid Build Coastguard Worker         // Set the full 32-bit config_address to a known value (0x11223344).
1066*bb4ee6a4SAndroid Build Coastguard Worker         pci_io_config.write(
1067*bb4ee6a4SAndroid Build Coastguard Worker             BusAccessInfo {
1068*bb4ee6a4SAndroid Build Coastguard Worker                 offset: 0,
1069*bb4ee6a4SAndroid Build Coastguard Worker                 address: 0xCF8,
1070*bb4ee6a4SAndroid Build Coastguard Worker                 id: 0,
1071*bb4ee6a4SAndroid Build Coastguard Worker             },
1072*bb4ee6a4SAndroid Build Coastguard Worker             &[0x44, 0x33, 0x22, 0x11],
1073*bb4ee6a4SAndroid Build Coastguard Worker         );
1074*bb4ee6a4SAndroid Build Coastguard Worker 
1075*bb4ee6a4SAndroid Build Coastguard Worker         // Overwrite the high 16 bits of config_address with 0x55AA (test for b/274366589).
1076*bb4ee6a4SAndroid Build Coastguard Worker         pci_io_config.write(
1077*bb4ee6a4SAndroid Build Coastguard Worker             BusAccessInfo {
1078*bb4ee6a4SAndroid Build Coastguard Worker                 offset: 2,
1079*bb4ee6a4SAndroid Build Coastguard Worker                 address: 0xCFA,
1080*bb4ee6a4SAndroid Build Coastguard Worker                 id: 0,
1081*bb4ee6a4SAndroid Build Coastguard Worker             },
1082*bb4ee6a4SAndroid Build Coastguard Worker             &[0xAA, 0x55],
1083*bb4ee6a4SAndroid Build Coastguard Worker         );
1084*bb4ee6a4SAndroid Build Coastguard Worker 
1085*bb4ee6a4SAndroid Build Coastguard Worker         // Verify config_address has the expected value (0x55AA3344).
1086*bb4ee6a4SAndroid Build Coastguard Worker         let mut config_address = [0u8; 4];
1087*bb4ee6a4SAndroid Build Coastguard Worker         pci_io_config.read(
1088*bb4ee6a4SAndroid Build Coastguard Worker             BusAccessInfo {
1089*bb4ee6a4SAndroid Build Coastguard Worker                 offset: 0,
1090*bb4ee6a4SAndroid Build Coastguard Worker                 address: 0xCF8,
1091*bb4ee6a4SAndroid Build Coastguard Worker                 id: 0,
1092*bb4ee6a4SAndroid Build Coastguard Worker             },
1093*bb4ee6a4SAndroid Build Coastguard Worker             &mut config_address,
1094*bb4ee6a4SAndroid Build Coastguard Worker         );
1095*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(config_address, [0x44, 0x33, 0xAA, 0x55]);
1096*bb4ee6a4SAndroid Build Coastguard Worker     }
1097*bb4ee6a4SAndroid Build Coastguard Worker }
1098