xref: /aosp_15_r20/external/crosvm/devices/src/pci/stub.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
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