1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2021 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 //! Implements a stub PCI device. This can be used to put a device on the PCI bus that will 6*bb4ee6a4SAndroid Build Coastguard Worker //! show up in PCI device enumeration with the configured parameters. The device will otherwise be 7*bb4ee6a4SAndroid Build Coastguard Worker //! non-functional, in particular it doesn't have any BARs, IRQs etc. and neither will it handle 8*bb4ee6a4SAndroid Build Coastguard Worker //! config register interactions. 9*bb4ee6a4SAndroid Build Coastguard Worker //! 10*bb4ee6a4SAndroid Build Coastguard Worker //! The motivation for stub PCI devices is the case of multifunction PCI devices getting passed 11*bb4ee6a4SAndroid Build Coastguard Worker //! through via VFIO to the guest. Per PCI device enumeration, functions other than 0 will only be 12*bb4ee6a4SAndroid Build Coastguard Worker //! scanned if function 0 is present. A stub PCI device is useful in that situation to present 13*bb4ee6a4SAndroid Build Coastguard Worker //! something to the guest on function 0. 14*bb4ee6a4SAndroid Build Coastguard Worker 15*bb4ee6a4SAndroid Build Coastguard Worker use base::RawDescriptor; 16*bb4ee6a4SAndroid Build Coastguard Worker use resources::Alloc; 17*bb4ee6a4SAndroid Build Coastguard Worker use resources::SystemAllocator; 18*bb4ee6a4SAndroid Build Coastguard Worker use serde::Deserialize; 19*bb4ee6a4SAndroid Build Coastguard Worker use serde::Deserializer; 20*bb4ee6a4SAndroid Build Coastguard Worker use serde::Serialize; 21*bb4ee6a4SAndroid Build Coastguard Worker use serde::Serializer; 22*bb4ee6a4SAndroid Build Coastguard Worker 23*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::pci_configuration::PciBarConfiguration; 24*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::pci_configuration::PciClassCode; 25*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::pci_configuration::PciConfiguration; 26*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::pci_configuration::PciHeaderType; 27*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::pci_configuration::PciProgrammingInterface; 28*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::pci_configuration::PciSubclass; 29*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::pci_device::PciDevice; 30*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::pci_device::Result; 31*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::PciAddress; 32*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::PciBarIndex; 33*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::PciDeviceError; 34*bb4ee6a4SAndroid Build Coastguard Worker use crate::Suspendable; 35*bb4ee6a4SAndroid Build Coastguard Worker 36*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Debug)] 37*bb4ee6a4SAndroid Build Coastguard Worker pub struct PciClassParameters { 38*bb4ee6a4SAndroid Build Coastguard Worker pub class: PciClassCode, 39*bb4ee6a4SAndroid Build Coastguard Worker pub subclass: u8, 40*bb4ee6a4SAndroid Build Coastguard Worker pub programming_interface: u8, 41*bb4ee6a4SAndroid Build Coastguard Worker } 42*bb4ee6a4SAndroid Build Coastguard Worker 43*bb4ee6a4SAndroid Build Coastguard Worker impl Default for PciClassParameters { default() -> Self44*bb4ee6a4SAndroid Build Coastguard Worker fn default() -> Self { 45*bb4ee6a4SAndroid Build Coastguard Worker PciClassParameters { 46*bb4ee6a4SAndroid Build Coastguard Worker class: PciClassCode::Other, 47*bb4ee6a4SAndroid Build Coastguard Worker subclass: 0, 48*bb4ee6a4SAndroid Build Coastguard Worker programming_interface: 0, 49*bb4ee6a4SAndroid Build Coastguard Worker } 50*bb4ee6a4SAndroid Build Coastguard Worker } 51*bb4ee6a4SAndroid Build Coastguard Worker } 52*bb4ee6a4SAndroid Build Coastguard Worker 53*bb4ee6a4SAndroid Build Coastguard Worker // Deserialize the combined class, subclass, and programming interface as a single numeric value. 54*bb4ee6a4SAndroid Build Coastguard Worker // This matches the numeric format used in `/sys/bus/pci/devices/*/class`. 55*bb4ee6a4SAndroid Build Coastguard Worker impl<'de> Deserialize<'de> for PciClassParameters { deserialize<D>(deserializer: D) -> std::result::Result<PciClassParameters, D::Error> where D: Deserializer<'de>,56*bb4ee6a4SAndroid Build Coastguard Worker fn deserialize<D>(deserializer: D) -> std::result::Result<PciClassParameters, D::Error> 57*bb4ee6a4SAndroid Build Coastguard Worker where 58*bb4ee6a4SAndroid Build Coastguard Worker D: Deserializer<'de>, 59*bb4ee6a4SAndroid Build Coastguard Worker { 60*bb4ee6a4SAndroid Build Coastguard Worker let class_numeric = u32::deserialize(deserializer)?; 61*bb4ee6a4SAndroid Build Coastguard Worker 62*bb4ee6a4SAndroid Build Coastguard Worker let class_code = (class_numeric >> 16) as u8; 63*bb4ee6a4SAndroid Build Coastguard Worker let class = PciClassCode::try_from(class_code).map_err(|_| { 64*bb4ee6a4SAndroid Build Coastguard Worker serde::de::Error::custom(format!("Unknown class code {:#x}", class_code)) 65*bb4ee6a4SAndroid Build Coastguard Worker })?; 66*bb4ee6a4SAndroid Build Coastguard Worker 67*bb4ee6a4SAndroid Build Coastguard Worker let subclass = (class_numeric >> 8) as u8; 68*bb4ee6a4SAndroid Build Coastguard Worker 69*bb4ee6a4SAndroid Build Coastguard Worker let programming_interface = class_numeric as u8; 70*bb4ee6a4SAndroid Build Coastguard Worker 71*bb4ee6a4SAndroid Build Coastguard Worker Ok(PciClassParameters { 72*bb4ee6a4SAndroid Build Coastguard Worker class, 73*bb4ee6a4SAndroid Build Coastguard Worker subclass, 74*bb4ee6a4SAndroid Build Coastguard Worker programming_interface, 75*bb4ee6a4SAndroid Build Coastguard Worker }) 76*bb4ee6a4SAndroid Build Coastguard Worker } 77*bb4ee6a4SAndroid Build Coastguard Worker } 78*bb4ee6a4SAndroid Build Coastguard Worker 79*bb4ee6a4SAndroid Build Coastguard Worker impl Serialize for PciClassParameters { serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error> where S: Serializer,80*bb4ee6a4SAndroid Build Coastguard Worker fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error> 81*bb4ee6a4SAndroid Build Coastguard Worker where 82*bb4ee6a4SAndroid Build Coastguard Worker S: Serializer, 83*bb4ee6a4SAndroid Build Coastguard Worker { 84*bb4ee6a4SAndroid Build Coastguard Worker let class_numeric: u32 = ((self.class as u32) << 16) 85*bb4ee6a4SAndroid Build Coastguard Worker | ((self.subclass as u32) << 8) 86*bb4ee6a4SAndroid Build Coastguard Worker | self.programming_interface as u32; 87*bb4ee6a4SAndroid Build Coastguard Worker 88*bb4ee6a4SAndroid Build Coastguard Worker serializer.serialize_u32(class_numeric) 89*bb4ee6a4SAndroid Build Coastguard Worker } 90*bb4ee6a4SAndroid Build Coastguard Worker } 91*bb4ee6a4SAndroid Build Coastguard Worker 92*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Serialize, Deserialize, Debug, serde_keyvalue::FromKeyValues)] 93*bb4ee6a4SAndroid Build Coastguard Worker #[serde(deny_unknown_fields, rename_all = "kebab-case")] 94*bb4ee6a4SAndroid Build Coastguard Worker pub struct StubPciParameters { 95*bb4ee6a4SAndroid Build Coastguard Worker pub address: PciAddress, 96*bb4ee6a4SAndroid Build Coastguard Worker #[serde(default)] 97*bb4ee6a4SAndroid Build Coastguard Worker pub vendor: u16, 98*bb4ee6a4SAndroid Build Coastguard Worker #[serde(default)] 99*bb4ee6a4SAndroid Build Coastguard Worker pub device: u16, 100*bb4ee6a4SAndroid Build Coastguard Worker #[serde(default)] 101*bb4ee6a4SAndroid Build Coastguard Worker pub class: PciClassParameters, 102*bb4ee6a4SAndroid Build Coastguard Worker #[serde(default, alias = "subsystem_vendor")] 103*bb4ee6a4SAndroid Build Coastguard Worker pub subsystem_vendor: u16, 104*bb4ee6a4SAndroid Build Coastguard Worker #[serde(default, alias = "subsystem_device")] 105*bb4ee6a4SAndroid Build Coastguard Worker pub subsystem_device: u16, 106*bb4ee6a4SAndroid Build Coastguard Worker #[serde(default)] 107*bb4ee6a4SAndroid Build Coastguard Worker pub revision: u8, 108*bb4ee6a4SAndroid Build Coastguard Worker } 109*bb4ee6a4SAndroid Build Coastguard Worker 110*bb4ee6a4SAndroid Build Coastguard Worker pub struct StubPciDevice { 111*bb4ee6a4SAndroid Build Coastguard Worker requested_address: PciAddress, 112*bb4ee6a4SAndroid Build Coastguard Worker assigned_address: Option<PciAddress>, 113*bb4ee6a4SAndroid Build Coastguard Worker config_regs: PciConfiguration, 114*bb4ee6a4SAndroid Build Coastguard Worker } 115*bb4ee6a4SAndroid Build Coastguard Worker 116*bb4ee6a4SAndroid Build Coastguard Worker struct NumericPciSubClass(u8); 117*bb4ee6a4SAndroid Build Coastguard Worker 118*bb4ee6a4SAndroid Build Coastguard Worker impl PciSubclass for NumericPciSubClass { get_register_value(&self) -> u8119*bb4ee6a4SAndroid Build Coastguard Worker fn get_register_value(&self) -> u8 { 120*bb4ee6a4SAndroid Build Coastguard Worker self.0 121*bb4ee6a4SAndroid Build Coastguard Worker } 122*bb4ee6a4SAndroid Build Coastguard Worker } 123*bb4ee6a4SAndroid Build Coastguard Worker 124*bb4ee6a4SAndroid Build Coastguard Worker struct NumericPciProgrammingInterface(u8); 125*bb4ee6a4SAndroid Build Coastguard Worker 126*bb4ee6a4SAndroid Build Coastguard Worker impl PciProgrammingInterface for NumericPciProgrammingInterface { get_register_value(&self) -> u8127*bb4ee6a4SAndroid Build Coastguard Worker fn get_register_value(&self) -> u8 { 128*bb4ee6a4SAndroid Build Coastguard Worker self.0 129*bb4ee6a4SAndroid Build Coastguard Worker } 130*bb4ee6a4SAndroid Build Coastguard Worker } 131*bb4ee6a4SAndroid Build Coastguard Worker 132*bb4ee6a4SAndroid Build Coastguard Worker impl StubPciDevice { new(config: &StubPciParameters) -> StubPciDevice133*bb4ee6a4SAndroid Build Coastguard Worker pub fn new(config: &StubPciParameters) -> StubPciDevice { 134*bb4ee6a4SAndroid Build Coastguard Worker let config_regs = PciConfiguration::new( 135*bb4ee6a4SAndroid Build Coastguard Worker config.vendor, 136*bb4ee6a4SAndroid Build Coastguard Worker config.device, 137*bb4ee6a4SAndroid Build Coastguard Worker config.class.class, 138*bb4ee6a4SAndroid Build Coastguard Worker &NumericPciSubClass(config.class.subclass), 139*bb4ee6a4SAndroid Build Coastguard Worker Some(&NumericPciProgrammingInterface( 140*bb4ee6a4SAndroid Build Coastguard Worker config.class.programming_interface, 141*bb4ee6a4SAndroid Build Coastguard Worker )), 142*bb4ee6a4SAndroid Build Coastguard Worker PciHeaderType::Device, 143*bb4ee6a4SAndroid Build Coastguard Worker config.subsystem_vendor, 144*bb4ee6a4SAndroid Build Coastguard Worker config.subsystem_device, 145*bb4ee6a4SAndroid Build Coastguard Worker config.revision, 146*bb4ee6a4SAndroid Build Coastguard Worker ); 147*bb4ee6a4SAndroid Build Coastguard Worker 148*bb4ee6a4SAndroid Build Coastguard Worker Self { 149*bb4ee6a4SAndroid Build Coastguard Worker requested_address: config.address, 150*bb4ee6a4SAndroid Build Coastguard Worker assigned_address: None, 151*bb4ee6a4SAndroid Build Coastguard Worker config_regs, 152*bb4ee6a4SAndroid Build Coastguard Worker } 153*bb4ee6a4SAndroid Build Coastguard Worker } 154*bb4ee6a4SAndroid Build Coastguard Worker } 155*bb4ee6a4SAndroid Build Coastguard Worker 156*bb4ee6a4SAndroid Build Coastguard Worker impl PciDevice for StubPciDevice { debug_label(&self) -> String157*bb4ee6a4SAndroid Build Coastguard Worker fn debug_label(&self) -> String { 158*bb4ee6a4SAndroid Build Coastguard Worker "Stub".to_owned() 159*bb4ee6a4SAndroid Build Coastguard Worker } 160*bb4ee6a4SAndroid Build Coastguard Worker preferred_address(&self) -> Option<PciAddress>161*bb4ee6a4SAndroid Build Coastguard Worker fn preferred_address(&self) -> Option<PciAddress> { 162*bb4ee6a4SAndroid Build Coastguard Worker Some(self.requested_address) 163*bb4ee6a4SAndroid Build Coastguard Worker } 164*bb4ee6a4SAndroid Build Coastguard Worker allocate_address(&mut self, resources: &mut SystemAllocator) -> Result<PciAddress>165*bb4ee6a4SAndroid Build Coastguard Worker fn allocate_address(&mut self, resources: &mut SystemAllocator) -> Result<PciAddress> { 166*bb4ee6a4SAndroid Build Coastguard Worker if self.assigned_address.is_none() { 167*bb4ee6a4SAndroid Build Coastguard Worker if resources.reserve_pci( 168*bb4ee6a4SAndroid Build Coastguard Worker Alloc::PciBar { 169*bb4ee6a4SAndroid Build Coastguard Worker bus: self.requested_address.bus, 170*bb4ee6a4SAndroid Build Coastguard Worker dev: self.requested_address.dev, 171*bb4ee6a4SAndroid Build Coastguard Worker func: self.requested_address.func, 172*bb4ee6a4SAndroid Build Coastguard Worker bar: 0, 173*bb4ee6a4SAndroid Build Coastguard Worker }, 174*bb4ee6a4SAndroid Build Coastguard Worker self.debug_label(), 175*bb4ee6a4SAndroid Build Coastguard Worker ) { 176*bb4ee6a4SAndroid Build Coastguard Worker self.assigned_address = Some(self.requested_address); 177*bb4ee6a4SAndroid Build Coastguard Worker } 178*bb4ee6a4SAndroid Build Coastguard Worker } 179*bb4ee6a4SAndroid Build Coastguard Worker self.assigned_address 180*bb4ee6a4SAndroid Build Coastguard Worker .ok_or(PciDeviceError::PciAllocationFailed) 181*bb4ee6a4SAndroid Build Coastguard Worker } 182*bb4ee6a4SAndroid Build Coastguard Worker keep_rds(&self) -> Vec<RawDescriptor>183*bb4ee6a4SAndroid Build Coastguard Worker fn keep_rds(&self) -> Vec<RawDescriptor> { 184*bb4ee6a4SAndroid Build Coastguard Worker Vec::new() 185*bb4ee6a4SAndroid Build Coastguard Worker } 186*bb4ee6a4SAndroid Build Coastguard Worker get_bar_configuration(&self, bar_num: usize) -> Option<PciBarConfiguration>187*bb4ee6a4SAndroid Build Coastguard Worker fn get_bar_configuration(&self, bar_num: usize) -> Option<PciBarConfiguration> { 188*bb4ee6a4SAndroid Build Coastguard Worker self.config_regs.get_bar_configuration(bar_num) 189*bb4ee6a4SAndroid Build Coastguard Worker } 190*bb4ee6a4SAndroid Build Coastguard Worker read_config_register(&self, reg_idx: usize) -> u32191*bb4ee6a4SAndroid Build Coastguard Worker fn read_config_register(&self, reg_idx: usize) -> u32 { 192*bb4ee6a4SAndroid Build Coastguard Worker self.config_regs.read_reg(reg_idx) 193*bb4ee6a4SAndroid Build Coastguard Worker } 194*bb4ee6a4SAndroid Build Coastguard Worker write_config_register(&mut self, reg_idx: usize, offset: u64, data: &[u8])195*bb4ee6a4SAndroid Build Coastguard Worker fn write_config_register(&mut self, reg_idx: usize, offset: u64, data: &[u8]) { 196*bb4ee6a4SAndroid Build Coastguard Worker self.config_regs.write_reg(reg_idx, offset, data); 197*bb4ee6a4SAndroid Build Coastguard Worker } 198*bb4ee6a4SAndroid Build Coastguard Worker read_bar(&mut self, _bar_index: PciBarIndex, _offset: u64, _data: &mut [u8])199*bb4ee6a4SAndroid Build Coastguard Worker fn read_bar(&mut self, _bar_index: PciBarIndex, _offset: u64, _data: &mut [u8]) {} 200*bb4ee6a4SAndroid Build Coastguard Worker write_bar(&mut self, _bar_index: PciBarIndex, _offset: u64, _data: &[u8])201*bb4ee6a4SAndroid Build Coastguard Worker fn write_bar(&mut self, _bar_index: PciBarIndex, _offset: u64, _data: &[u8]) {} 202*bb4ee6a4SAndroid Build Coastguard Worker } 203*bb4ee6a4SAndroid Build Coastguard Worker 204*bb4ee6a4SAndroid Build Coastguard Worker impl Suspendable for StubPciDevice { sleep(&mut self) -> anyhow::Result<()>205*bb4ee6a4SAndroid Build Coastguard Worker fn sleep(&mut self) -> anyhow::Result<()> { 206*bb4ee6a4SAndroid Build Coastguard Worker // There are no workers to sleep/wake. 207*bb4ee6a4SAndroid Build Coastguard Worker Ok(()) 208*bb4ee6a4SAndroid Build Coastguard Worker } 209*bb4ee6a4SAndroid Build Coastguard Worker wake(&mut self) -> anyhow::Result<()>210*bb4ee6a4SAndroid Build Coastguard Worker fn wake(&mut self) -> anyhow::Result<()> { 211*bb4ee6a4SAndroid Build Coastguard Worker // There are no workers to sleep/wake. 212*bb4ee6a4SAndroid Build Coastguard Worker Ok(()) 213*bb4ee6a4SAndroid Build Coastguard Worker } 214*bb4ee6a4SAndroid Build Coastguard Worker snapshot(&mut self) -> anyhow::Result<serde_json::Value>215*bb4ee6a4SAndroid Build Coastguard Worker fn snapshot(&mut self) -> anyhow::Result<serde_json::Value> { 216*bb4ee6a4SAndroid Build Coastguard Worker self.config_regs.snapshot() 217*bb4ee6a4SAndroid Build Coastguard Worker } 218*bb4ee6a4SAndroid Build Coastguard Worker restore(&mut self, data: serde_json::Value) -> anyhow::Result<()>219*bb4ee6a4SAndroid Build Coastguard Worker fn restore(&mut self, data: serde_json::Value) -> anyhow::Result<()> { 220*bb4ee6a4SAndroid Build Coastguard Worker self.config_regs.restore(data) 221*bb4ee6a4SAndroid Build Coastguard Worker } 222*bb4ee6a4SAndroid Build Coastguard Worker } 223*bb4ee6a4SAndroid Build Coastguard Worker 224*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(test)] 225*bb4ee6a4SAndroid Build Coastguard Worker mod test { 226*bb4ee6a4SAndroid Build Coastguard Worker use resources::AddressRange; 227*bb4ee6a4SAndroid Build Coastguard Worker use resources::SystemAllocator; 228*bb4ee6a4SAndroid Build Coastguard Worker use resources::SystemAllocatorConfig; 229*bb4ee6a4SAndroid Build Coastguard Worker use serde_keyvalue::from_key_values; 230*bb4ee6a4SAndroid Build Coastguard Worker use serde_keyvalue::ErrorKind; 231*bb4ee6a4SAndroid Build Coastguard Worker use serde_keyvalue::ParseError; 232*bb4ee6a4SAndroid Build Coastguard Worker 233*bb4ee6a4SAndroid Build Coastguard Worker use super::*; 234*bb4ee6a4SAndroid Build Coastguard Worker 235*bb4ee6a4SAndroid Build Coastguard Worker const CONFIG: StubPciParameters = StubPciParameters { 236*bb4ee6a4SAndroid Build Coastguard Worker address: PciAddress { 237*bb4ee6a4SAndroid Build Coastguard Worker bus: 0x0a, 238*bb4ee6a4SAndroid Build Coastguard Worker dev: 0x0b, 239*bb4ee6a4SAndroid Build Coastguard Worker func: 0x1, 240*bb4ee6a4SAndroid Build Coastguard Worker }, 241*bb4ee6a4SAndroid Build Coastguard Worker vendor: 2, 242*bb4ee6a4SAndroid Build Coastguard Worker device: 3, 243*bb4ee6a4SAndroid Build Coastguard Worker class: PciClassParameters { 244*bb4ee6a4SAndroid Build Coastguard Worker class: PciClassCode::MultimediaController, 245*bb4ee6a4SAndroid Build Coastguard Worker subclass: 5, 246*bb4ee6a4SAndroid Build Coastguard Worker programming_interface: 6, 247*bb4ee6a4SAndroid Build Coastguard Worker }, 248*bb4ee6a4SAndroid Build Coastguard Worker subsystem_vendor: 7, 249*bb4ee6a4SAndroid Build Coastguard Worker subsystem_device: 8, 250*bb4ee6a4SAndroid Build Coastguard Worker revision: 9, 251*bb4ee6a4SAndroid Build Coastguard Worker }; 252*bb4ee6a4SAndroid Build Coastguard Worker from_stub_arg(options: &str) -> std::result::Result<StubPciParameters, ParseError>253*bb4ee6a4SAndroid Build Coastguard Worker fn from_stub_arg(options: &str) -> std::result::Result<StubPciParameters, ParseError> { 254*bb4ee6a4SAndroid Build Coastguard Worker from_key_values(options) 255*bb4ee6a4SAndroid Build Coastguard Worker } 256*bb4ee6a4SAndroid Build Coastguard Worker 257*bb4ee6a4SAndroid Build Coastguard Worker #[test] configuration()258*bb4ee6a4SAndroid Build Coastguard Worker fn configuration() { 259*bb4ee6a4SAndroid Build Coastguard Worker let device = StubPciDevice::new(&CONFIG); 260*bb4ee6a4SAndroid Build Coastguard Worker 261*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(device.read_config_register(0), 0x0003_0002); 262*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(device.read_config_register(2), 0x04_05_06_09); 263*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(device.read_config_register(11), 0x0008_0007); 264*bb4ee6a4SAndroid Build Coastguard Worker } 265*bb4ee6a4SAndroid Build Coastguard Worker 266*bb4ee6a4SAndroid Build Coastguard Worker #[test] address_allocation()267*bb4ee6a4SAndroid Build Coastguard Worker fn address_allocation() { 268*bb4ee6a4SAndroid Build Coastguard Worker let mut allocator = SystemAllocator::new( 269*bb4ee6a4SAndroid Build Coastguard Worker SystemAllocatorConfig { 270*bb4ee6a4SAndroid Build Coastguard Worker io: Some(AddressRange { 271*bb4ee6a4SAndroid Build Coastguard Worker start: 0x1000, 272*bb4ee6a4SAndroid Build Coastguard Worker end: 0x2fff, 273*bb4ee6a4SAndroid Build Coastguard Worker }), 274*bb4ee6a4SAndroid Build Coastguard Worker low_mmio: AddressRange { 275*bb4ee6a4SAndroid Build Coastguard Worker start: 0x2000_0000, 276*bb4ee6a4SAndroid Build Coastguard Worker end: 0x2fff_ffff, 277*bb4ee6a4SAndroid Build Coastguard Worker }, 278*bb4ee6a4SAndroid Build Coastguard Worker high_mmio: AddressRange { 279*bb4ee6a4SAndroid Build Coastguard Worker start: 0x1_0000_0000, 280*bb4ee6a4SAndroid Build Coastguard Worker end: 0x1_0fff_ffff, 281*bb4ee6a4SAndroid Build Coastguard Worker }, 282*bb4ee6a4SAndroid Build Coastguard Worker platform_mmio: None, 283*bb4ee6a4SAndroid Build Coastguard Worker first_irq: 5, 284*bb4ee6a4SAndroid Build Coastguard Worker }, 285*bb4ee6a4SAndroid Build Coastguard Worker None, 286*bb4ee6a4SAndroid Build Coastguard Worker &[], 287*bb4ee6a4SAndroid Build Coastguard Worker ) 288*bb4ee6a4SAndroid Build Coastguard Worker .unwrap(); 289*bb4ee6a4SAndroid Build Coastguard Worker let mut device = StubPciDevice::new(&CONFIG); 290*bb4ee6a4SAndroid Build Coastguard Worker 291*bb4ee6a4SAndroid Build Coastguard Worker assert!(device.allocate_address(&mut allocator).is_ok()); 292*bb4ee6a4SAndroid Build Coastguard Worker assert!(allocator.release_pci(0xa, 0xb, 1)); 293*bb4ee6a4SAndroid Build Coastguard Worker } 294*bb4ee6a4SAndroid Build Coastguard Worker 295*bb4ee6a4SAndroid Build Coastguard Worker #[test] params_missing_address()296*bb4ee6a4SAndroid Build Coastguard Worker fn params_missing_address() { 297*bb4ee6a4SAndroid Build Coastguard Worker // PCI address argument is mandatory. 298*bb4ee6a4SAndroid Build Coastguard Worker let err = from_stub_arg("").unwrap_err(); 299*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!( 300*bb4ee6a4SAndroid Build Coastguard Worker err, 301*bb4ee6a4SAndroid Build Coastguard Worker ParseError { 302*bb4ee6a4SAndroid Build Coastguard Worker kind: ErrorKind::SerdeError("missing field `address`".into()), 303*bb4ee6a4SAndroid Build Coastguard Worker pos: 0, 304*bb4ee6a4SAndroid Build Coastguard Worker } 305*bb4ee6a4SAndroid Build Coastguard Worker ); 306*bb4ee6a4SAndroid Build Coastguard Worker } 307*bb4ee6a4SAndroid Build Coastguard Worker 308*bb4ee6a4SAndroid Build Coastguard Worker #[test] params_address_implicit()309*bb4ee6a4SAndroid Build Coastguard Worker fn params_address_implicit() { 310*bb4ee6a4SAndroid Build Coastguard Worker // Address is the default argument. 311*bb4ee6a4SAndroid Build Coastguard Worker let params = from_stub_arg("0000:00:01.2").unwrap(); 312*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!( 313*bb4ee6a4SAndroid Build Coastguard Worker params.address, 314*bb4ee6a4SAndroid Build Coastguard Worker PciAddress { 315*bb4ee6a4SAndroid Build Coastguard Worker bus: 0, 316*bb4ee6a4SAndroid Build Coastguard Worker dev: 1, 317*bb4ee6a4SAndroid Build Coastguard Worker func: 2 318*bb4ee6a4SAndroid Build Coastguard Worker } 319*bb4ee6a4SAndroid Build Coastguard Worker ); 320*bb4ee6a4SAndroid Build Coastguard Worker } 321*bb4ee6a4SAndroid Build Coastguard Worker 322*bb4ee6a4SAndroid Build Coastguard Worker #[test] params_address_explicit()323*bb4ee6a4SAndroid Build Coastguard Worker fn params_address_explicit() { 324*bb4ee6a4SAndroid Build Coastguard Worker // Explicitly-specified address. 325*bb4ee6a4SAndroid Build Coastguard Worker let params = from_stub_arg("address=0000:00:01.2").unwrap(); 326*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!( 327*bb4ee6a4SAndroid Build Coastguard Worker params.address, 328*bb4ee6a4SAndroid Build Coastguard Worker PciAddress { 329*bb4ee6a4SAndroid Build Coastguard Worker bus: 0, 330*bb4ee6a4SAndroid Build Coastguard Worker dev: 1, 331*bb4ee6a4SAndroid Build Coastguard Worker func: 2 332*bb4ee6a4SAndroid Build Coastguard Worker } 333*bb4ee6a4SAndroid Build Coastguard Worker ); 334*bb4ee6a4SAndroid Build Coastguard Worker } 335*bb4ee6a4SAndroid Build Coastguard Worker 336*bb4ee6a4SAndroid Build Coastguard Worker #[test] params_class()337*bb4ee6a4SAndroid Build Coastguard Worker fn params_class() { 338*bb4ee6a4SAndroid Build Coastguard Worker // Class, subclass, and programming interface are encoded as a single number. 339*bb4ee6a4SAndroid Build Coastguard Worker let params = from_stub_arg("address=0000:00:01.2,class=0x012345").unwrap(); 340*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(params.class.class, PciClassCode::MassStorage); 341*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(params.class.subclass, 0x23); 342*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(params.class.programming_interface, 0x45); 343*bb4ee6a4SAndroid Build Coastguard Worker } 344*bb4ee6a4SAndroid Build Coastguard Worker 345*bb4ee6a4SAndroid Build Coastguard Worker #[test] params_subsystem_underscores()346*bb4ee6a4SAndroid Build Coastguard Worker fn params_subsystem_underscores() { 347*bb4ee6a4SAndroid Build Coastguard Worker // Accept aliases with underscores rather than hyphens for compatibility. 348*bb4ee6a4SAndroid Build Coastguard Worker let params = 349*bb4ee6a4SAndroid Build Coastguard Worker from_stub_arg("address=0000:00:01.2,subsystem_vendor=0x8675,subsystem_device=0x309") 350*bb4ee6a4SAndroid Build Coastguard Worker .unwrap(); 351*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(params.subsystem_vendor, 0x8675); 352*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(params.subsystem_device, 0x0309); 353*bb4ee6a4SAndroid Build Coastguard Worker } 354*bb4ee6a4SAndroid Build Coastguard Worker 355*bb4ee6a4SAndroid Build Coastguard Worker #[test] params_full()356*bb4ee6a4SAndroid Build Coastguard Worker fn params_full() { 357*bb4ee6a4SAndroid Build Coastguard Worker let params = from_stub_arg( 358*bb4ee6a4SAndroid Build Coastguard Worker "address=0000:00:01.2,vendor=0x1234,device=0x5678,subsystem-vendor=0x8675,subsystem-device=0x309,class=0x012345,revision=52", 359*bb4ee6a4SAndroid Build Coastguard Worker ).unwrap(); 360*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!( 361*bb4ee6a4SAndroid Build Coastguard Worker params.address, 362*bb4ee6a4SAndroid Build Coastguard Worker PciAddress { 363*bb4ee6a4SAndroid Build Coastguard Worker bus: 0, 364*bb4ee6a4SAndroid Build Coastguard Worker dev: 1, 365*bb4ee6a4SAndroid Build Coastguard Worker func: 2 366*bb4ee6a4SAndroid Build Coastguard Worker } 367*bb4ee6a4SAndroid Build Coastguard Worker ); 368*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(params.vendor, 0x1234); 369*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(params.device, 0x5678); 370*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(params.subsystem_vendor, 0x8675); 371*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(params.subsystem_device, 0x0309); 372*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(params.class.class, PciClassCode::MassStorage); 373*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(params.class.subclass, 0x23); 374*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(params.class.programming_interface, 0x45); 375*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(params.revision, 52); 376*bb4ee6a4SAndroid Build Coastguard Worker } 377*bb4ee6a4SAndroid Build Coastguard Worker 378*bb4ee6a4SAndroid Build Coastguard Worker #[test] stub_pci_device_snapshot_restore() -> anyhow::Result<()>379*bb4ee6a4SAndroid Build Coastguard Worker fn stub_pci_device_snapshot_restore() -> anyhow::Result<()> { 380*bb4ee6a4SAndroid Build Coastguard Worker let mut device = StubPciDevice::new(&CONFIG); 381*bb4ee6a4SAndroid Build Coastguard Worker let init_reg_value = device.read_config_register(1); 382*bb4ee6a4SAndroid Build Coastguard Worker let snapshot_init = device.snapshot().unwrap(); 383*bb4ee6a4SAndroid Build Coastguard Worker 384*bb4ee6a4SAndroid Build Coastguard Worker // Modify config reg 1 and make sure it went through. 385*bb4ee6a4SAndroid Build Coastguard Worker let new_reg_value: u32 = 0xCAFE; 386*bb4ee6a4SAndroid Build Coastguard Worker device.write_config_register(1, 0, &new_reg_value.to_le_bytes()); 387*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(device.read_config_register(1), new_reg_value); 388*bb4ee6a4SAndroid Build Coastguard Worker 389*bb4ee6a4SAndroid Build Coastguard Worker // Capture a snapshot after the modification. 390*bb4ee6a4SAndroid Build Coastguard Worker let mut snapshot_modified = device.snapshot().unwrap(); 391*bb4ee6a4SAndroid Build Coastguard Worker assert_ne!(snapshot_init, snapshot_modified); 392*bb4ee6a4SAndroid Build Coastguard Worker 393*bb4ee6a4SAndroid Build Coastguard Worker // Modify the same register and verify that it's restored correctly. 394*bb4ee6a4SAndroid Build Coastguard Worker device.write_config_register(1, 0, &[0xBA, 0xBA]); 395*bb4ee6a4SAndroid Build Coastguard Worker assert_ne!(device.read_config_register(1), new_reg_value); 396*bb4ee6a4SAndroid Build Coastguard Worker assert_ne!(device.read_config_register(1), init_reg_value); 397*bb4ee6a4SAndroid Build Coastguard Worker device.restore(snapshot_init.clone())?; 398*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(device.read_config_register(1), init_reg_value); 399*bb4ee6a4SAndroid Build Coastguard Worker 400*bb4ee6a4SAndroid Build Coastguard Worker // Capture a snapshot after restoring the initial snapshot. 401*bb4ee6a4SAndroid Build Coastguard Worker let mut snapshot_restored = device.snapshot().unwrap(); 402*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(snapshot_init, snapshot_restored); 403*bb4ee6a4SAndroid Build Coastguard Worker 404*bb4ee6a4SAndroid Build Coastguard Worker // Restore to the first modification and verify the values. 405*bb4ee6a4SAndroid Build Coastguard Worker device.restore(snapshot_modified.clone())?; 406*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(device.read_config_register(1), new_reg_value); 407*bb4ee6a4SAndroid Build Coastguard Worker snapshot_restored = device.snapshot().unwrap(); 408*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(snapshot_modified, snapshot_restored); 409*bb4ee6a4SAndroid Build Coastguard Worker 410*bb4ee6a4SAndroid Build Coastguard Worker /* 411*bb4ee6a4SAndroid Build Coastguard Worker Restore the initial snapshot and verify that addresses are not encoded. 412*bb4ee6a4SAndroid Build Coastguard Worker The addresses are only configurable during VM creation so they never 413*bb4ee6a4SAndroid Build Coastguard Worker change afterwards and are not part of the snapshot. Force a change 414*bb4ee6a4SAndroid Build Coastguard Worker to requested_address to confirm that. 415*bb4ee6a4SAndroid Build Coastguard Worker */ 416*bb4ee6a4SAndroid Build Coastguard Worker device.restore(snapshot_init.clone())?; 417*bb4ee6a4SAndroid Build Coastguard Worker device.requested_address = PciAddress { 418*bb4ee6a4SAndroid Build Coastguard Worker bus: 0x0d, 419*bb4ee6a4SAndroid Build Coastguard Worker dev: 0x0e, 420*bb4ee6a4SAndroid Build Coastguard Worker func: 0x4, 421*bb4ee6a4SAndroid Build Coastguard Worker }; 422*bb4ee6a4SAndroid Build Coastguard Worker snapshot_modified = device.snapshot().unwrap(); 423*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(snapshot_init, snapshot_modified); 424*bb4ee6a4SAndroid Build Coastguard Worker 425*bb4ee6a4SAndroid Build Coastguard Worker Ok(()) 426*bb4ee6a4SAndroid Build Coastguard Worker } 427*bb4ee6a4SAndroid Build Coastguard Worker } 428