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::HashMap;
6*bb4ee6a4SAndroid Build Coastguard Worker use std::collections::HashSet;
7*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::Arc;
8*bb4ee6a4SAndroid Build Coastguard Worker
9*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(target_arch = "x86_64")]
10*bb4ee6a4SAndroid Build Coastguard Worker use acpi_tables::sdt::SDT;
11*bb4ee6a4SAndroid Build Coastguard Worker use anyhow::bail;
12*bb4ee6a4SAndroid Build Coastguard Worker use base::error;
13*bb4ee6a4SAndroid Build Coastguard Worker use base::trace;
14*bb4ee6a4SAndroid Build Coastguard Worker use base::warn;
15*bb4ee6a4SAndroid Build Coastguard Worker use base::MemoryMapping;
16*bb4ee6a4SAndroid Build Coastguard Worker use base::RawDescriptor;
17*bb4ee6a4SAndroid Build Coastguard Worker use base::SharedMemory;
18*bb4ee6a4SAndroid Build Coastguard Worker use remain::sorted;
19*bb4ee6a4SAndroid Build Coastguard Worker use resources::Error as SystemAllocatorFaliure;
20*bb4ee6a4SAndroid Build Coastguard Worker use resources::SystemAllocator;
21*bb4ee6a4SAndroid Build Coastguard Worker use sync::Mutex;
22*bb4ee6a4SAndroid Build Coastguard Worker use thiserror::Error;
23*bb4ee6a4SAndroid Build Coastguard Worker use vm_control::api::VmMemoryClient;
24*bb4ee6a4SAndroid Build Coastguard Worker
25*bb4ee6a4SAndroid Build Coastguard Worker use super::PciId;
26*bb4ee6a4SAndroid Build Coastguard Worker use crate::bus::BusDeviceObj;
27*bb4ee6a4SAndroid Build Coastguard Worker use crate::bus::BusRange;
28*bb4ee6a4SAndroid Build Coastguard Worker use crate::bus::BusType;
29*bb4ee6a4SAndroid Build Coastguard Worker use crate::bus::ConfigWriteResult;
30*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::pci_configuration;
31*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::pci_configuration::PciBarConfiguration;
32*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::pci_configuration::COMMAND_REG;
33*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::pci_configuration::COMMAND_REG_IO_SPACE_MASK;
34*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::pci_configuration::COMMAND_REG_MEMORY_SPACE_MASK;
35*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::pci_configuration::NUM_BAR_REGS;
36*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::pci_configuration::PCI_ID_REG;
37*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::PciAddress;
38*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::PciAddressError;
39*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::PciBarIndex;
40*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::PciInterruptPin;
41*bb4ee6a4SAndroid Build Coastguard Worker use crate::virtio::ipc_memory_mapper::IpcMemoryMapper;
42*bb4ee6a4SAndroid Build Coastguard Worker use crate::BusAccessInfo;
43*bb4ee6a4SAndroid Build Coastguard Worker use crate::BusDevice;
44*bb4ee6a4SAndroid Build Coastguard Worker use crate::DeviceId;
45*bb4ee6a4SAndroid Build Coastguard Worker use crate::IrqLevelEvent;
46*bb4ee6a4SAndroid Build Coastguard Worker use crate::Suspendable;
47*bb4ee6a4SAndroid Build Coastguard Worker use crate::VirtioPciDevice;
48*bb4ee6a4SAndroid Build Coastguard Worker
49*bb4ee6a4SAndroid Build Coastguard Worker #[sorted]
50*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Error, Debug)]
51*bb4ee6a4SAndroid Build Coastguard Worker pub enum Error {
52*bb4ee6a4SAndroid Build Coastguard Worker /// Deactivation of ACPI notifications failed
53*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to disable ACPI notifications")]
54*bb4ee6a4SAndroid Build Coastguard Worker AcpiNotifyDeactivationFailed,
55*bb4ee6a4SAndroid Build Coastguard Worker /// Setup of ACPI notifications failed
56*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to enable ACPI notifications")]
57*bb4ee6a4SAndroid Build Coastguard Worker AcpiNotifySetupFailed,
58*bb4ee6a4SAndroid Build Coastguard Worker /// Simulating ACPI notifications hardware triggering failed
59*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to test ACPI notifications")]
60*bb4ee6a4SAndroid Build Coastguard Worker AcpiNotifyTestFailed,
61*bb4ee6a4SAndroid Build Coastguard Worker /// Added pci device's parent bus does not belong to this bus
62*bb4ee6a4SAndroid Build Coastguard Worker #[error("pci device {0}'s parent bus does not belong to bus {1}")]
63*bb4ee6a4SAndroid Build Coastguard Worker AddedDeviceBusNotExist(PciAddress, u8),
64*bb4ee6a4SAndroid Build Coastguard Worker /// Invalid alignment encountered.
65*bb4ee6a4SAndroid Build Coastguard Worker #[error("Alignment must be a power of 2")]
66*bb4ee6a4SAndroid Build Coastguard Worker BadAlignment,
67*bb4ee6a4SAndroid Build Coastguard Worker /// The new bus has already been added to this bus
68*bb4ee6a4SAndroid Build Coastguard Worker #[error("Added bus {0} already existed on bus {1}")]
69*bb4ee6a4SAndroid Build Coastguard Worker BusAlreadyExist(u8, u8),
70*bb4ee6a4SAndroid Build Coastguard Worker /// Target bus not exists on this bus
71*bb4ee6a4SAndroid Build Coastguard Worker #[error("pci bus {0} does not exist on bus {1}")]
72*bb4ee6a4SAndroid Build Coastguard Worker BusNotExist(u8, u8),
73*bb4ee6a4SAndroid Build Coastguard Worker /// Setup of the device capabilities failed.
74*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to add capability {0}")]
75*bb4ee6a4SAndroid Build Coastguard Worker CapabilitiesSetup(pci_configuration::Error),
76*bb4ee6a4SAndroid Build Coastguard Worker /// Create cras client failed.
77*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(all(unix, feature = "audio", feature = "audio_cras"))]
78*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to create CRAS Client: {0}")]
79*bb4ee6a4SAndroid Build Coastguard Worker CreateCrasClientFailed(libcras::Error),
80*bb4ee6a4SAndroid Build Coastguard Worker /// Device is already on this bus
81*bb4ee6a4SAndroid Build Coastguard Worker #[error("pci device {0} has already been added to bus {1}")]
82*bb4ee6a4SAndroid Build Coastguard Worker DeviceAlreadyExist(PciAddress, u8),
83*bb4ee6a4SAndroid Build Coastguard Worker /// Device not exist on this bus
84*bb4ee6a4SAndroid Build Coastguard Worker #[error("pci device {0} does not located on bus {1}")]
85*bb4ee6a4SAndroid Build Coastguard Worker DeviceNotExist(PciAddress, u8),
86*bb4ee6a4SAndroid Build Coastguard Worker /// Fail to clone an event.
87*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to clone an event: {0}")]
88*bb4ee6a4SAndroid Build Coastguard Worker EventCloneFailed(i32),
89*bb4ee6a4SAndroid Build Coastguard Worker /// Fail to create an event.
90*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to create an event: {0}")]
91*bb4ee6a4SAndroid Build Coastguard Worker EventCreationFailed(i32),
92*bb4ee6a4SAndroid Build Coastguard Worker /// Fail to signal on an event.
93*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to signal an event: {0}")]
94*bb4ee6a4SAndroid Build Coastguard Worker EventSignalFailed(i32),
95*bb4ee6a4SAndroid Build Coastguard Worker /// Allocating space for an IO BAR failed.
96*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to allocate space for an IO BAR, size={0}: {1}")]
97*bb4ee6a4SAndroid Build Coastguard Worker IoAllocationFailed(u64, SystemAllocatorFaliure),
98*bb4ee6a4SAndroid Build Coastguard Worker /// Registering an IO BAR failed.
99*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to register an IO BAR, addr={0} err={1}")]
100*bb4ee6a4SAndroid Build Coastguard Worker IoRegistrationFailed(u64, pci_configuration::Error),
101*bb4ee6a4SAndroid Build Coastguard Worker /// Setting up MMIO mapping
102*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to set up MMIO mapping: {0}")]
103*bb4ee6a4SAndroid Build Coastguard Worker MmioSetup(anyhow::Error),
104*bb4ee6a4SAndroid Build Coastguard Worker /// Out-of-space encountered
105*bb4ee6a4SAndroid Build Coastguard Worker #[error("Out-of-space detected")]
106*bb4ee6a4SAndroid Build Coastguard Worker OutOfSpace,
107*bb4ee6a4SAndroid Build Coastguard Worker /// Overflow encountered
108*bb4ee6a4SAndroid Build Coastguard Worker #[error("base={0} + size={1} overflows")]
109*bb4ee6a4SAndroid Build Coastguard Worker Overflow(u64, u64),
110*bb4ee6a4SAndroid Build Coastguard Worker /// The new added bus does not located on this bus
111*bb4ee6a4SAndroid Build Coastguard Worker #[error("Added bus {0} does not located on bus {1}")]
112*bb4ee6a4SAndroid Build Coastguard Worker ParentBusNotExist(u8, u8),
113*bb4ee6a4SAndroid Build Coastguard Worker /// PCI Address parsing failure.
114*bb4ee6a4SAndroid Build Coastguard Worker #[error("PCI address '{0}' could not be parsed: {1}")]
115*bb4ee6a4SAndroid Build Coastguard Worker PciAddressParseFailure(String, PciAddressError),
116*bb4ee6a4SAndroid Build Coastguard Worker /// PCI Address allocation failure.
117*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to allocate PCI address")]
118*bb4ee6a4SAndroid Build Coastguard Worker PciAllocationFailed,
119*bb4ee6a4SAndroid Build Coastguard Worker /// PCI Bus window allocation failure.
120*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to allocate window for PCI bus: {0}")]
121*bb4ee6a4SAndroid Build Coastguard Worker PciBusWindowAllocationFailure(String),
122*bb4ee6a4SAndroid Build Coastguard Worker /// Size of zero encountered
123*bb4ee6a4SAndroid Build Coastguard Worker #[error("Size of zero detected")]
124*bb4ee6a4SAndroid Build Coastguard Worker SizeZero,
125*bb4ee6a4SAndroid Build Coastguard Worker }
126*bb4ee6a4SAndroid Build Coastguard Worker
127*bb4ee6a4SAndroid Build Coastguard Worker pub type Result<T> = std::result::Result<T, Error>;
128*bb4ee6a4SAndroid Build Coastguard Worker
129*bb4ee6a4SAndroid Build Coastguard Worker /// Pci Bar Range information
130*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Clone, Debug)]
131*bb4ee6a4SAndroid Build Coastguard Worker pub struct BarRange {
132*bb4ee6a4SAndroid Build Coastguard Worker /// pci bar start address
133*bb4ee6a4SAndroid Build Coastguard Worker pub addr: u64,
134*bb4ee6a4SAndroid Build Coastguard Worker /// pci bar size
135*bb4ee6a4SAndroid Build Coastguard Worker pub size: u64,
136*bb4ee6a4SAndroid Build Coastguard Worker /// pci bar is prefetchable or not, it used to set parent's bridge window
137*bb4ee6a4SAndroid Build Coastguard Worker pub prefetchable: bool,
138*bb4ee6a4SAndroid Build Coastguard Worker }
139*bb4ee6a4SAndroid Build Coastguard Worker
140*bb4ee6a4SAndroid Build Coastguard Worker /// Pci Bus information
141*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Debug)]
142*bb4ee6a4SAndroid Build Coastguard Worker pub struct PciBus {
143*bb4ee6a4SAndroid Build Coastguard Worker // bus number
144*bb4ee6a4SAndroid Build Coastguard Worker bus_num: u8,
145*bb4ee6a4SAndroid Build Coastguard Worker // parent bus number
146*bb4ee6a4SAndroid Build Coastguard Worker parent_bus_num: u8,
147*bb4ee6a4SAndroid Build Coastguard Worker // devices located on this bus
148*bb4ee6a4SAndroid Build Coastguard Worker child_devices: HashSet<PciAddress>,
149*bb4ee6a4SAndroid Build Coastguard Worker // Hash map that stores all direct child buses of this bus.
150*bb4ee6a4SAndroid Build Coastguard Worker // It maps from child bus number to its pci bus structure.
151*bb4ee6a4SAndroid Build Coastguard Worker child_buses: HashMap<u8, Arc<Mutex<PciBus>>>,
152*bb4ee6a4SAndroid Build Coastguard Worker // Is hotplug bus
153*bb4ee6a4SAndroid Build Coastguard Worker hotplug_bus: bool,
154*bb4ee6a4SAndroid Build Coastguard Worker }
155*bb4ee6a4SAndroid Build Coastguard Worker
156*bb4ee6a4SAndroid Build Coastguard Worker impl PciBus {
157*bb4ee6a4SAndroid Build Coastguard Worker // Creates a new pci bus
new(bus_num: u8, parent_bus_num: u8, hotplug_bus: bool) -> Self158*bb4ee6a4SAndroid Build Coastguard Worker pub fn new(bus_num: u8, parent_bus_num: u8, hotplug_bus: bool) -> Self {
159*bb4ee6a4SAndroid Build Coastguard Worker PciBus {
160*bb4ee6a4SAndroid Build Coastguard Worker bus_num,
161*bb4ee6a4SAndroid Build Coastguard Worker parent_bus_num,
162*bb4ee6a4SAndroid Build Coastguard Worker child_devices: HashSet::new(),
163*bb4ee6a4SAndroid Build Coastguard Worker child_buses: HashMap::new(),
164*bb4ee6a4SAndroid Build Coastguard Worker hotplug_bus,
165*bb4ee6a4SAndroid Build Coastguard Worker }
166*bb4ee6a4SAndroid Build Coastguard Worker }
167*bb4ee6a4SAndroid Build Coastguard Worker
get_bus_num(&self) -> u8168*bb4ee6a4SAndroid Build Coastguard Worker pub fn get_bus_num(&self) -> u8 {
169*bb4ee6a4SAndroid Build Coastguard Worker self.bus_num
170*bb4ee6a4SAndroid Build Coastguard Worker }
171*bb4ee6a4SAndroid Build Coastguard Worker
172*bb4ee6a4SAndroid Build Coastguard Worker // Find all PCI buses from this PCI bus to a given PCI bus
path_to(&self, bus_num: u8) -> Vec<u8>173*bb4ee6a4SAndroid Build Coastguard Worker pub fn path_to(&self, bus_num: u8) -> Vec<u8> {
174*bb4ee6a4SAndroid Build Coastguard Worker if self.bus_num == bus_num {
175*bb4ee6a4SAndroid Build Coastguard Worker return vec![self.bus_num];
176*bb4ee6a4SAndroid Build Coastguard Worker }
177*bb4ee6a4SAndroid Build Coastguard Worker
178*bb4ee6a4SAndroid Build Coastguard Worker for (_, child_bus) in self.child_buses.iter() {
179*bb4ee6a4SAndroid Build Coastguard Worker let mut path = child_bus.lock().path_to(bus_num);
180*bb4ee6a4SAndroid Build Coastguard Worker if !path.is_empty() {
181*bb4ee6a4SAndroid Build Coastguard Worker path.insert(0, self.bus_num);
182*bb4ee6a4SAndroid Build Coastguard Worker return path;
183*bb4ee6a4SAndroid Build Coastguard Worker }
184*bb4ee6a4SAndroid Build Coastguard Worker }
185*bb4ee6a4SAndroid Build Coastguard Worker Vec::new()
186*bb4ee6a4SAndroid Build Coastguard Worker }
187*bb4ee6a4SAndroid Build Coastguard Worker
188*bb4ee6a4SAndroid Build Coastguard Worker // Add a new child device to this pci bus tree.
add_child_device(&mut self, add_device: PciAddress) -> Result<()>189*bb4ee6a4SAndroid Build Coastguard Worker pub fn add_child_device(&mut self, add_device: PciAddress) -> Result<()> {
190*bb4ee6a4SAndroid Build Coastguard Worker if self.bus_num == add_device.bus {
191*bb4ee6a4SAndroid Build Coastguard Worker if !self.child_devices.insert(add_device) {
192*bb4ee6a4SAndroid Build Coastguard Worker return Err(Error::DeviceAlreadyExist(add_device, self.bus_num));
193*bb4ee6a4SAndroid Build Coastguard Worker }
194*bb4ee6a4SAndroid Build Coastguard Worker return Ok(());
195*bb4ee6a4SAndroid Build Coastguard Worker }
196*bb4ee6a4SAndroid Build Coastguard Worker
197*bb4ee6a4SAndroid Build Coastguard Worker for child_bus in self.child_buses.values() {
198*bb4ee6a4SAndroid Build Coastguard Worker match child_bus.lock().add_child_device(add_device) {
199*bb4ee6a4SAndroid Build Coastguard Worker Ok(()) => return Ok(()),
200*bb4ee6a4SAndroid Build Coastguard Worker Err(e) => {
201*bb4ee6a4SAndroid Build Coastguard Worker if let Error::DeviceAlreadyExist(_, _) = e {
202*bb4ee6a4SAndroid Build Coastguard Worker return Err(e);
203*bb4ee6a4SAndroid Build Coastguard Worker }
204*bb4ee6a4SAndroid Build Coastguard Worker }
205*bb4ee6a4SAndroid Build Coastguard Worker }
206*bb4ee6a4SAndroid Build Coastguard Worker }
207*bb4ee6a4SAndroid Build Coastguard Worker Err(Error::AddedDeviceBusNotExist(add_device, self.bus_num))
208*bb4ee6a4SAndroid Build Coastguard Worker }
209*bb4ee6a4SAndroid Build Coastguard Worker
210*bb4ee6a4SAndroid Build Coastguard Worker // Remove one child device from this pci bus tree
remove_child_device(&mut self, device: PciAddress) -> Result<()>211*bb4ee6a4SAndroid Build Coastguard Worker pub fn remove_child_device(&mut self, device: PciAddress) -> Result<()> {
212*bb4ee6a4SAndroid Build Coastguard Worker if self.child_devices.remove(&device) {
213*bb4ee6a4SAndroid Build Coastguard Worker return Ok(());
214*bb4ee6a4SAndroid Build Coastguard Worker }
215*bb4ee6a4SAndroid Build Coastguard Worker for child_bus in self.child_buses.values() {
216*bb4ee6a4SAndroid Build Coastguard Worker if child_bus.lock().remove_child_device(device).is_ok() {
217*bb4ee6a4SAndroid Build Coastguard Worker return Ok(());
218*bb4ee6a4SAndroid Build Coastguard Worker }
219*bb4ee6a4SAndroid Build Coastguard Worker }
220*bb4ee6a4SAndroid Build Coastguard Worker Err(Error::DeviceNotExist(device, self.bus_num))
221*bb4ee6a4SAndroid Build Coastguard Worker }
222*bb4ee6a4SAndroid Build Coastguard Worker
223*bb4ee6a4SAndroid Build Coastguard Worker // Add a new child bus to this pci bus tree.
add_child_bus(&mut self, add_bus: Arc<Mutex<PciBus>>) -> Result<()>224*bb4ee6a4SAndroid Build Coastguard Worker pub fn add_child_bus(&mut self, add_bus: Arc<Mutex<PciBus>>) -> Result<()> {
225*bb4ee6a4SAndroid Build Coastguard Worker let add_bus_num = add_bus.lock().bus_num;
226*bb4ee6a4SAndroid Build Coastguard Worker let add_bus_parent = add_bus.lock().parent_bus_num;
227*bb4ee6a4SAndroid Build Coastguard Worker if self.bus_num == add_bus_parent {
228*bb4ee6a4SAndroid Build Coastguard Worker if self.child_buses.contains_key(&add_bus_num) {
229*bb4ee6a4SAndroid Build Coastguard Worker return Err(Error::BusAlreadyExist(self.bus_num, add_bus_num));
230*bb4ee6a4SAndroid Build Coastguard Worker }
231*bb4ee6a4SAndroid Build Coastguard Worker self.child_buses.insert(add_bus_num, add_bus);
232*bb4ee6a4SAndroid Build Coastguard Worker return Ok(());
233*bb4ee6a4SAndroid Build Coastguard Worker }
234*bb4ee6a4SAndroid Build Coastguard Worker
235*bb4ee6a4SAndroid Build Coastguard Worker for child_bus in self.child_buses.values() {
236*bb4ee6a4SAndroid Build Coastguard Worker match child_bus.lock().add_child_bus(add_bus.clone()) {
237*bb4ee6a4SAndroid Build Coastguard Worker Ok(_) => return Ok(()),
238*bb4ee6a4SAndroid Build Coastguard Worker Err(e) => {
239*bb4ee6a4SAndroid Build Coastguard Worker if let Error::BusAlreadyExist(_, _) = e {
240*bb4ee6a4SAndroid Build Coastguard Worker return Err(e);
241*bb4ee6a4SAndroid Build Coastguard Worker }
242*bb4ee6a4SAndroid Build Coastguard Worker }
243*bb4ee6a4SAndroid Build Coastguard Worker }
244*bb4ee6a4SAndroid Build Coastguard Worker }
245*bb4ee6a4SAndroid Build Coastguard Worker Err(Error::ParentBusNotExist(add_bus_num, self.bus_num))
246*bb4ee6a4SAndroid Build Coastguard Worker }
247*bb4ee6a4SAndroid Build Coastguard Worker
248*bb4ee6a4SAndroid Build Coastguard Worker // Remove one child bus from this pci bus tree.
remove_child_bus(&mut self, bus_no: u8) -> Result<()>249*bb4ee6a4SAndroid Build Coastguard Worker pub fn remove_child_bus(&mut self, bus_no: u8) -> Result<()> {
250*bb4ee6a4SAndroid Build Coastguard Worker if self.child_buses.remove(&bus_no).is_some() {
251*bb4ee6a4SAndroid Build Coastguard Worker return Ok(());
252*bb4ee6a4SAndroid Build Coastguard Worker }
253*bb4ee6a4SAndroid Build Coastguard Worker for (_, child_bus) in self.child_buses.iter() {
254*bb4ee6a4SAndroid Build Coastguard Worker if child_bus.lock().remove_child_bus(bus_no).is_ok() {
255*bb4ee6a4SAndroid Build Coastguard Worker return Ok(());
256*bb4ee6a4SAndroid Build Coastguard Worker }
257*bb4ee6a4SAndroid Build Coastguard Worker }
258*bb4ee6a4SAndroid Build Coastguard Worker Err(Error::BusNotExist(bus_no, self.bus_num))
259*bb4ee6a4SAndroid Build Coastguard Worker }
260*bb4ee6a4SAndroid Build Coastguard Worker
261*bb4ee6a4SAndroid Build Coastguard Worker // Find all downstream devices under the given bus
find_downstream_devices(&self, bus_no: u8) -> Vec<PciAddress>262*bb4ee6a4SAndroid Build Coastguard Worker pub fn find_downstream_devices(&self, bus_no: u8) -> Vec<PciAddress> {
263*bb4ee6a4SAndroid Build Coastguard Worker if self.bus_num == bus_no {
264*bb4ee6a4SAndroid Build Coastguard Worker return self.get_downstream_devices();
265*bb4ee6a4SAndroid Build Coastguard Worker }
266*bb4ee6a4SAndroid Build Coastguard Worker for (_, child_bus) in self.child_buses.iter() {
267*bb4ee6a4SAndroid Build Coastguard Worker let res = child_bus.lock().find_downstream_devices(bus_no);
268*bb4ee6a4SAndroid Build Coastguard Worker if !res.is_empty() {
269*bb4ee6a4SAndroid Build Coastguard Worker return res;
270*bb4ee6a4SAndroid Build Coastguard Worker }
271*bb4ee6a4SAndroid Build Coastguard Worker }
272*bb4ee6a4SAndroid Build Coastguard Worker
273*bb4ee6a4SAndroid Build Coastguard Worker Vec::new()
274*bb4ee6a4SAndroid Build Coastguard Worker }
275*bb4ee6a4SAndroid Build Coastguard Worker
276*bb4ee6a4SAndroid Build Coastguard Worker // Get all devices in this pci bus tree by level-order traversal (BFS)
get_downstream_devices(&self) -> Vec<PciAddress>277*bb4ee6a4SAndroid Build Coastguard Worker pub fn get_downstream_devices(&self) -> Vec<PciAddress> {
278*bb4ee6a4SAndroid Build Coastguard Worker let mut devices = Vec::new();
279*bb4ee6a4SAndroid Build Coastguard Worker devices.extend(self.child_devices.clone());
280*bb4ee6a4SAndroid Build Coastguard Worker for child_bus in self.child_buses.values() {
281*bb4ee6a4SAndroid Build Coastguard Worker devices.extend(child_bus.lock().get_downstream_devices());
282*bb4ee6a4SAndroid Build Coastguard Worker }
283*bb4ee6a4SAndroid Build Coastguard Worker devices
284*bb4ee6a4SAndroid Build Coastguard Worker }
285*bb4ee6a4SAndroid Build Coastguard Worker
286*bb4ee6a4SAndroid Build Coastguard Worker // Check if given device is located in the device tree
contains(&self, device: PciAddress) -> bool287*bb4ee6a4SAndroid Build Coastguard Worker pub fn contains(&self, device: PciAddress) -> bool {
288*bb4ee6a4SAndroid Build Coastguard Worker if self.child_devices.contains(&device) {
289*bb4ee6a4SAndroid Build Coastguard Worker return true;
290*bb4ee6a4SAndroid Build Coastguard Worker }
291*bb4ee6a4SAndroid Build Coastguard Worker
292*bb4ee6a4SAndroid Build Coastguard Worker for (_, child_bus) in self.child_buses.iter() {
293*bb4ee6a4SAndroid Build Coastguard Worker if child_bus.lock().contains(device) {
294*bb4ee6a4SAndroid Build Coastguard Worker return true;
295*bb4ee6a4SAndroid Build Coastguard Worker }
296*bb4ee6a4SAndroid Build Coastguard Worker }
297*bb4ee6a4SAndroid Build Coastguard Worker
298*bb4ee6a4SAndroid Build Coastguard Worker false
299*bb4ee6a4SAndroid Build Coastguard Worker }
300*bb4ee6a4SAndroid Build Coastguard Worker
301*bb4ee6a4SAndroid Build Coastguard Worker // Returns the hotplug bus that this device is on.
get_hotplug_bus(&self, device: PciAddress) -> Option<u8>302*bb4ee6a4SAndroid Build Coastguard Worker pub fn get_hotplug_bus(&self, device: PciAddress) -> Option<u8> {
303*bb4ee6a4SAndroid Build Coastguard Worker if self.hotplug_bus && self.contains(device) {
304*bb4ee6a4SAndroid Build Coastguard Worker return Some(self.bus_num);
305*bb4ee6a4SAndroid Build Coastguard Worker }
306*bb4ee6a4SAndroid Build Coastguard Worker for (_, child_bus) in self.child_buses.iter() {
307*bb4ee6a4SAndroid Build Coastguard Worker let hotplug_bus = child_bus.lock().get_hotplug_bus(device);
308*bb4ee6a4SAndroid Build Coastguard Worker if hotplug_bus.is_some() {
309*bb4ee6a4SAndroid Build Coastguard Worker return hotplug_bus;
310*bb4ee6a4SAndroid Build Coastguard Worker }
311*bb4ee6a4SAndroid Build Coastguard Worker }
312*bb4ee6a4SAndroid Build Coastguard Worker None
313*bb4ee6a4SAndroid Build Coastguard Worker }
314*bb4ee6a4SAndroid Build Coastguard Worker }
315*bb4ee6a4SAndroid Build Coastguard Worker
316*bb4ee6a4SAndroid Build Coastguard Worker pub enum PreferredIrq {
317*bb4ee6a4SAndroid Build Coastguard Worker None,
318*bb4ee6a4SAndroid Build Coastguard Worker Any,
319*bb4ee6a4SAndroid Build Coastguard Worker Fixed { pin: PciInterruptPin, gsi: u32 },
320*bb4ee6a4SAndroid Build Coastguard Worker }
321*bb4ee6a4SAndroid Build Coastguard Worker
322*bb4ee6a4SAndroid Build Coastguard Worker pub trait PciDevice: Send + Suspendable {
323*bb4ee6a4SAndroid Build Coastguard Worker /// Returns a label suitable for debug output.
debug_label(&self) -> String324*bb4ee6a4SAndroid Build Coastguard Worker fn debug_label(&self) -> String;
325*bb4ee6a4SAndroid Build Coastguard Worker
326*bb4ee6a4SAndroid Build Coastguard Worker /// Preferred PCI address for this device, if any.
preferred_address(&self) -> Option<PciAddress>327*bb4ee6a4SAndroid Build Coastguard Worker fn preferred_address(&self) -> Option<PciAddress> {
328*bb4ee6a4SAndroid Build Coastguard Worker None
329*bb4ee6a4SAndroid Build Coastguard Worker }
330*bb4ee6a4SAndroid Build Coastguard Worker
331*bb4ee6a4SAndroid Build Coastguard Worker /// Allocate and return an unique bus, device and function number for this device.
332*bb4ee6a4SAndroid Build Coastguard Worker /// May be called multiple times; on subsequent calls, the device should return the same
333*bb4ee6a4SAndroid Build Coastguard Worker /// address it returned from the first call.
allocate_address(&mut self, resources: &mut SystemAllocator) -> Result<PciAddress>334*bb4ee6a4SAndroid Build Coastguard Worker fn allocate_address(&mut self, resources: &mut SystemAllocator) -> Result<PciAddress>;
335*bb4ee6a4SAndroid Build Coastguard Worker
336*bb4ee6a4SAndroid Build Coastguard Worker /// A vector of device-specific file descriptors that must be kept open
337*bb4ee6a4SAndroid Build Coastguard Worker /// after jailing. Must be called before the process is jailed.
keep_rds(&self) -> Vec<RawDescriptor>338*bb4ee6a4SAndroid Build Coastguard Worker fn keep_rds(&self) -> Vec<RawDescriptor>;
339*bb4ee6a4SAndroid Build Coastguard Worker
340*bb4ee6a4SAndroid Build Coastguard Worker /// Preferred IRQ for this device.
341*bb4ee6a4SAndroid Build Coastguard Worker /// The device may request a specific pin and IRQ number by returning a `Fixed` value.
342*bb4ee6a4SAndroid Build Coastguard Worker /// If a device does not support INTx# interrupts at all, it should return `None`.
343*bb4ee6a4SAndroid Build Coastguard Worker /// Otherwise, an appropriate IRQ will be allocated automatically.
344*bb4ee6a4SAndroid Build Coastguard Worker /// The device's `assign_irq` function will be called with its assigned IRQ either way.
preferred_irq(&self) -> PreferredIrq345*bb4ee6a4SAndroid Build Coastguard Worker fn preferred_irq(&self) -> PreferredIrq {
346*bb4ee6a4SAndroid Build Coastguard Worker PreferredIrq::Any
347*bb4ee6a4SAndroid Build Coastguard Worker }
348*bb4ee6a4SAndroid Build Coastguard Worker
349*bb4ee6a4SAndroid Build Coastguard Worker /// Assign a legacy PCI IRQ to this device.
350*bb4ee6a4SAndroid Build Coastguard Worker /// The device may write to `irq_evt` to trigger an interrupt.
351*bb4ee6a4SAndroid Build Coastguard Worker /// When `irq_resample_evt` is signaled, the device should re-assert `irq_evt` if necessary.
assign_irq(&mut self, _irq_evt: IrqLevelEvent, _pin: PciInterruptPin, _irq_num: u32)352*bb4ee6a4SAndroid Build Coastguard Worker fn assign_irq(&mut self, _irq_evt: IrqLevelEvent, _pin: PciInterruptPin, _irq_num: u32) {}
353*bb4ee6a4SAndroid Build Coastguard Worker
354*bb4ee6a4SAndroid Build Coastguard Worker /// Allocates the needed IO BAR space using the `allocate` function which takes a size and
355*bb4ee6a4SAndroid Build Coastguard Worker /// returns an address. Returns a Vec of BarRange{addr, size, prefetchable}.
allocate_io_bars(&mut self, _resources: &mut SystemAllocator) -> Result<Vec<BarRange>>356*bb4ee6a4SAndroid Build Coastguard Worker fn allocate_io_bars(&mut self, _resources: &mut SystemAllocator) -> Result<Vec<BarRange>> {
357*bb4ee6a4SAndroid Build Coastguard Worker Ok(Vec::new())
358*bb4ee6a4SAndroid Build Coastguard Worker }
359*bb4ee6a4SAndroid Build Coastguard Worker
360*bb4ee6a4SAndroid Build Coastguard Worker /// Allocates the needed device BAR space. Returns a Vec of BarRange{addr, size, prefetchable}.
361*bb4ee6a4SAndroid Build Coastguard Worker /// Unlike MMIO BARs (see allocate_io_bars), device BARs are not expected to incur VM exits
362*bb4ee6a4SAndroid Build Coastguard Worker /// - these BARs represent normal memory.
allocate_device_bars(&mut self, _resources: &mut SystemAllocator) -> Result<Vec<BarRange>>363*bb4ee6a4SAndroid Build Coastguard Worker fn allocate_device_bars(&mut self, _resources: &mut SystemAllocator) -> Result<Vec<BarRange>> {
364*bb4ee6a4SAndroid Build Coastguard Worker Ok(Vec::new())
365*bb4ee6a4SAndroid Build Coastguard Worker }
366*bb4ee6a4SAndroid Build Coastguard Worker
367*bb4ee6a4SAndroid Build Coastguard Worker /// Returns the configuration of a base address register, if present.
get_bar_configuration(&self, bar_num: usize) -> Option<PciBarConfiguration>368*bb4ee6a4SAndroid Build Coastguard Worker fn get_bar_configuration(&self, bar_num: usize) -> Option<PciBarConfiguration>;
369*bb4ee6a4SAndroid Build Coastguard Worker
370*bb4ee6a4SAndroid Build Coastguard Worker /// Register any capabilties specified by the device.
register_device_capabilities(&mut self) -> Result<()>371*bb4ee6a4SAndroid Build Coastguard Worker fn register_device_capabilities(&mut self) -> Result<()> {
372*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
373*bb4ee6a4SAndroid Build Coastguard Worker }
374*bb4ee6a4SAndroid Build Coastguard Worker
375*bb4ee6a4SAndroid Build Coastguard Worker /// Gets a reference to the API client for sending VmMemoryRequest. Any devices that uses
376*bb4ee6a4SAndroid Build Coastguard Worker /// ioevents must provide this.
get_vm_memory_client(&self) -> Option<&VmMemoryClient>377*bb4ee6a4SAndroid Build Coastguard Worker fn get_vm_memory_client(&self) -> Option<&VmMemoryClient> {
378*bb4ee6a4SAndroid Build Coastguard Worker None
379*bb4ee6a4SAndroid Build Coastguard Worker }
380*bb4ee6a4SAndroid Build Coastguard Worker
381*bb4ee6a4SAndroid Build Coastguard Worker /// Reads from a PCI configuration register.
382*bb4ee6a4SAndroid Build Coastguard Worker /// * `reg_idx` - PCI register index (in units of 4 bytes).
read_config_register(&self, reg_idx: usize) -> u32383*bb4ee6a4SAndroid Build Coastguard Worker fn read_config_register(&self, reg_idx: usize) -> u32;
384*bb4ee6a4SAndroid Build Coastguard Worker
385*bb4ee6a4SAndroid Build Coastguard Worker /// Writes to a PCI configuration register.
386*bb4ee6a4SAndroid Build Coastguard Worker /// * `reg_idx` - PCI register index (in units of 4 bytes).
387*bb4ee6a4SAndroid Build Coastguard Worker /// * `offset` - byte offset within 4-byte register.
388*bb4ee6a4SAndroid Build Coastguard Worker /// * `data` - The data to write.
write_config_register(&mut self, reg_idx: usize, offset: u64, data: &[u8])389*bb4ee6a4SAndroid Build Coastguard Worker fn write_config_register(&mut self, reg_idx: usize, offset: u64, data: &[u8]);
390*bb4ee6a4SAndroid Build Coastguard Worker
391*bb4ee6a4SAndroid Build Coastguard Worker /// Provides a memory region to back MMIO access to the configuration
392*bb4ee6a4SAndroid Build Coastguard Worker /// space. If the device can keep the memory region up to date, then it
393*bb4ee6a4SAndroid Build Coastguard Worker /// should return Ok(true), after which no more calls to read_config_register
394*bb4ee6a4SAndroid Build Coastguard Worker /// will be made. If support isn't implemented, it should return Ok(false).
395*bb4ee6a4SAndroid Build Coastguard Worker /// Otherwise, it should return an error (a failure here is not treated as
396*bb4ee6a4SAndroid Build Coastguard Worker /// a fatal setup error).
397*bb4ee6a4SAndroid Build Coastguard Worker ///
398*bb4ee6a4SAndroid Build Coastguard Worker /// The device must set the header type register (0x0E) before returning
399*bb4ee6a4SAndroid Build Coastguard Worker /// from this function, and must make no further modifications to it
400*bb4ee6a4SAndroid Build Coastguard Worker /// after returning. This is to allow the caller to manage the multi-
401*bb4ee6a4SAndroid Build Coastguard Worker /// function device bit without worrying about race conditions.
402*bb4ee6a4SAndroid Build Coastguard Worker ///
403*bb4ee6a4SAndroid Build Coastguard Worker /// * `shmem` - The shared memory to use for the configuration space.
404*bb4ee6a4SAndroid Build Coastguard Worker /// * `base` - The base address of the memory region in shmem.
405*bb4ee6a4SAndroid Build Coastguard Worker /// * `len` - The length of the memory region.
setup_pci_config_mapping( &mut self, _shmem: &SharedMemory, _base: usize, _len: usize, ) -> Result<bool>406*bb4ee6a4SAndroid Build Coastguard Worker fn setup_pci_config_mapping(
407*bb4ee6a4SAndroid Build Coastguard Worker &mut self,
408*bb4ee6a4SAndroid Build Coastguard Worker _shmem: &SharedMemory,
409*bb4ee6a4SAndroid Build Coastguard Worker _base: usize,
410*bb4ee6a4SAndroid Build Coastguard Worker _len: usize,
411*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<bool> {
412*bb4ee6a4SAndroid Build Coastguard Worker Ok(false)
413*bb4ee6a4SAndroid Build Coastguard Worker }
414*bb4ee6a4SAndroid Build Coastguard Worker
415*bb4ee6a4SAndroid Build Coastguard Worker /// Reads from a virtual config register.
416*bb4ee6a4SAndroid Build Coastguard Worker /// * `reg_idx` - virtual config register index (in units of 4 bytes).
read_virtual_config_register(&self, _reg_idx: usize) -> u32417*bb4ee6a4SAndroid Build Coastguard Worker fn read_virtual_config_register(&self, _reg_idx: usize) -> u32 {
418*bb4ee6a4SAndroid Build Coastguard Worker 0
419*bb4ee6a4SAndroid Build Coastguard Worker }
420*bb4ee6a4SAndroid Build Coastguard Worker
421*bb4ee6a4SAndroid Build Coastguard Worker /// Writes to a virtual config register.
422*bb4ee6a4SAndroid Build Coastguard Worker /// * `reg_idx` - virtual config register index (in units of 4 bytes).
423*bb4ee6a4SAndroid Build Coastguard Worker /// * `value` - the value to be written.
write_virtual_config_register(&mut self, _reg_idx: usize, _value: u32)424*bb4ee6a4SAndroid Build Coastguard Worker fn write_virtual_config_register(&mut self, _reg_idx: usize, _value: u32) {}
425*bb4ee6a4SAndroid Build Coastguard Worker
426*bb4ee6a4SAndroid Build Coastguard Worker /// Reads from a BAR region mapped in to the device.
427*bb4ee6a4SAndroid Build Coastguard Worker /// * `bar_index` - The index of the PCI BAR.
428*bb4ee6a4SAndroid Build Coastguard Worker /// * `offset` - The starting offset in bytes inside the BAR.
429*bb4ee6a4SAndroid Build Coastguard Worker /// * `data` - Filled with the data from `offset`.
read_bar(&mut self, bar_index: PciBarIndex, offset: u64, data: &mut [u8])430*bb4ee6a4SAndroid Build Coastguard Worker fn read_bar(&mut self, bar_index: PciBarIndex, offset: u64, data: &mut [u8]);
431*bb4ee6a4SAndroid Build Coastguard Worker
432*bb4ee6a4SAndroid Build Coastguard Worker /// Writes to a BAR region mapped in to the device.
433*bb4ee6a4SAndroid Build Coastguard Worker /// * `bar_index` - The index of the PCI BAR.
434*bb4ee6a4SAndroid Build Coastguard Worker /// * `offset` - The starting offset in bytes inside the BAR.
435*bb4ee6a4SAndroid Build Coastguard Worker /// * `data` - The data to write.
write_bar(&mut self, bar_index: PciBarIndex, offset: u64, data: &[u8])436*bb4ee6a4SAndroid Build Coastguard Worker fn write_bar(&mut self, bar_index: PciBarIndex, offset: u64, data: &[u8]);
437*bb4ee6a4SAndroid Build Coastguard Worker
438*bb4ee6a4SAndroid Build Coastguard Worker /// Invoked when the device is sandboxed.
on_device_sandboxed(&mut self)439*bb4ee6a4SAndroid Build Coastguard Worker fn on_device_sandboxed(&mut self) {}
440*bb4ee6a4SAndroid Build Coastguard Worker
441*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(target_arch = "x86_64")]
generate_acpi(&mut self, sdts: Vec<SDT>) -> Option<Vec<SDT>>442*bb4ee6a4SAndroid Build Coastguard Worker fn generate_acpi(&mut self, sdts: Vec<SDT>) -> Option<Vec<SDT>> {
443*bb4ee6a4SAndroid Build Coastguard Worker Some(sdts)
444*bb4ee6a4SAndroid Build Coastguard Worker }
445*bb4ee6a4SAndroid Build Coastguard Worker
446*bb4ee6a4SAndroid Build Coastguard Worker /// Construct customized acpi method, and return the AML code and
447*bb4ee6a4SAndroid Build Coastguard Worker /// shared memory
generate_acpi_methods(&mut self) -> (Vec<u8>, Option<(u32, MemoryMapping)>)448*bb4ee6a4SAndroid Build Coastguard Worker fn generate_acpi_methods(&mut self) -> (Vec<u8>, Option<(u32, MemoryMapping)>) {
449*bb4ee6a4SAndroid Build Coastguard Worker (Vec::new(), None)
450*bb4ee6a4SAndroid Build Coastguard Worker }
451*bb4ee6a4SAndroid Build Coastguard Worker
set_gpe(&mut self, _resources: &mut SystemAllocator) -> Option<u32>452*bb4ee6a4SAndroid Build Coastguard Worker fn set_gpe(&mut self, _resources: &mut SystemAllocator) -> Option<u32> {
453*bb4ee6a4SAndroid Build Coastguard Worker None
454*bb4ee6a4SAndroid Build Coastguard Worker }
455*bb4ee6a4SAndroid Build Coastguard Worker
456*bb4ee6a4SAndroid Build Coastguard Worker /// Invoked when the device is destroyed
destroy_device(&mut self)457*bb4ee6a4SAndroid Build Coastguard Worker fn destroy_device(&mut self) {}
458*bb4ee6a4SAndroid Build Coastguard Worker
459*bb4ee6a4SAndroid Build Coastguard Worker /// Get the removed children devices under pci bridge
get_removed_children_devices(&self) -> Vec<PciAddress>460*bb4ee6a4SAndroid Build Coastguard Worker fn get_removed_children_devices(&self) -> Vec<PciAddress> {
461*bb4ee6a4SAndroid Build Coastguard Worker Vec::new()
462*bb4ee6a4SAndroid Build Coastguard Worker }
463*bb4ee6a4SAndroid Build Coastguard Worker
464*bb4ee6a4SAndroid Build Coastguard Worker /// Get the pci bus generated by this pci device
get_new_pci_bus(&self) -> Option<Arc<Mutex<PciBus>>>465*bb4ee6a4SAndroid Build Coastguard Worker fn get_new_pci_bus(&self) -> Option<Arc<Mutex<PciBus>>> {
466*bb4ee6a4SAndroid Build Coastguard Worker None
467*bb4ee6a4SAndroid Build Coastguard Worker }
468*bb4ee6a4SAndroid Build Coastguard Worker
469*bb4ee6a4SAndroid Build Coastguard Worker /// if device is a pci brdige, configure pci bridge window
configure_bridge_window( &mut self, _resources: &mut SystemAllocator, _bar_ranges: &[BarRange], ) -> Result<Vec<BarRange>>470*bb4ee6a4SAndroid Build Coastguard Worker fn configure_bridge_window(
471*bb4ee6a4SAndroid Build Coastguard Worker &mut self,
472*bb4ee6a4SAndroid Build Coastguard Worker _resources: &mut SystemAllocator,
473*bb4ee6a4SAndroid Build Coastguard Worker _bar_ranges: &[BarRange],
474*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<Vec<BarRange>> {
475*bb4ee6a4SAndroid Build Coastguard Worker Ok(Vec::new())
476*bb4ee6a4SAndroid Build Coastguard Worker }
477*bb4ee6a4SAndroid Build Coastguard Worker
478*bb4ee6a4SAndroid Build Coastguard Worker /// if device is a pci bridge, configure subordinate bus number
set_subordinate_bus(&mut self, _bus_no: u8)479*bb4ee6a4SAndroid Build Coastguard Worker fn set_subordinate_bus(&mut self, _bus_no: u8) {}
480*bb4ee6a4SAndroid Build Coastguard Worker
481*bb4ee6a4SAndroid Build Coastguard Worker /// Indicates whether the device supports IOMMU
supports_iommu(&self) -> bool482*bb4ee6a4SAndroid Build Coastguard Worker fn supports_iommu(&self) -> bool {
483*bb4ee6a4SAndroid Build Coastguard Worker false
484*bb4ee6a4SAndroid Build Coastguard Worker }
485*bb4ee6a4SAndroid Build Coastguard Worker
486*bb4ee6a4SAndroid Build Coastguard Worker /// Sets the IOMMU for the device if `supports_iommu()`
set_iommu(&mut self, _iommu: IpcMemoryMapper) -> anyhow::Result<()>487*bb4ee6a4SAndroid Build Coastguard Worker fn set_iommu(&mut self, _iommu: IpcMemoryMapper) -> anyhow::Result<()> {
488*bb4ee6a4SAndroid Build Coastguard Worker bail!("Iommu not supported.");
489*bb4ee6a4SAndroid Build Coastguard Worker }
490*bb4ee6a4SAndroid Build Coastguard Worker
491*bb4ee6a4SAndroid Build Coastguard Worker // Used for bootorder
as_virtio_pci_device(&self) -> Option<&VirtioPciDevice>492*bb4ee6a4SAndroid Build Coastguard Worker fn as_virtio_pci_device(&self) -> Option<&VirtioPciDevice> {
493*bb4ee6a4SAndroid Build Coastguard Worker None
494*bb4ee6a4SAndroid Build Coastguard Worker }
495*bb4ee6a4SAndroid Build Coastguard Worker }
496*bb4ee6a4SAndroid Build Coastguard Worker
update_ranges( old_enabled: bool, new_enabled: bool, bus_type_filter: BusType, old_ranges: &[(BusRange, BusType)], new_ranges: &[(BusRange, BusType)], ) -> (Vec<BusRange>, Vec<BusRange>)497*bb4ee6a4SAndroid Build Coastguard Worker fn update_ranges(
498*bb4ee6a4SAndroid Build Coastguard Worker old_enabled: bool,
499*bb4ee6a4SAndroid Build Coastguard Worker new_enabled: bool,
500*bb4ee6a4SAndroid Build Coastguard Worker bus_type_filter: BusType,
501*bb4ee6a4SAndroid Build Coastguard Worker old_ranges: &[(BusRange, BusType)],
502*bb4ee6a4SAndroid Build Coastguard Worker new_ranges: &[(BusRange, BusType)],
503*bb4ee6a4SAndroid Build Coastguard Worker ) -> (Vec<BusRange>, Vec<BusRange>) {
504*bb4ee6a4SAndroid Build Coastguard Worker let mut remove_ranges = Vec::new();
505*bb4ee6a4SAndroid Build Coastguard Worker let mut add_ranges = Vec::new();
506*bb4ee6a4SAndroid Build Coastguard Worker
507*bb4ee6a4SAndroid Build Coastguard Worker let old_ranges_filtered = old_ranges
508*bb4ee6a4SAndroid Build Coastguard Worker .iter()
509*bb4ee6a4SAndroid Build Coastguard Worker .filter(|(_range, bus_type)| *bus_type == bus_type_filter)
510*bb4ee6a4SAndroid Build Coastguard Worker .map(|(range, _bus_type)| *range);
511*bb4ee6a4SAndroid Build Coastguard Worker let new_ranges_filtered = new_ranges
512*bb4ee6a4SAndroid Build Coastguard Worker .iter()
513*bb4ee6a4SAndroid Build Coastguard Worker .filter(|(_range, bus_type)| *bus_type == bus_type_filter)
514*bb4ee6a4SAndroid Build Coastguard Worker .map(|(range, _bus_type)| *range);
515*bb4ee6a4SAndroid Build Coastguard Worker
516*bb4ee6a4SAndroid Build Coastguard Worker if old_enabled && !new_enabled {
517*bb4ee6a4SAndroid Build Coastguard Worker // Bus type was enabled and is now disabled; remove all old ranges.
518*bb4ee6a4SAndroid Build Coastguard Worker remove_ranges.extend(old_ranges_filtered);
519*bb4ee6a4SAndroid Build Coastguard Worker } else if !old_enabled && new_enabled {
520*bb4ee6a4SAndroid Build Coastguard Worker // Bus type was disabled and is now enabled; add all new ranges.
521*bb4ee6a4SAndroid Build Coastguard Worker add_ranges.extend(new_ranges_filtered);
522*bb4ee6a4SAndroid Build Coastguard Worker } else if old_enabled && new_enabled {
523*bb4ee6a4SAndroid Build Coastguard Worker // Bus type was enabled before and is still enabled; diff old and new ranges.
524*bb4ee6a4SAndroid Build Coastguard Worker for (old_range, new_range) in old_ranges_filtered.zip(new_ranges_filtered) {
525*bb4ee6a4SAndroid Build Coastguard Worker if old_range.base != new_range.base {
526*bb4ee6a4SAndroid Build Coastguard Worker remove_ranges.push(old_range);
527*bb4ee6a4SAndroid Build Coastguard Worker add_ranges.push(new_range);
528*bb4ee6a4SAndroid Build Coastguard Worker }
529*bb4ee6a4SAndroid Build Coastguard Worker }
530*bb4ee6a4SAndroid Build Coastguard Worker }
531*bb4ee6a4SAndroid Build Coastguard Worker
532*bb4ee6a4SAndroid Build Coastguard Worker (remove_ranges, add_ranges)
533*bb4ee6a4SAndroid Build Coastguard Worker }
534*bb4ee6a4SAndroid Build Coastguard Worker
535*bb4ee6a4SAndroid Build Coastguard Worker // Debug-only helper function to convert a slice of bytes into a u32.
536*bb4ee6a4SAndroid Build Coastguard Worker // This can be lossy - only use it for logging!
trace_data(data: &[u8], offset: u64) -> u32537*bb4ee6a4SAndroid Build Coastguard Worker fn trace_data(data: &[u8], offset: u64) -> u32 {
538*bb4ee6a4SAndroid Build Coastguard Worker let mut data4 = [0u8; 4];
539*bb4ee6a4SAndroid Build Coastguard Worker for (d, s) in data4.iter_mut().skip(offset as usize).zip(data.iter()) {
540*bb4ee6a4SAndroid Build Coastguard Worker *d = *s;
541*bb4ee6a4SAndroid Build Coastguard Worker }
542*bb4ee6a4SAndroid Build Coastguard Worker u32::from_le_bytes(data4)
543*bb4ee6a4SAndroid Build Coastguard Worker }
544*bb4ee6a4SAndroid Build Coastguard Worker
545*bb4ee6a4SAndroid Build Coastguard Worker /// Find the BAR containing an access specified by `address` and `size`.
546*bb4ee6a4SAndroid Build Coastguard Worker ///
547*bb4ee6a4SAndroid Build Coastguard Worker /// If found, returns the BAR index and offset in bytes within that BAR corresponding to `address`.
548*bb4ee6a4SAndroid Build Coastguard Worker ///
549*bb4ee6a4SAndroid Build Coastguard Worker /// The BAR must fully contain the access region; partial overlaps will return `None`. Zero-sized
550*bb4ee6a4SAndroid Build Coastguard Worker /// accesses should not normally happen, but in case one does, this function will return `None`.
551*bb4ee6a4SAndroid Build Coastguard Worker ///
552*bb4ee6a4SAndroid Build Coastguard Worker /// This function only finds memory BARs, not I/O BARs. If a device with a BAR in I/O address space
553*bb4ee6a4SAndroid Build Coastguard Worker /// is ever added, address space information will need to be added to `BusDevice::read()` and
554*bb4ee6a4SAndroid Build Coastguard Worker /// `BusDevice::write()` and passed along to this function.
find_bar_and_offset( device: &impl PciDevice, address: u64, size: usize, ) -> Option<(PciBarIndex, u64)>555*bb4ee6a4SAndroid Build Coastguard Worker fn find_bar_and_offset(
556*bb4ee6a4SAndroid Build Coastguard Worker device: &impl PciDevice,
557*bb4ee6a4SAndroid Build Coastguard Worker address: u64,
558*bb4ee6a4SAndroid Build Coastguard Worker size: usize,
559*bb4ee6a4SAndroid Build Coastguard Worker ) -> Option<(PciBarIndex, u64)> {
560*bb4ee6a4SAndroid Build Coastguard Worker if size == 0 {
561*bb4ee6a4SAndroid Build Coastguard Worker return None;
562*bb4ee6a4SAndroid Build Coastguard Worker }
563*bb4ee6a4SAndroid Build Coastguard Worker
564*bb4ee6a4SAndroid Build Coastguard Worker for bar_index in 0..NUM_BAR_REGS {
565*bb4ee6a4SAndroid Build Coastguard Worker if let Some(bar_info) = device.get_bar_configuration(bar_index) {
566*bb4ee6a4SAndroid Build Coastguard Worker if !bar_info.is_memory() {
567*bb4ee6a4SAndroid Build Coastguard Worker continue;
568*bb4ee6a4SAndroid Build Coastguard Worker }
569*bb4ee6a4SAndroid Build Coastguard Worker
570*bb4ee6a4SAndroid Build Coastguard Worker // If access address >= BAR address, calculate the offset of the access in bytes from
571*bb4ee6a4SAndroid Build Coastguard Worker // the start of the BAR. If underflow occurs, the access begins before this BAR, so it
572*bb4ee6a4SAndroid Build Coastguard Worker // cannot be fully contained in the BAR; skip to the next BAR.
573*bb4ee6a4SAndroid Build Coastguard Worker let Some(offset) = address.checked_sub(bar_info.address()) else {
574*bb4ee6a4SAndroid Build Coastguard Worker continue;
575*bb4ee6a4SAndroid Build Coastguard Worker };
576*bb4ee6a4SAndroid Build Coastguard Worker
577*bb4ee6a4SAndroid Build Coastguard Worker // Calculate the largest valid offset given the BAR size and access size. If underflow
578*bb4ee6a4SAndroid Build Coastguard Worker // occurs, the access size is larger than the BAR size, so the access is definitely not
579*bb4ee6a4SAndroid Build Coastguard Worker // fully contained in the BAR; skip to the next BAR.
580*bb4ee6a4SAndroid Build Coastguard Worker let Some(max_offset) = bar_info.size().checked_sub(size as u64) else {
581*bb4ee6a4SAndroid Build Coastguard Worker continue;
582*bb4ee6a4SAndroid Build Coastguard Worker };
583*bb4ee6a4SAndroid Build Coastguard Worker
584*bb4ee6a4SAndroid Build Coastguard Worker // If offset <= max_offset, then the access is entirely contained within the BAR.
585*bb4ee6a4SAndroid Build Coastguard Worker if offset <= max_offset {
586*bb4ee6a4SAndroid Build Coastguard Worker return Some((bar_index, offset));
587*bb4ee6a4SAndroid Build Coastguard Worker }
588*bb4ee6a4SAndroid Build Coastguard Worker }
589*bb4ee6a4SAndroid Build Coastguard Worker }
590*bb4ee6a4SAndroid Build Coastguard Worker
591*bb4ee6a4SAndroid Build Coastguard Worker None
592*bb4ee6a4SAndroid Build Coastguard Worker }
593*bb4ee6a4SAndroid Build Coastguard Worker
594*bb4ee6a4SAndroid Build Coastguard Worker impl<T: PciDevice> BusDevice for T {
debug_label(&self) -> String595*bb4ee6a4SAndroid Build Coastguard Worker fn debug_label(&self) -> String {
596*bb4ee6a4SAndroid Build Coastguard Worker PciDevice::debug_label(self)
597*bb4ee6a4SAndroid Build Coastguard Worker }
598*bb4ee6a4SAndroid Build Coastguard Worker
device_id(&self) -> DeviceId599*bb4ee6a4SAndroid Build Coastguard Worker fn device_id(&self) -> DeviceId {
600*bb4ee6a4SAndroid Build Coastguard Worker // Use the PCI ID for PCI devices, which contains the PCI vendor ID and the PCI device ID
601*bb4ee6a4SAndroid Build Coastguard Worker let pci_id: PciId = PciDevice::read_config_register(self, PCI_ID_REG).into();
602*bb4ee6a4SAndroid Build Coastguard Worker pci_id.into()
603*bb4ee6a4SAndroid Build Coastguard Worker }
604*bb4ee6a4SAndroid Build Coastguard Worker
read(&mut self, info: BusAccessInfo, data: &mut [u8])605*bb4ee6a4SAndroid Build Coastguard Worker fn read(&mut self, info: BusAccessInfo, data: &mut [u8]) {
606*bb4ee6a4SAndroid Build Coastguard Worker if let Some((bar_index, offset)) = find_bar_and_offset(self, info.address, data.len()) {
607*bb4ee6a4SAndroid Build Coastguard Worker self.read_bar(bar_index, offset, data);
608*bb4ee6a4SAndroid Build Coastguard Worker } else {
609*bb4ee6a4SAndroid Build Coastguard Worker error!("PciDevice::read({:#x}) did not match a BAR", info.address);
610*bb4ee6a4SAndroid Build Coastguard Worker }
611*bb4ee6a4SAndroid Build Coastguard Worker }
612*bb4ee6a4SAndroid Build Coastguard Worker
write(&mut self, info: BusAccessInfo, data: &[u8])613*bb4ee6a4SAndroid Build Coastguard Worker fn write(&mut self, info: BusAccessInfo, data: &[u8]) {
614*bb4ee6a4SAndroid Build Coastguard Worker if let Some((bar_index, offset)) = find_bar_and_offset(self, info.address, data.len()) {
615*bb4ee6a4SAndroid Build Coastguard Worker self.write_bar(bar_index, offset, data);
616*bb4ee6a4SAndroid Build Coastguard Worker } else {
617*bb4ee6a4SAndroid Build Coastguard Worker error!("PciDevice::write({:#x}) did not match a BAR", info.address);
618*bb4ee6a4SAndroid Build Coastguard Worker }
619*bb4ee6a4SAndroid Build Coastguard Worker }
620*bb4ee6a4SAndroid Build Coastguard Worker
config_register_write( &mut self, reg_idx: usize, offset: u64, data: &[u8], ) -> ConfigWriteResult621*bb4ee6a4SAndroid Build Coastguard Worker fn config_register_write(
622*bb4ee6a4SAndroid Build Coastguard Worker &mut self,
623*bb4ee6a4SAndroid Build Coastguard Worker reg_idx: usize,
624*bb4ee6a4SAndroid Build Coastguard Worker offset: u64,
625*bb4ee6a4SAndroid Build Coastguard Worker data: &[u8],
626*bb4ee6a4SAndroid Build Coastguard Worker ) -> ConfigWriteResult {
627*bb4ee6a4SAndroid Build Coastguard Worker if offset as usize + data.len() > 4 {
628*bb4ee6a4SAndroid Build Coastguard Worker return Default::default();
629*bb4ee6a4SAndroid Build Coastguard Worker }
630*bb4ee6a4SAndroid Build Coastguard Worker
631*bb4ee6a4SAndroid Build Coastguard Worker trace!(
632*bb4ee6a4SAndroid Build Coastguard Worker "reg_idx {:02X} data {:08X}",
633*bb4ee6a4SAndroid Build Coastguard Worker reg_idx,
634*bb4ee6a4SAndroid Build Coastguard Worker trace_data(data, offset)
635*bb4ee6a4SAndroid Build Coastguard Worker );
636*bb4ee6a4SAndroid Build Coastguard Worker
637*bb4ee6a4SAndroid Build Coastguard Worker let old_command_reg = self.read_config_register(COMMAND_REG);
638*bb4ee6a4SAndroid Build Coastguard Worker let old_ranges =
639*bb4ee6a4SAndroid Build Coastguard Worker if old_command_reg & (COMMAND_REG_MEMORY_SPACE_MASK | COMMAND_REG_IO_SPACE_MASK) != 0 {
640*bb4ee6a4SAndroid Build Coastguard Worker self.get_ranges()
641*bb4ee6a4SAndroid Build Coastguard Worker } else {
642*bb4ee6a4SAndroid Build Coastguard Worker Vec::new()
643*bb4ee6a4SAndroid Build Coastguard Worker };
644*bb4ee6a4SAndroid Build Coastguard Worker
645*bb4ee6a4SAndroid Build Coastguard Worker self.write_config_register(reg_idx, offset, data);
646*bb4ee6a4SAndroid Build Coastguard Worker
647*bb4ee6a4SAndroid Build Coastguard Worker let new_command_reg = self.read_config_register(COMMAND_REG);
648*bb4ee6a4SAndroid Build Coastguard Worker let new_ranges =
649*bb4ee6a4SAndroid Build Coastguard Worker if new_command_reg & (COMMAND_REG_MEMORY_SPACE_MASK | COMMAND_REG_IO_SPACE_MASK) != 0 {
650*bb4ee6a4SAndroid Build Coastguard Worker self.get_ranges()
651*bb4ee6a4SAndroid Build Coastguard Worker } else {
652*bb4ee6a4SAndroid Build Coastguard Worker Vec::new()
653*bb4ee6a4SAndroid Build Coastguard Worker };
654*bb4ee6a4SAndroid Build Coastguard Worker
655*bb4ee6a4SAndroid Build Coastguard Worker let (mmio_remove, mmio_add) = update_ranges(
656*bb4ee6a4SAndroid Build Coastguard Worker old_command_reg & COMMAND_REG_MEMORY_SPACE_MASK != 0,
657*bb4ee6a4SAndroid Build Coastguard Worker new_command_reg & COMMAND_REG_MEMORY_SPACE_MASK != 0,
658*bb4ee6a4SAndroid Build Coastguard Worker BusType::Mmio,
659*bb4ee6a4SAndroid Build Coastguard Worker &old_ranges,
660*bb4ee6a4SAndroid Build Coastguard Worker &new_ranges,
661*bb4ee6a4SAndroid Build Coastguard Worker );
662*bb4ee6a4SAndroid Build Coastguard Worker
663*bb4ee6a4SAndroid Build Coastguard Worker let (io_remove, io_add) = update_ranges(
664*bb4ee6a4SAndroid Build Coastguard Worker old_command_reg & COMMAND_REG_IO_SPACE_MASK != 0,
665*bb4ee6a4SAndroid Build Coastguard Worker new_command_reg & COMMAND_REG_IO_SPACE_MASK != 0,
666*bb4ee6a4SAndroid Build Coastguard Worker BusType::Io,
667*bb4ee6a4SAndroid Build Coastguard Worker &old_ranges,
668*bb4ee6a4SAndroid Build Coastguard Worker &new_ranges,
669*bb4ee6a4SAndroid Build Coastguard Worker );
670*bb4ee6a4SAndroid Build Coastguard Worker
671*bb4ee6a4SAndroid Build Coastguard Worker ConfigWriteResult {
672*bb4ee6a4SAndroid Build Coastguard Worker mmio_remove,
673*bb4ee6a4SAndroid Build Coastguard Worker mmio_add,
674*bb4ee6a4SAndroid Build Coastguard Worker io_remove,
675*bb4ee6a4SAndroid Build Coastguard Worker io_add,
676*bb4ee6a4SAndroid Build Coastguard Worker removed_pci_devices: self.get_removed_children_devices(),
677*bb4ee6a4SAndroid Build Coastguard Worker }
678*bb4ee6a4SAndroid Build Coastguard Worker }
679*bb4ee6a4SAndroid Build Coastguard Worker
config_register_read(&self, reg_idx: usize) -> u32680*bb4ee6a4SAndroid Build Coastguard Worker fn config_register_read(&self, reg_idx: usize) -> u32 {
681*bb4ee6a4SAndroid Build Coastguard Worker self.read_config_register(reg_idx)
682*bb4ee6a4SAndroid Build Coastguard Worker }
683*bb4ee6a4SAndroid Build Coastguard Worker
init_pci_config_mapping(&mut self, shmem: &SharedMemory, base: usize, len: usize) -> bool684*bb4ee6a4SAndroid Build Coastguard Worker fn init_pci_config_mapping(&mut self, shmem: &SharedMemory, base: usize, len: usize) -> bool {
685*bb4ee6a4SAndroid Build Coastguard Worker match self.setup_pci_config_mapping(shmem, base, len) {
686*bb4ee6a4SAndroid Build Coastguard Worker Ok(res) => res,
687*bb4ee6a4SAndroid Build Coastguard Worker Err(err) => {
688*bb4ee6a4SAndroid Build Coastguard Worker warn!("Failed to create PCI mapping: {:#}", err);
689*bb4ee6a4SAndroid Build Coastguard Worker false
690*bb4ee6a4SAndroid Build Coastguard Worker }
691*bb4ee6a4SAndroid Build Coastguard Worker }
692*bb4ee6a4SAndroid Build Coastguard Worker }
693*bb4ee6a4SAndroid Build Coastguard Worker
virtual_config_register_write(&mut self, reg_idx: usize, value: u32)694*bb4ee6a4SAndroid Build Coastguard Worker fn virtual_config_register_write(&mut self, reg_idx: usize, value: u32) {
695*bb4ee6a4SAndroid Build Coastguard Worker self.write_virtual_config_register(reg_idx, value);
696*bb4ee6a4SAndroid Build Coastguard Worker }
697*bb4ee6a4SAndroid Build Coastguard Worker
virtual_config_register_read(&self, reg_idx: usize) -> u32698*bb4ee6a4SAndroid Build Coastguard Worker fn virtual_config_register_read(&self, reg_idx: usize) -> u32 {
699*bb4ee6a4SAndroid Build Coastguard Worker self.read_virtual_config_register(reg_idx)
700*bb4ee6a4SAndroid Build Coastguard Worker }
701*bb4ee6a4SAndroid Build Coastguard Worker
on_sandboxed(&mut self)702*bb4ee6a4SAndroid Build Coastguard Worker fn on_sandboxed(&mut self) {
703*bb4ee6a4SAndroid Build Coastguard Worker self.on_device_sandboxed();
704*bb4ee6a4SAndroid Build Coastguard Worker }
705*bb4ee6a4SAndroid Build Coastguard Worker
get_ranges(&self) -> Vec<(BusRange, BusType)>706*bb4ee6a4SAndroid Build Coastguard Worker fn get_ranges(&self) -> Vec<(BusRange, BusType)> {
707*bb4ee6a4SAndroid Build Coastguard Worker let mut ranges = Vec::new();
708*bb4ee6a4SAndroid Build Coastguard Worker for bar_num in 0..NUM_BAR_REGS {
709*bb4ee6a4SAndroid Build Coastguard Worker if let Some(bar) = self.get_bar_configuration(bar_num) {
710*bb4ee6a4SAndroid Build Coastguard Worker let bus_type = if bar.is_memory() {
711*bb4ee6a4SAndroid Build Coastguard Worker BusType::Mmio
712*bb4ee6a4SAndroid Build Coastguard Worker } else {
713*bb4ee6a4SAndroid Build Coastguard Worker BusType::Io
714*bb4ee6a4SAndroid Build Coastguard Worker };
715*bb4ee6a4SAndroid Build Coastguard Worker ranges.push((
716*bb4ee6a4SAndroid Build Coastguard Worker BusRange {
717*bb4ee6a4SAndroid Build Coastguard Worker base: bar.address(),
718*bb4ee6a4SAndroid Build Coastguard Worker len: bar.size(),
719*bb4ee6a4SAndroid Build Coastguard Worker },
720*bb4ee6a4SAndroid Build Coastguard Worker bus_type,
721*bb4ee6a4SAndroid Build Coastguard Worker ));
722*bb4ee6a4SAndroid Build Coastguard Worker }
723*bb4ee6a4SAndroid Build Coastguard Worker }
724*bb4ee6a4SAndroid Build Coastguard Worker ranges
725*bb4ee6a4SAndroid Build Coastguard Worker }
726*bb4ee6a4SAndroid Build Coastguard Worker
727*bb4ee6a4SAndroid Build Coastguard Worker // Invoked when the device is destroyed
destroy_device(&mut self)728*bb4ee6a4SAndroid Build Coastguard Worker fn destroy_device(&mut self) {
729*bb4ee6a4SAndroid Build Coastguard Worker self.destroy_device()
730*bb4ee6a4SAndroid Build Coastguard Worker }
731*bb4ee6a4SAndroid Build Coastguard Worker
is_bridge(&self) -> Option<u8>732*bb4ee6a4SAndroid Build Coastguard Worker fn is_bridge(&self) -> Option<u8> {
733*bb4ee6a4SAndroid Build Coastguard Worker self.get_new_pci_bus().map(|bus| bus.lock().get_bus_num())
734*bb4ee6a4SAndroid Build Coastguard Worker }
735*bb4ee6a4SAndroid Build Coastguard Worker }
736*bb4ee6a4SAndroid Build Coastguard Worker
737*bb4ee6a4SAndroid Build Coastguard Worker impl<T: PciDevice + ?Sized> PciDevice for Box<T> {
738*bb4ee6a4SAndroid Build Coastguard Worker /// Returns a label suitable for debug output.
debug_label(&self) -> String739*bb4ee6a4SAndroid Build Coastguard Worker fn debug_label(&self) -> String {
740*bb4ee6a4SAndroid Build Coastguard Worker (**self).debug_label()
741*bb4ee6a4SAndroid Build Coastguard Worker }
preferred_address(&self) -> Option<PciAddress>742*bb4ee6a4SAndroid Build Coastguard Worker fn preferred_address(&self) -> Option<PciAddress> {
743*bb4ee6a4SAndroid Build Coastguard Worker (**self).preferred_address()
744*bb4ee6a4SAndroid Build Coastguard Worker }
allocate_address(&mut self, resources: &mut SystemAllocator) -> Result<PciAddress>745*bb4ee6a4SAndroid Build Coastguard Worker fn allocate_address(&mut self, resources: &mut SystemAllocator) -> Result<PciAddress> {
746*bb4ee6a4SAndroid Build Coastguard Worker (**self).allocate_address(resources)
747*bb4ee6a4SAndroid Build Coastguard Worker }
keep_rds(&self) -> Vec<RawDescriptor>748*bb4ee6a4SAndroid Build Coastguard Worker fn keep_rds(&self) -> Vec<RawDescriptor> {
749*bb4ee6a4SAndroid Build Coastguard Worker (**self).keep_rds()
750*bb4ee6a4SAndroid Build Coastguard Worker }
preferred_irq(&self) -> PreferredIrq751*bb4ee6a4SAndroid Build Coastguard Worker fn preferred_irq(&self) -> PreferredIrq {
752*bb4ee6a4SAndroid Build Coastguard Worker (**self).preferred_irq()
753*bb4ee6a4SAndroid Build Coastguard Worker }
assign_irq(&mut self, irq_evt: IrqLevelEvent, pin: PciInterruptPin, irq_num: u32)754*bb4ee6a4SAndroid Build Coastguard Worker fn assign_irq(&mut self, irq_evt: IrqLevelEvent, pin: PciInterruptPin, irq_num: u32) {
755*bb4ee6a4SAndroid Build Coastguard Worker (**self).assign_irq(irq_evt, pin, irq_num)
756*bb4ee6a4SAndroid Build Coastguard Worker }
allocate_io_bars(&mut self, resources: &mut SystemAllocator) -> Result<Vec<BarRange>>757*bb4ee6a4SAndroid Build Coastguard Worker fn allocate_io_bars(&mut self, resources: &mut SystemAllocator) -> Result<Vec<BarRange>> {
758*bb4ee6a4SAndroid Build Coastguard Worker (**self).allocate_io_bars(resources)
759*bb4ee6a4SAndroid Build Coastguard Worker }
allocate_device_bars(&mut self, resources: &mut SystemAllocator) -> Result<Vec<BarRange>>760*bb4ee6a4SAndroid Build Coastguard Worker fn allocate_device_bars(&mut self, resources: &mut SystemAllocator) -> Result<Vec<BarRange>> {
761*bb4ee6a4SAndroid Build Coastguard Worker (**self).allocate_device_bars(resources)
762*bb4ee6a4SAndroid Build Coastguard Worker }
get_bar_configuration(&self, bar_num: usize) -> Option<PciBarConfiguration>763*bb4ee6a4SAndroid Build Coastguard Worker fn get_bar_configuration(&self, bar_num: usize) -> Option<PciBarConfiguration> {
764*bb4ee6a4SAndroid Build Coastguard Worker (**self).get_bar_configuration(bar_num)
765*bb4ee6a4SAndroid Build Coastguard Worker }
register_device_capabilities(&mut self) -> Result<()>766*bb4ee6a4SAndroid Build Coastguard Worker fn register_device_capabilities(&mut self) -> Result<()> {
767*bb4ee6a4SAndroid Build Coastguard Worker (**self).register_device_capabilities()
768*bb4ee6a4SAndroid Build Coastguard Worker }
read_virtual_config_register(&self, reg_idx: usize) -> u32769*bb4ee6a4SAndroid Build Coastguard Worker fn read_virtual_config_register(&self, reg_idx: usize) -> u32 {
770*bb4ee6a4SAndroid Build Coastguard Worker (**self).read_virtual_config_register(reg_idx)
771*bb4ee6a4SAndroid Build Coastguard Worker }
write_virtual_config_register(&mut self, reg_idx: usize, value: u32)772*bb4ee6a4SAndroid Build Coastguard Worker fn write_virtual_config_register(&mut self, reg_idx: usize, value: u32) {
773*bb4ee6a4SAndroid Build Coastguard Worker (**self).write_virtual_config_register(reg_idx, value)
774*bb4ee6a4SAndroid Build Coastguard Worker }
get_vm_memory_client(&self) -> Option<&VmMemoryClient>775*bb4ee6a4SAndroid Build Coastguard Worker fn get_vm_memory_client(&self) -> Option<&VmMemoryClient> {
776*bb4ee6a4SAndroid Build Coastguard Worker (**self).get_vm_memory_client()
777*bb4ee6a4SAndroid Build Coastguard Worker }
read_config_register(&self, reg_idx: usize) -> u32778*bb4ee6a4SAndroid Build Coastguard Worker fn read_config_register(&self, reg_idx: usize) -> u32 {
779*bb4ee6a4SAndroid Build Coastguard Worker (**self).read_config_register(reg_idx)
780*bb4ee6a4SAndroid Build Coastguard Worker }
write_config_register(&mut self, reg_idx: usize, offset: u64, data: &[u8])781*bb4ee6a4SAndroid Build Coastguard Worker fn write_config_register(&mut self, reg_idx: usize, offset: u64, data: &[u8]) {
782*bb4ee6a4SAndroid Build Coastguard Worker (**self).write_config_register(reg_idx, offset, data)
783*bb4ee6a4SAndroid Build Coastguard Worker }
setup_pci_config_mapping( &mut self, shmem: &SharedMemory, base: usize, len: usize, ) -> Result<bool>784*bb4ee6a4SAndroid Build Coastguard Worker fn setup_pci_config_mapping(
785*bb4ee6a4SAndroid Build Coastguard Worker &mut self,
786*bb4ee6a4SAndroid Build Coastguard Worker shmem: &SharedMemory,
787*bb4ee6a4SAndroid Build Coastguard Worker base: usize,
788*bb4ee6a4SAndroid Build Coastguard Worker len: usize,
789*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<bool> {
790*bb4ee6a4SAndroid Build Coastguard Worker (**self).setup_pci_config_mapping(shmem, base, len)
791*bb4ee6a4SAndroid Build Coastguard Worker }
read_bar(&mut self, bar_index: PciBarIndex, offset: u64, data: &mut [u8])792*bb4ee6a4SAndroid Build Coastguard Worker fn read_bar(&mut self, bar_index: PciBarIndex, offset: u64, data: &mut [u8]) {
793*bb4ee6a4SAndroid Build Coastguard Worker (**self).read_bar(bar_index, offset, data)
794*bb4ee6a4SAndroid Build Coastguard Worker }
write_bar(&mut self, bar_index: PciBarIndex, offset: u64, data: &[u8])795*bb4ee6a4SAndroid Build Coastguard Worker fn write_bar(&mut self, bar_index: PciBarIndex, offset: u64, data: &[u8]) {
796*bb4ee6a4SAndroid Build Coastguard Worker (**self).write_bar(bar_index, offset, data)
797*bb4ee6a4SAndroid Build Coastguard Worker }
798*bb4ee6a4SAndroid Build Coastguard Worker /// Invoked when the device is sandboxed.
on_device_sandboxed(&mut self)799*bb4ee6a4SAndroid Build Coastguard Worker fn on_device_sandboxed(&mut self) {
800*bb4ee6a4SAndroid Build Coastguard Worker (**self).on_device_sandboxed()
801*bb4ee6a4SAndroid Build Coastguard Worker }
802*bb4ee6a4SAndroid Build Coastguard Worker
803*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(target_arch = "x86_64")]
generate_acpi(&mut self, sdts: Vec<SDT>) -> Option<Vec<SDT>>804*bb4ee6a4SAndroid Build Coastguard Worker fn generate_acpi(&mut self, sdts: Vec<SDT>) -> Option<Vec<SDT>> {
805*bb4ee6a4SAndroid Build Coastguard Worker (**self).generate_acpi(sdts)
806*bb4ee6a4SAndroid Build Coastguard Worker }
807*bb4ee6a4SAndroid Build Coastguard Worker
generate_acpi_methods(&mut self) -> (Vec<u8>, Option<(u32, MemoryMapping)>)808*bb4ee6a4SAndroid Build Coastguard Worker fn generate_acpi_methods(&mut self) -> (Vec<u8>, Option<(u32, MemoryMapping)>) {
809*bb4ee6a4SAndroid Build Coastguard Worker (**self).generate_acpi_methods()
810*bb4ee6a4SAndroid Build Coastguard Worker }
811*bb4ee6a4SAndroid Build Coastguard Worker
set_gpe(&mut self, resources: &mut SystemAllocator) -> Option<u32>812*bb4ee6a4SAndroid Build Coastguard Worker fn set_gpe(&mut self, resources: &mut SystemAllocator) -> Option<u32> {
813*bb4ee6a4SAndroid Build Coastguard Worker (**self).set_gpe(resources)
814*bb4ee6a4SAndroid Build Coastguard Worker }
815*bb4ee6a4SAndroid Build Coastguard Worker
destroy_device(&mut self)816*bb4ee6a4SAndroid Build Coastguard Worker fn destroy_device(&mut self) {
817*bb4ee6a4SAndroid Build Coastguard Worker (**self).destroy_device();
818*bb4ee6a4SAndroid Build Coastguard Worker }
get_new_pci_bus(&self) -> Option<Arc<Mutex<PciBus>>>819*bb4ee6a4SAndroid Build Coastguard Worker fn get_new_pci_bus(&self) -> Option<Arc<Mutex<PciBus>>> {
820*bb4ee6a4SAndroid Build Coastguard Worker (**self).get_new_pci_bus()
821*bb4ee6a4SAndroid Build Coastguard Worker }
get_removed_children_devices(&self) -> Vec<PciAddress>822*bb4ee6a4SAndroid Build Coastguard Worker fn get_removed_children_devices(&self) -> Vec<PciAddress> {
823*bb4ee6a4SAndroid Build Coastguard Worker (**self).get_removed_children_devices()
824*bb4ee6a4SAndroid Build Coastguard Worker }
825*bb4ee6a4SAndroid Build Coastguard Worker
configure_bridge_window( &mut self, resources: &mut SystemAllocator, bar_ranges: &[BarRange], ) -> Result<Vec<BarRange>>826*bb4ee6a4SAndroid Build Coastguard Worker fn configure_bridge_window(
827*bb4ee6a4SAndroid Build Coastguard Worker &mut self,
828*bb4ee6a4SAndroid Build Coastguard Worker resources: &mut SystemAllocator,
829*bb4ee6a4SAndroid Build Coastguard Worker bar_ranges: &[BarRange],
830*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<Vec<BarRange>> {
831*bb4ee6a4SAndroid Build Coastguard Worker (**self).configure_bridge_window(resources, bar_ranges)
832*bb4ee6a4SAndroid Build Coastguard Worker }
833*bb4ee6a4SAndroid Build Coastguard Worker }
834*bb4ee6a4SAndroid Build Coastguard Worker
835*bb4ee6a4SAndroid Build Coastguard Worker impl<T: PciDevice + ?Sized> Suspendable for Box<T> {
snapshot(&mut self) -> anyhow::Result<serde_json::Value>836*bb4ee6a4SAndroid Build Coastguard Worker fn snapshot(&mut self) -> anyhow::Result<serde_json::Value> {
837*bb4ee6a4SAndroid Build Coastguard Worker (**self).snapshot()
838*bb4ee6a4SAndroid Build Coastguard Worker }
839*bb4ee6a4SAndroid Build Coastguard Worker
restore(&mut self, data: serde_json::Value) -> anyhow::Result<()>840*bb4ee6a4SAndroid Build Coastguard Worker fn restore(&mut self, data: serde_json::Value) -> anyhow::Result<()> {
841*bb4ee6a4SAndroid Build Coastguard Worker (**self).restore(data)
842*bb4ee6a4SAndroid Build Coastguard Worker }
843*bb4ee6a4SAndroid Build Coastguard Worker
sleep(&mut self) -> anyhow::Result<()>844*bb4ee6a4SAndroid Build Coastguard Worker fn sleep(&mut self) -> anyhow::Result<()> {
845*bb4ee6a4SAndroid Build Coastguard Worker (**self).sleep()
846*bb4ee6a4SAndroid Build Coastguard Worker }
847*bb4ee6a4SAndroid Build Coastguard Worker
wake(&mut self) -> anyhow::Result<()>848*bb4ee6a4SAndroid Build Coastguard Worker fn wake(&mut self) -> anyhow::Result<()> {
849*bb4ee6a4SAndroid Build Coastguard Worker (**self).wake()
850*bb4ee6a4SAndroid Build Coastguard Worker }
851*bb4ee6a4SAndroid Build Coastguard Worker }
852*bb4ee6a4SAndroid Build Coastguard Worker
853*bb4ee6a4SAndroid Build Coastguard Worker impl<T: 'static + PciDevice> BusDeviceObj for T {
as_pci_device(&self) -> Option<&dyn PciDevice>854*bb4ee6a4SAndroid Build Coastguard Worker fn as_pci_device(&self) -> Option<&dyn PciDevice> {
855*bb4ee6a4SAndroid Build Coastguard Worker Some(self)
856*bb4ee6a4SAndroid Build Coastguard Worker }
as_pci_device_mut(&mut self) -> Option<&mut dyn PciDevice>857*bb4ee6a4SAndroid Build Coastguard Worker fn as_pci_device_mut(&mut self) -> Option<&mut dyn PciDevice> {
858*bb4ee6a4SAndroid Build Coastguard Worker Some(self)
859*bb4ee6a4SAndroid Build Coastguard Worker }
into_pci_device(self: Box<Self>) -> Option<Box<dyn PciDevice>>860*bb4ee6a4SAndroid Build Coastguard Worker fn into_pci_device(self: Box<Self>) -> Option<Box<dyn PciDevice>> {
861*bb4ee6a4SAndroid Build Coastguard Worker Some(self)
862*bb4ee6a4SAndroid Build Coastguard Worker }
863*bb4ee6a4SAndroid Build Coastguard Worker }
864*bb4ee6a4SAndroid Build Coastguard Worker
865*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(test)]
866*bb4ee6a4SAndroid Build Coastguard Worker mod tests {
867*bb4ee6a4SAndroid Build Coastguard Worker use pci_configuration::PciBarPrefetchable;
868*bb4ee6a4SAndroid Build Coastguard Worker use pci_configuration::PciBarRegionType;
869*bb4ee6a4SAndroid Build Coastguard Worker use pci_configuration::PciClassCode;
870*bb4ee6a4SAndroid Build Coastguard Worker use pci_configuration::PciConfiguration;
871*bb4ee6a4SAndroid Build Coastguard Worker use pci_configuration::PciHeaderType;
872*bb4ee6a4SAndroid Build Coastguard Worker use pci_configuration::PciMultimediaSubclass;
873*bb4ee6a4SAndroid Build Coastguard Worker
874*bb4ee6a4SAndroid Build Coastguard Worker use super::*;
875*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::pci_configuration::BAR0_REG;
876*bb4ee6a4SAndroid Build Coastguard Worker
877*bb4ee6a4SAndroid Build Coastguard Worker const BAR0_SIZE: u64 = 0x1000;
878*bb4ee6a4SAndroid Build Coastguard Worker const BAR2_SIZE: u64 = 0x20;
879*bb4ee6a4SAndroid Build Coastguard Worker const BAR0_ADDR: u64 = 0xc0000000;
880*bb4ee6a4SAndroid Build Coastguard Worker const BAR2_ADDR: u64 = 0x800;
881*bb4ee6a4SAndroid Build Coastguard Worker
882*bb4ee6a4SAndroid Build Coastguard Worker struct TestDev {
883*bb4ee6a4SAndroid Build Coastguard Worker pub config_regs: PciConfiguration,
884*bb4ee6a4SAndroid Build Coastguard Worker }
885*bb4ee6a4SAndroid Build Coastguard Worker
886*bb4ee6a4SAndroid Build Coastguard Worker impl PciDevice for TestDev {
debug_label(&self) -> String887*bb4ee6a4SAndroid Build Coastguard Worker fn debug_label(&self) -> String {
888*bb4ee6a4SAndroid Build Coastguard Worker "test".to_owned()
889*bb4ee6a4SAndroid Build Coastguard Worker }
890*bb4ee6a4SAndroid Build Coastguard Worker
keep_rds(&self) -> Vec<RawDescriptor>891*bb4ee6a4SAndroid Build Coastguard Worker fn keep_rds(&self) -> Vec<RawDescriptor> {
892*bb4ee6a4SAndroid Build Coastguard Worker Vec::new()
893*bb4ee6a4SAndroid Build Coastguard Worker }
894*bb4ee6a4SAndroid Build Coastguard Worker
read_config_register(&self, reg_idx: usize) -> u32895*bb4ee6a4SAndroid Build Coastguard Worker fn read_config_register(&self, reg_idx: usize) -> u32 {
896*bb4ee6a4SAndroid Build Coastguard Worker self.config_regs.read_reg(reg_idx)
897*bb4ee6a4SAndroid Build Coastguard Worker }
898*bb4ee6a4SAndroid Build Coastguard Worker
write_config_register(&mut self, reg_idx: usize, offset: u64, data: &[u8])899*bb4ee6a4SAndroid Build Coastguard Worker fn write_config_register(&mut self, reg_idx: usize, offset: u64, data: &[u8]) {
900*bb4ee6a4SAndroid Build Coastguard Worker self.config_regs.write_reg(reg_idx, offset, data);
901*bb4ee6a4SAndroid Build Coastguard Worker }
902*bb4ee6a4SAndroid Build Coastguard Worker
read_bar(&mut self, _bar_index: PciBarIndex, _offset: u64, _data: &mut [u8])903*bb4ee6a4SAndroid Build Coastguard Worker fn read_bar(&mut self, _bar_index: PciBarIndex, _offset: u64, _data: &mut [u8]) {}
904*bb4ee6a4SAndroid Build Coastguard Worker
write_bar(&mut self, _bar_index: PciBarIndex, _offset: u64, _data: &[u8])905*bb4ee6a4SAndroid Build Coastguard Worker fn write_bar(&mut self, _bar_index: PciBarIndex, _offset: u64, _data: &[u8]) {}
906*bb4ee6a4SAndroid Build Coastguard Worker
allocate_address(&mut self, _resources: &mut SystemAllocator) -> Result<PciAddress>907*bb4ee6a4SAndroid Build Coastguard Worker fn allocate_address(&mut self, _resources: &mut SystemAllocator) -> Result<PciAddress> {
908*bb4ee6a4SAndroid Build Coastguard Worker Err(Error::PciAllocationFailed)
909*bb4ee6a4SAndroid Build Coastguard Worker }
910*bb4ee6a4SAndroid Build Coastguard Worker
get_bar_configuration(&self, bar_num: usize) -> Option<PciBarConfiguration>911*bb4ee6a4SAndroid Build Coastguard Worker fn get_bar_configuration(&self, bar_num: usize) -> Option<PciBarConfiguration> {
912*bb4ee6a4SAndroid Build Coastguard Worker self.config_regs.get_bar_configuration(bar_num)
913*bb4ee6a4SAndroid Build Coastguard Worker }
914*bb4ee6a4SAndroid Build Coastguard Worker }
915*bb4ee6a4SAndroid Build Coastguard Worker
916*bb4ee6a4SAndroid Build Coastguard Worker impl Suspendable for TestDev {}
917*bb4ee6a4SAndroid Build Coastguard Worker
918*bb4ee6a4SAndroid Build Coastguard Worker #[test]
config_write_result()919*bb4ee6a4SAndroid Build Coastguard Worker fn config_write_result() {
920*bb4ee6a4SAndroid Build Coastguard Worker let mut test_dev = TestDev {
921*bb4ee6a4SAndroid Build Coastguard Worker config_regs: PciConfiguration::new(
922*bb4ee6a4SAndroid Build Coastguard Worker 0x1234,
923*bb4ee6a4SAndroid Build Coastguard Worker 0xABCD,
924*bb4ee6a4SAndroid Build Coastguard Worker PciClassCode::MultimediaController,
925*bb4ee6a4SAndroid Build Coastguard Worker &PciMultimediaSubclass::AudioDevice,
926*bb4ee6a4SAndroid Build Coastguard Worker None,
927*bb4ee6a4SAndroid Build Coastguard Worker PciHeaderType::Device,
928*bb4ee6a4SAndroid Build Coastguard Worker 0x5678,
929*bb4ee6a4SAndroid Build Coastguard Worker 0xEF01,
930*bb4ee6a4SAndroid Build Coastguard Worker 0,
931*bb4ee6a4SAndroid Build Coastguard Worker ),
932*bb4ee6a4SAndroid Build Coastguard Worker };
933*bb4ee6a4SAndroid Build Coastguard Worker
934*bb4ee6a4SAndroid Build Coastguard Worker let _ = test_dev.config_regs.add_pci_bar(
935*bb4ee6a4SAndroid Build Coastguard Worker PciBarConfiguration::new(
936*bb4ee6a4SAndroid Build Coastguard Worker 0,
937*bb4ee6a4SAndroid Build Coastguard Worker BAR0_SIZE,
938*bb4ee6a4SAndroid Build Coastguard Worker PciBarRegionType::Memory64BitRegion,
939*bb4ee6a4SAndroid Build Coastguard Worker PciBarPrefetchable::Prefetchable,
940*bb4ee6a4SAndroid Build Coastguard Worker )
941*bb4ee6a4SAndroid Build Coastguard Worker .set_address(BAR0_ADDR),
942*bb4ee6a4SAndroid Build Coastguard Worker );
943*bb4ee6a4SAndroid Build Coastguard Worker let _ = test_dev.config_regs.add_pci_bar(
944*bb4ee6a4SAndroid Build Coastguard Worker PciBarConfiguration::new(
945*bb4ee6a4SAndroid Build Coastguard Worker 2,
946*bb4ee6a4SAndroid Build Coastguard Worker BAR2_SIZE,
947*bb4ee6a4SAndroid Build Coastguard Worker PciBarRegionType::IoRegion,
948*bb4ee6a4SAndroid Build Coastguard Worker PciBarPrefetchable::NotPrefetchable,
949*bb4ee6a4SAndroid Build Coastguard Worker )
950*bb4ee6a4SAndroid Build Coastguard Worker .set_address(BAR2_ADDR),
951*bb4ee6a4SAndroid Build Coastguard Worker );
952*bb4ee6a4SAndroid Build Coastguard Worker let bar0_range = BusRange {
953*bb4ee6a4SAndroid Build Coastguard Worker base: BAR0_ADDR,
954*bb4ee6a4SAndroid Build Coastguard Worker len: BAR0_SIZE,
955*bb4ee6a4SAndroid Build Coastguard Worker };
956*bb4ee6a4SAndroid Build Coastguard Worker let bar2_range = BusRange {
957*bb4ee6a4SAndroid Build Coastguard Worker base: BAR2_ADDR,
958*bb4ee6a4SAndroid Build Coastguard Worker len: BAR2_SIZE,
959*bb4ee6a4SAndroid Build Coastguard Worker };
960*bb4ee6a4SAndroid Build Coastguard Worker
961*bb4ee6a4SAndroid Build Coastguard Worker // Initialize command register to an all-zeroes value.
962*bb4ee6a4SAndroid Build Coastguard Worker test_dev.config_register_write(COMMAND_REG, 0, &0u32.to_le_bytes());
963*bb4ee6a4SAndroid Build Coastguard Worker
964*bb4ee6a4SAndroid Build Coastguard Worker // Enable IO space access (bit 0 of command register).
965*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
966*bb4ee6a4SAndroid Build Coastguard Worker test_dev.config_register_write(COMMAND_REG, 0, &1u32.to_le_bytes()),
967*bb4ee6a4SAndroid Build Coastguard Worker ConfigWriteResult {
968*bb4ee6a4SAndroid Build Coastguard Worker mmio_remove: Vec::new(),
969*bb4ee6a4SAndroid Build Coastguard Worker mmio_add: Vec::new(),
970*bb4ee6a4SAndroid Build Coastguard Worker io_remove: Vec::new(),
971*bb4ee6a4SAndroid Build Coastguard Worker io_add: vec![bar2_range],
972*bb4ee6a4SAndroid Build Coastguard Worker removed_pci_devices: Vec::new(),
973*bb4ee6a4SAndroid Build Coastguard Worker }
974*bb4ee6a4SAndroid Build Coastguard Worker );
975*bb4ee6a4SAndroid Build Coastguard Worker
976*bb4ee6a4SAndroid Build Coastguard Worker // Enable memory space access (bit 1 of command register).
977*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
978*bb4ee6a4SAndroid Build Coastguard Worker test_dev.config_register_write(COMMAND_REG, 0, &3u32.to_le_bytes()),
979*bb4ee6a4SAndroid Build Coastguard Worker ConfigWriteResult {
980*bb4ee6a4SAndroid Build Coastguard Worker mmio_remove: Vec::new(),
981*bb4ee6a4SAndroid Build Coastguard Worker mmio_add: vec![bar0_range],
982*bb4ee6a4SAndroid Build Coastguard Worker io_remove: Vec::new(),
983*bb4ee6a4SAndroid Build Coastguard Worker io_add: Vec::new(),
984*bb4ee6a4SAndroid Build Coastguard Worker removed_pci_devices: Vec::new(),
985*bb4ee6a4SAndroid Build Coastguard Worker }
986*bb4ee6a4SAndroid Build Coastguard Worker );
987*bb4ee6a4SAndroid Build Coastguard Worker
988*bb4ee6a4SAndroid Build Coastguard Worker // Rewrite the same IO + mem value again (result should be no change).
989*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
990*bb4ee6a4SAndroid Build Coastguard Worker test_dev.config_register_write(COMMAND_REG, 0, &3u32.to_le_bytes()),
991*bb4ee6a4SAndroid Build Coastguard Worker ConfigWriteResult {
992*bb4ee6a4SAndroid Build Coastguard Worker mmio_remove: Vec::new(),
993*bb4ee6a4SAndroid Build Coastguard Worker mmio_add: Vec::new(),
994*bb4ee6a4SAndroid Build Coastguard Worker io_remove: Vec::new(),
995*bb4ee6a4SAndroid Build Coastguard Worker io_add: Vec::new(),
996*bb4ee6a4SAndroid Build Coastguard Worker removed_pci_devices: Vec::new(),
997*bb4ee6a4SAndroid Build Coastguard Worker }
998*bb4ee6a4SAndroid Build Coastguard Worker );
999*bb4ee6a4SAndroid Build Coastguard Worker
1000*bb4ee6a4SAndroid Build Coastguard Worker // Disable IO space access, leaving mem enabled.
1001*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
1002*bb4ee6a4SAndroid Build Coastguard Worker test_dev.config_register_write(COMMAND_REG, 0, &2u32.to_le_bytes()),
1003*bb4ee6a4SAndroid Build Coastguard Worker ConfigWriteResult {
1004*bb4ee6a4SAndroid Build Coastguard Worker mmio_remove: Vec::new(),
1005*bb4ee6a4SAndroid Build Coastguard Worker mmio_add: Vec::new(),
1006*bb4ee6a4SAndroid Build Coastguard Worker io_remove: vec![bar2_range],
1007*bb4ee6a4SAndroid Build Coastguard Worker io_add: Vec::new(),
1008*bb4ee6a4SAndroid Build Coastguard Worker removed_pci_devices: Vec::new(),
1009*bb4ee6a4SAndroid Build Coastguard Worker }
1010*bb4ee6a4SAndroid Build Coastguard Worker );
1011*bb4ee6a4SAndroid Build Coastguard Worker
1012*bb4ee6a4SAndroid Build Coastguard Worker // Disable mem space access.
1013*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
1014*bb4ee6a4SAndroid Build Coastguard Worker test_dev.config_register_write(COMMAND_REG, 0, &0u32.to_le_bytes()),
1015*bb4ee6a4SAndroid Build Coastguard Worker ConfigWriteResult {
1016*bb4ee6a4SAndroid Build Coastguard Worker mmio_remove: vec![bar0_range],
1017*bb4ee6a4SAndroid Build Coastguard Worker mmio_add: Vec::new(),
1018*bb4ee6a4SAndroid Build Coastguard Worker io_remove: Vec::new(),
1019*bb4ee6a4SAndroid Build Coastguard Worker io_add: Vec::new(),
1020*bb4ee6a4SAndroid Build Coastguard Worker removed_pci_devices: Vec::new(),
1021*bb4ee6a4SAndroid Build Coastguard Worker }
1022*bb4ee6a4SAndroid Build Coastguard Worker );
1023*bb4ee6a4SAndroid Build Coastguard Worker
1024*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(test_dev.get_ranges(), Vec::new());
1025*bb4ee6a4SAndroid Build Coastguard Worker
1026*bb4ee6a4SAndroid Build Coastguard Worker // Re-enable mem and IO space.
1027*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
1028*bb4ee6a4SAndroid Build Coastguard Worker test_dev.config_register_write(COMMAND_REG, 0, &3u32.to_le_bytes()),
1029*bb4ee6a4SAndroid Build Coastguard Worker ConfigWriteResult {
1030*bb4ee6a4SAndroid Build Coastguard Worker mmio_remove: Vec::new(),
1031*bb4ee6a4SAndroid Build Coastguard Worker mmio_add: vec![bar0_range],
1032*bb4ee6a4SAndroid Build Coastguard Worker io_remove: Vec::new(),
1033*bb4ee6a4SAndroid Build Coastguard Worker io_add: vec![bar2_range],
1034*bb4ee6a4SAndroid Build Coastguard Worker removed_pci_devices: Vec::new(),
1035*bb4ee6a4SAndroid Build Coastguard Worker }
1036*bb4ee6a4SAndroid Build Coastguard Worker );
1037*bb4ee6a4SAndroid Build Coastguard Worker
1038*bb4ee6a4SAndroid Build Coastguard Worker // Change Bar0's address
1039*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
1040*bb4ee6a4SAndroid Build Coastguard Worker test_dev.config_register_write(BAR0_REG, 0, &0xD0000000u32.to_le_bytes()),
1041*bb4ee6a4SAndroid Build Coastguard Worker ConfigWriteResult {
1042*bb4ee6a4SAndroid Build Coastguard Worker mmio_remove: vec!(bar0_range),
1043*bb4ee6a4SAndroid Build Coastguard Worker mmio_add: vec![BusRange {
1044*bb4ee6a4SAndroid Build Coastguard Worker base: 0xD0000000,
1045*bb4ee6a4SAndroid Build Coastguard Worker len: BAR0_SIZE
1046*bb4ee6a4SAndroid Build Coastguard Worker }],
1047*bb4ee6a4SAndroid Build Coastguard Worker io_remove: Vec::new(),
1048*bb4ee6a4SAndroid Build Coastguard Worker io_add: Vec::new(),
1049*bb4ee6a4SAndroid Build Coastguard Worker removed_pci_devices: Vec::new(),
1050*bb4ee6a4SAndroid Build Coastguard Worker }
1051*bb4ee6a4SAndroid Build Coastguard Worker );
1052*bb4ee6a4SAndroid Build Coastguard Worker }
1053*bb4ee6a4SAndroid Build Coastguard Worker
1054*bb4ee6a4SAndroid Build Coastguard Worker #[test]
find_bar()1055*bb4ee6a4SAndroid Build Coastguard Worker fn find_bar() {
1056*bb4ee6a4SAndroid Build Coastguard Worker let mut dev = TestDev {
1057*bb4ee6a4SAndroid Build Coastguard Worker config_regs: PciConfiguration::new(
1058*bb4ee6a4SAndroid Build Coastguard Worker 0x1234,
1059*bb4ee6a4SAndroid Build Coastguard Worker 0xABCD,
1060*bb4ee6a4SAndroid Build Coastguard Worker PciClassCode::MultimediaController,
1061*bb4ee6a4SAndroid Build Coastguard Worker &PciMultimediaSubclass::AudioDevice,
1062*bb4ee6a4SAndroid Build Coastguard Worker None,
1063*bb4ee6a4SAndroid Build Coastguard Worker PciHeaderType::Device,
1064*bb4ee6a4SAndroid Build Coastguard Worker 0x5678,
1065*bb4ee6a4SAndroid Build Coastguard Worker 0xEF01,
1066*bb4ee6a4SAndroid Build Coastguard Worker 0,
1067*bb4ee6a4SAndroid Build Coastguard Worker ),
1068*bb4ee6a4SAndroid Build Coastguard Worker };
1069*bb4ee6a4SAndroid Build Coastguard Worker
1070*bb4ee6a4SAndroid Build Coastguard Worker let _ = dev.config_regs.add_pci_bar(
1071*bb4ee6a4SAndroid Build Coastguard Worker PciBarConfiguration::new(
1072*bb4ee6a4SAndroid Build Coastguard Worker 0,
1073*bb4ee6a4SAndroid Build Coastguard Worker BAR0_SIZE,
1074*bb4ee6a4SAndroid Build Coastguard Worker PciBarRegionType::Memory64BitRegion,
1075*bb4ee6a4SAndroid Build Coastguard Worker PciBarPrefetchable::Prefetchable,
1076*bb4ee6a4SAndroid Build Coastguard Worker )
1077*bb4ee6a4SAndroid Build Coastguard Worker .set_address(BAR0_ADDR),
1078*bb4ee6a4SAndroid Build Coastguard Worker );
1079*bb4ee6a4SAndroid Build Coastguard Worker let _ = dev.config_regs.add_pci_bar(
1080*bb4ee6a4SAndroid Build Coastguard Worker PciBarConfiguration::new(
1081*bb4ee6a4SAndroid Build Coastguard Worker 2,
1082*bb4ee6a4SAndroid Build Coastguard Worker BAR2_SIZE,
1083*bb4ee6a4SAndroid Build Coastguard Worker PciBarRegionType::IoRegion,
1084*bb4ee6a4SAndroid Build Coastguard Worker PciBarPrefetchable::NotPrefetchable,
1085*bb4ee6a4SAndroid Build Coastguard Worker )
1086*bb4ee6a4SAndroid Build Coastguard Worker .set_address(BAR2_ADDR),
1087*bb4ee6a4SAndroid Build Coastguard Worker );
1088*bb4ee6a4SAndroid Build Coastguard Worker
1089*bb4ee6a4SAndroid Build Coastguard Worker // No matching BAR
1090*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(find_bar_and_offset(&dev, 0, 4), None);
1091*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(find_bar_and_offset(&dev, 0xbfffffff, 4), None);
1092*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(find_bar_and_offset(&dev, 0xc0000000, 0), None);
1093*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(find_bar_and_offset(&dev, 0xc0000000, 0x1001), None);
1094*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(find_bar_and_offset(&dev, 0xffff_ffff_ffff_ffff, 1), None);
1095*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(find_bar_and_offset(&dev, 0xffff_ffff_ffff_ffff, 4), None);
1096*bb4ee6a4SAndroid Build Coastguard Worker
1097*bb4ee6a4SAndroid Build Coastguard Worker // BAR0 (64-bit memory BAR at 0xc0000000, size 0x1000)
1098*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(find_bar_and_offset(&dev, 0xc0000000, 4), Some((0, 0)));
1099*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(find_bar_and_offset(&dev, 0xc0000001, 4), Some((0, 1)));
1100*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(find_bar_and_offset(&dev, 0xc0000ffc, 4), Some((0, 0xffc)));
1101*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(find_bar_and_offset(&dev, 0xc0000ffd, 4), None);
1102*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(find_bar_and_offset(&dev, 0xc0000ffe, 4), None);
1103*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(find_bar_and_offset(&dev, 0xc0000fff, 4), None);
1104*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(find_bar_and_offset(&dev, 0xc0000fff, 1), Some((0, 0xfff)));
1105*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(find_bar_and_offset(&dev, 0xc0001000, 1), None);
1106*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(find_bar_and_offset(&dev, 0xc0000000, 0xfff), Some((0, 0)));
1107*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(find_bar_and_offset(&dev, 0xc0000000, 0x1000), Some((0, 0)));
1108*bb4ee6a4SAndroid Build Coastguard Worker
1109*bb4ee6a4SAndroid Build Coastguard Worker // BAR2 (I/O BAR)
1110*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(find_bar_and_offset(&dev, 0x800, 1), None);
1111*bb4ee6a4SAndroid Build Coastguard Worker }
1112*bb4ee6a4SAndroid Build Coastguard Worker }
1113