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