xref: /aosp_15_r20/external/crosvm/devices/src/bus.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2017 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 //! Handles routing to devices in an address space.
6*bb4ee6a4SAndroid Build Coastguard Worker 
7*bb4ee6a4SAndroid Build Coastguard Worker use std::cmp::Ord;
8*bb4ee6a4SAndroid Build Coastguard Worker use std::cmp::Ordering;
9*bb4ee6a4SAndroid Build Coastguard Worker use std::cmp::PartialEq;
10*bb4ee6a4SAndroid Build Coastguard Worker use std::cmp::PartialOrd;
11*bb4ee6a4SAndroid Build Coastguard Worker use std::collections::BTreeMap;
12*bb4ee6a4SAndroid Build Coastguard Worker use std::collections::BTreeSet;
13*bb4ee6a4SAndroid Build Coastguard Worker use std::fmt;
14*bb4ee6a4SAndroid Build Coastguard Worker use std::result;
15*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::Arc;
16*bb4ee6a4SAndroid Build Coastguard Worker 
17*bb4ee6a4SAndroid Build Coastguard Worker use anyhow::anyhow;
18*bb4ee6a4SAndroid Build Coastguard Worker use anyhow::Context;
19*bb4ee6a4SAndroid Build Coastguard Worker use base::debug;
20*bb4ee6a4SAndroid Build Coastguard Worker use base::error;
21*bb4ee6a4SAndroid Build Coastguard Worker use base::Event;
22*bb4ee6a4SAndroid Build Coastguard Worker use base::SharedMemory;
23*bb4ee6a4SAndroid Build Coastguard Worker use remain::sorted;
24*bb4ee6a4SAndroid Build Coastguard Worker use serde::Deserialize;
25*bb4ee6a4SAndroid Build Coastguard Worker use serde::Serialize;
26*bb4ee6a4SAndroid Build Coastguard Worker use sync::Mutex;
27*bb4ee6a4SAndroid Build Coastguard Worker use thiserror::Error;
28*bb4ee6a4SAndroid Build Coastguard Worker 
29*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "stats")]
30*bb4ee6a4SAndroid Build Coastguard Worker use crate::bus_stats::BusOperation;
31*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "stats")]
32*bb4ee6a4SAndroid Build Coastguard Worker use crate::BusStatistics;
33*bb4ee6a4SAndroid Build Coastguard Worker use crate::DeviceId;
34*bb4ee6a4SAndroid Build Coastguard Worker use crate::PciAddress;
35*bb4ee6a4SAndroid Build Coastguard Worker use crate::PciDevice;
36*bb4ee6a4SAndroid Build Coastguard Worker use crate::Suspendable;
37*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_os = "android", target_os = "linux"))]
38*bb4ee6a4SAndroid Build Coastguard Worker use crate::VfioPlatformDevice;
39*bb4ee6a4SAndroid Build Coastguard Worker use crate::VirtioMmioDevice;
40*bb4ee6a4SAndroid Build Coastguard Worker 
41*bb4ee6a4SAndroid Build Coastguard Worker /// Information about how a device was accessed.
42*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Copy, Clone, Eq, PartialEq, Debug, Serialize, Deserialize)]
43*bb4ee6a4SAndroid Build Coastguard Worker pub struct BusAccessInfo {
44*bb4ee6a4SAndroid Build Coastguard Worker     /// Offset from base address that the device was accessed at.
45*bb4ee6a4SAndroid Build Coastguard Worker     pub offset: u64,
46*bb4ee6a4SAndroid Build Coastguard Worker     /// Absolute address of the device's access in its address space.
47*bb4ee6a4SAndroid Build Coastguard Worker     pub address: u64,
48*bb4ee6a4SAndroid Build Coastguard Worker     /// ID of the entity requesting a device access, usually the VCPU id.
49*bb4ee6a4SAndroid Build Coastguard Worker     pub id: usize,
50*bb4ee6a4SAndroid Build Coastguard Worker }
51*bb4ee6a4SAndroid Build Coastguard Worker 
52*bb4ee6a4SAndroid Build Coastguard Worker // Implement `Display` for `MinMax`.
53*bb4ee6a4SAndroid Build Coastguard Worker impl std::fmt::Display for BusAccessInfo {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result54*bb4ee6a4SAndroid Build Coastguard Worker     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
55*bb4ee6a4SAndroid Build Coastguard Worker         write!(f, "{:?}", self)
56*bb4ee6a4SAndroid Build Coastguard Worker     }
57*bb4ee6a4SAndroid Build Coastguard Worker }
58*bb4ee6a4SAndroid Build Coastguard Worker 
59*bb4ee6a4SAndroid Build Coastguard Worker /// Result of a write to a device's PCI configuration space.
60*bb4ee6a4SAndroid Build Coastguard Worker /// This value represents the state change(s) that occurred due to the write.
61*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Clone, Debug, Default, PartialEq, Eq)]
62*bb4ee6a4SAndroid Build Coastguard Worker pub struct ConfigWriteResult {
63*bb4ee6a4SAndroid Build Coastguard Worker     /// The BusRange in the vector will be removed from mmio_bus
64*bb4ee6a4SAndroid Build Coastguard Worker     pub mmio_remove: Vec<BusRange>,
65*bb4ee6a4SAndroid Build Coastguard Worker 
66*bb4ee6a4SAndroid Build Coastguard Worker     /// The BusRange in the vector will be added into mmio_bus
67*bb4ee6a4SAndroid Build Coastguard Worker     pub mmio_add: Vec<BusRange>,
68*bb4ee6a4SAndroid Build Coastguard Worker 
69*bb4ee6a4SAndroid Build Coastguard Worker     /// The BusRange in the vector will be removed from io_bus
70*bb4ee6a4SAndroid Build Coastguard Worker     pub io_remove: Vec<BusRange>,
71*bb4ee6a4SAndroid Build Coastguard Worker 
72*bb4ee6a4SAndroid Build Coastguard Worker     /// The BusRange in the vector will be added into io_bus
73*bb4ee6a4SAndroid Build Coastguard Worker     pub io_add: Vec<BusRange>,
74*bb4ee6a4SAndroid Build Coastguard Worker 
75*bb4ee6a4SAndroid Build Coastguard Worker     /// Device specified at PciAddress will be removed after this config write
76*bb4ee6a4SAndroid Build Coastguard Worker     /// - `Vec<PciAddress>>`: specified device will be removed after this config write
77*bb4ee6a4SAndroid Build Coastguard Worker     pub removed_pci_devices: Vec<PciAddress>,
78*bb4ee6a4SAndroid Build Coastguard Worker }
79*bb4ee6a4SAndroid Build Coastguard Worker 
80*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize, PartialOrd, Ord)]
81*bb4ee6a4SAndroid Build Coastguard Worker pub enum BusType {
82*bb4ee6a4SAndroid Build Coastguard Worker     Mmio,
83*bb4ee6a4SAndroid Build Coastguard Worker     Io,
84*bb4ee6a4SAndroid Build Coastguard Worker }
85*bb4ee6a4SAndroid Build Coastguard Worker 
86*bb4ee6a4SAndroid Build Coastguard Worker /// Trait for devices that respond to reads or writes in an arbitrary address space.
87*bb4ee6a4SAndroid Build Coastguard Worker ///
88*bb4ee6a4SAndroid Build Coastguard Worker /// The device does not care where it exists in address space as each method is only given an offset
89*bb4ee6a4SAndroid Build Coastguard Worker /// into its allocated portion of address space.
90*bb4ee6a4SAndroid Build Coastguard Worker #[allow(unused_variables)]
91*bb4ee6a4SAndroid Build Coastguard Worker pub trait BusDevice: Send + Suspendable {
92*bb4ee6a4SAndroid Build Coastguard Worker     /// Returns a label suitable for debug output.
debug_label(&self) -> String93*bb4ee6a4SAndroid Build Coastguard Worker     fn debug_label(&self) -> String;
94*bb4ee6a4SAndroid Build Coastguard Worker     /// Returns a unique id per device type suitable for metrics gathering.
device_id(&self) -> DeviceId95*bb4ee6a4SAndroid Build Coastguard Worker     fn device_id(&self) -> DeviceId;
96*bb4ee6a4SAndroid Build Coastguard Worker     /// Reads at `offset` from this device
read(&mut self, offset: BusAccessInfo, data: &mut [u8])97*bb4ee6a4SAndroid Build Coastguard Worker     fn read(&mut self, offset: BusAccessInfo, data: &mut [u8]) {}
98*bb4ee6a4SAndroid Build Coastguard Worker     /// Writes at `offset` into this device
write(&mut self, offset: BusAccessInfo, data: &[u8])99*bb4ee6a4SAndroid Build Coastguard Worker     fn write(&mut self, offset: BusAccessInfo, data: &[u8]) {}
100*bb4ee6a4SAndroid Build Coastguard Worker     /// Sets a register in the configuration space. Only used by PCI.
101*bb4ee6a4SAndroid Build Coastguard Worker     /// * `reg_idx` - The index of the config register to modify.
102*bb4ee6a4SAndroid Build Coastguard Worker     /// * `offset` - Offset in to the register.
config_register_write( &mut self, reg_idx: usize, offset: u64, data: &[u8], ) -> ConfigWriteResult103*bb4ee6a4SAndroid Build Coastguard Worker     fn config_register_write(
104*bb4ee6a4SAndroid Build Coastguard Worker         &mut self,
105*bb4ee6a4SAndroid Build Coastguard Worker         reg_idx: usize,
106*bb4ee6a4SAndroid Build Coastguard Worker         offset: u64,
107*bb4ee6a4SAndroid Build Coastguard Worker         data: &[u8],
108*bb4ee6a4SAndroid Build Coastguard Worker     ) -> ConfigWriteResult {
109*bb4ee6a4SAndroid Build Coastguard Worker         ConfigWriteResult {
110*bb4ee6a4SAndroid Build Coastguard Worker             ..Default::default()
111*bb4ee6a4SAndroid Build Coastguard Worker         }
112*bb4ee6a4SAndroid Build Coastguard Worker     }
113*bb4ee6a4SAndroid Build Coastguard Worker     /// Gets a register from the configuration space. Only used by PCI.
114*bb4ee6a4SAndroid Build Coastguard Worker     /// * `reg_idx` - The index of the config register to read.
config_register_read(&self, reg_idx: usize) -> u32115*bb4ee6a4SAndroid Build Coastguard Worker     fn config_register_read(&self, reg_idx: usize) -> u32 {
116*bb4ee6a4SAndroid Build Coastguard Worker         0
117*bb4ee6a4SAndroid Build Coastguard Worker     }
118*bb4ee6a4SAndroid Build Coastguard Worker     /// Provides a memory region to back MMIO access to the configuration
119*bb4ee6a4SAndroid Build Coastguard Worker     /// space. If the device can keep the memory region up to date, then it
120*bb4ee6a4SAndroid Build Coastguard Worker     /// should return true, after which no more calls to config_register_read
121*bb4ee6a4SAndroid Build Coastguard Worker     /// will be made. Otherwise the device should return false.
122*bb4ee6a4SAndroid Build Coastguard Worker     ///
123*bb4ee6a4SAndroid Build Coastguard Worker     /// The device must set the header type register (0x0E) before returning
124*bb4ee6a4SAndroid Build Coastguard Worker     /// from this function, and must make no further modifications to it
125*bb4ee6a4SAndroid Build Coastguard Worker     /// after returning. This is to allow the caller to manage the multi-
126*bb4ee6a4SAndroid Build Coastguard Worker     /// function device bit without worrying about race conditions.
127*bb4ee6a4SAndroid Build Coastguard Worker     ///
128*bb4ee6a4SAndroid Build Coastguard Worker     /// * `shmem` - The shared memory to use for the configuration space.
129*bb4ee6a4SAndroid Build Coastguard Worker     /// * `base` - The base address of the memory region in shmem.
130*bb4ee6a4SAndroid Build Coastguard Worker     /// * `len` - The length of the memory region.
init_pci_config_mapping(&mut self, shmem: &SharedMemory, base: usize, len: usize) -> bool131*bb4ee6a4SAndroid Build Coastguard Worker     fn init_pci_config_mapping(&mut self, shmem: &SharedMemory, base: usize, len: usize) -> bool {
132*bb4ee6a4SAndroid Build Coastguard Worker         false
133*bb4ee6a4SAndroid Build Coastguard Worker     }
134*bb4ee6a4SAndroid Build Coastguard Worker     /// Sets a register in the virtual config space. Only used by PCI.
135*bb4ee6a4SAndroid Build Coastguard Worker     /// * `reg_idx` - The index of the config register to modify.
136*bb4ee6a4SAndroid Build Coastguard Worker     /// * `value` - The value to be written.
virtual_config_register_write(&mut self, reg_idx: usize, value: u32)137*bb4ee6a4SAndroid Build Coastguard Worker     fn virtual_config_register_write(&mut self, reg_idx: usize, value: u32) {}
138*bb4ee6a4SAndroid Build Coastguard Worker     /// Gets a register from the virtual config space. Only used by PCI.
139*bb4ee6a4SAndroid Build Coastguard Worker     /// * `reg_idx` - The index of the config register to read.
virtual_config_register_read(&self, reg_idx: usize) -> u32140*bb4ee6a4SAndroid Build Coastguard Worker     fn virtual_config_register_read(&self, reg_idx: usize) -> u32 {
141*bb4ee6a4SAndroid Build Coastguard Worker         0
142*bb4ee6a4SAndroid Build Coastguard Worker     }
143*bb4ee6a4SAndroid Build Coastguard Worker     /// Invoked when the device is sandboxed.
on_sandboxed(&mut self)144*bb4ee6a4SAndroid Build Coastguard Worker     fn on_sandboxed(&mut self) {}
145*bb4ee6a4SAndroid Build Coastguard Worker 
146*bb4ee6a4SAndroid Build Coastguard Worker     /// Gets a list of all ranges registered by this BusDevice.
get_ranges(&self) -> Vec<(BusRange, BusType)>147*bb4ee6a4SAndroid Build Coastguard Worker     fn get_ranges(&self) -> Vec<(BusRange, BusType)> {
148*bb4ee6a4SAndroid Build Coastguard Worker         Vec::new()
149*bb4ee6a4SAndroid Build Coastguard Worker     }
150*bb4ee6a4SAndroid Build Coastguard Worker 
151*bb4ee6a4SAndroid Build Coastguard Worker     /// Invoked when the device is destroyed
destroy_device(&mut self)152*bb4ee6a4SAndroid Build Coastguard Worker     fn destroy_device(&mut self) {}
153*bb4ee6a4SAndroid Build Coastguard Worker 
154*bb4ee6a4SAndroid Build Coastguard Worker     /// Returns the secondary bus number if this bus device is pci bridge
is_bridge(&self) -> Option<u8>155*bb4ee6a4SAndroid Build Coastguard Worker     fn is_bridge(&self) -> Option<u8> {
156*bb4ee6a4SAndroid Build Coastguard Worker         None
157*bb4ee6a4SAndroid Build Coastguard Worker     }
158*bb4ee6a4SAndroid Build Coastguard Worker }
159*bb4ee6a4SAndroid Build Coastguard Worker 
160*bb4ee6a4SAndroid Build Coastguard Worker pub trait BusDeviceSync: BusDevice + Sync {
read(&self, offset: BusAccessInfo, data: &mut [u8])161*bb4ee6a4SAndroid Build Coastguard Worker     fn read(&self, offset: BusAccessInfo, data: &mut [u8]);
write(&self, offset: BusAccessInfo, data: &[u8])162*bb4ee6a4SAndroid Build Coastguard Worker     fn write(&self, offset: BusAccessInfo, data: &[u8]);
snapshot_sync(&self) -> anyhow::Result<serde_json::Value>163*bb4ee6a4SAndroid Build Coastguard Worker     fn snapshot_sync(&self) -> anyhow::Result<serde_json::Value> {
164*bb4ee6a4SAndroid Build Coastguard Worker         Err(anyhow!(
165*bb4ee6a4SAndroid Build Coastguard Worker             "snapshot_sync not implemented for {}",
166*bb4ee6a4SAndroid Build Coastguard Worker             std::any::type_name::<Self>()
167*bb4ee6a4SAndroid Build Coastguard Worker         ))
168*bb4ee6a4SAndroid Build Coastguard Worker     }
169*bb4ee6a4SAndroid Build Coastguard Worker     /// Load a saved snapshot of an image.
restore_sync(&self, _data: serde_json::Value) -> anyhow::Result<()>170*bb4ee6a4SAndroid Build Coastguard Worker     fn restore_sync(&self, _data: serde_json::Value) -> anyhow::Result<()> {
171*bb4ee6a4SAndroid Build Coastguard Worker         Err(anyhow!(
172*bb4ee6a4SAndroid Build Coastguard Worker             "restore_sync not implemented for {}",
173*bb4ee6a4SAndroid Build Coastguard Worker             std::any::type_name::<Self>()
174*bb4ee6a4SAndroid Build Coastguard Worker         ))
175*bb4ee6a4SAndroid Build Coastguard Worker     }
176*bb4ee6a4SAndroid Build Coastguard Worker     /// Stop all threads related to the device.
177*bb4ee6a4SAndroid Build Coastguard Worker     /// Sleep should be idempotent.
sleep_sync(&self) -> anyhow::Result<()>178*bb4ee6a4SAndroid Build Coastguard Worker     fn sleep_sync(&self) -> anyhow::Result<()> {
179*bb4ee6a4SAndroid Build Coastguard Worker         Err(anyhow!(
180*bb4ee6a4SAndroid Build Coastguard Worker             "sleep_sync not implemented for {}",
181*bb4ee6a4SAndroid Build Coastguard Worker             std::any::type_name::<Self>()
182*bb4ee6a4SAndroid Build Coastguard Worker         ))
183*bb4ee6a4SAndroid Build Coastguard Worker     }
184*bb4ee6a4SAndroid Build Coastguard Worker     /// Create/Resume all threads related to the device.
185*bb4ee6a4SAndroid Build Coastguard Worker     /// Wake should be idempotent.
wake_sync(&self) -> anyhow::Result<()>186*bb4ee6a4SAndroid Build Coastguard Worker     fn wake_sync(&self) -> anyhow::Result<()> {
187*bb4ee6a4SAndroid Build Coastguard Worker         Err(anyhow!(
188*bb4ee6a4SAndroid Build Coastguard Worker             "wake_sync not implemented for {}",
189*bb4ee6a4SAndroid Build Coastguard Worker             std::any::type_name::<Self>()
190*bb4ee6a4SAndroid Build Coastguard Worker         ))
191*bb4ee6a4SAndroid Build Coastguard Worker     }
192*bb4ee6a4SAndroid Build Coastguard Worker }
193*bb4ee6a4SAndroid Build Coastguard Worker 
194*bb4ee6a4SAndroid Build Coastguard Worker pub trait BusResumeDevice: Send {
195*bb4ee6a4SAndroid Build Coastguard Worker     /// notify the devices which are invoked
196*bb4ee6a4SAndroid Build Coastguard Worker     /// before the VM resumes form suspend.
resume_imminent(&mut self)197*bb4ee6a4SAndroid Build Coastguard Worker     fn resume_imminent(&mut self) {}
198*bb4ee6a4SAndroid Build Coastguard Worker }
199*bb4ee6a4SAndroid Build Coastguard Worker 
200*bb4ee6a4SAndroid Build Coastguard Worker /// The key to identify hotplug device from host view.
201*bb4ee6a4SAndroid Build Coastguard Worker /// like host sysfs path for vfio pci device, host disk file
202*bb4ee6a4SAndroid Build Coastguard Worker /// path for virtio block device
203*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
204*bb4ee6a4SAndroid Build Coastguard Worker pub enum HotPlugKey {
205*bb4ee6a4SAndroid Build Coastguard Worker     HostUpstreamPort { host_addr: PciAddress },
206*bb4ee6a4SAndroid Build Coastguard Worker     HostDownstreamPort { host_addr: PciAddress },
207*bb4ee6a4SAndroid Build Coastguard Worker     HostVfio { host_addr: PciAddress },
208*bb4ee6a4SAndroid Build Coastguard Worker     GuestDevice { guest_addr: PciAddress },
209*bb4ee6a4SAndroid Build Coastguard Worker }
210*bb4ee6a4SAndroid Build Coastguard Worker 
211*bb4ee6a4SAndroid Build Coastguard Worker /// Trait for devices that notify hotplug event into guest
212*bb4ee6a4SAndroid Build Coastguard Worker pub trait HotPlugBus: Send {
213*bb4ee6a4SAndroid Build Coastguard Worker     /// Request hot plug event. Returns error if the request is not sent. Upon success, optionally
214*bb4ee6a4SAndroid Build Coastguard Worker     /// returns an event, which is triggerred once when the guest OS completes the request (by
215*bb4ee6a4SAndroid Build Coastguard Worker     /// sending PCI_EXP_SLTCTL_CCIE). Returns None if no such mechanism is provided.
216*bb4ee6a4SAndroid Build Coastguard Worker     /// * 'addr' - the guest pci address for hotplug in device
hot_plug(&mut self, addr: PciAddress) -> anyhow::Result<Option<Event>>217*bb4ee6a4SAndroid Build Coastguard Worker     fn hot_plug(&mut self, addr: PciAddress) -> anyhow::Result<Option<Event>>;
218*bb4ee6a4SAndroid Build Coastguard Worker     /// Request hot unplug event. Returns error if the request is not sent. Upon success, optionally
219*bb4ee6a4SAndroid Build Coastguard Worker     /// returns an event, which is triggerred once when the guest OS completes the request (by
220*bb4ee6a4SAndroid Build Coastguard Worker     /// sending PCI_EXP_SLTCTL_CCIE). Returns None if no such mechanism is provided.
221*bb4ee6a4SAndroid Build Coastguard Worker     /// * 'addr' - the guest pci address for hotplug out device
hot_unplug(&mut self, addr: PciAddress) -> anyhow::Result<Option<Event>>222*bb4ee6a4SAndroid Build Coastguard Worker     fn hot_unplug(&mut self, addr: PciAddress) -> anyhow::Result<Option<Event>>;
223*bb4ee6a4SAndroid Build Coastguard Worker     /// Get a notification event when the HotPlugBus is ready for hot plug commands. If the port is
224*bb4ee6a4SAndroid Build Coastguard Worker     /// already ready, then the notification event is triggerred immediately.
get_ready_notification(&mut self) -> anyhow::Result<Event>225*bb4ee6a4SAndroid Build Coastguard Worker     fn get_ready_notification(&mut self) -> anyhow::Result<Event>;
226*bb4ee6a4SAndroid Build Coastguard Worker     /// Check whether the hotplug bus is available to add the new device
227*bb4ee6a4SAndroid Build Coastguard Worker     ///
228*bb4ee6a4SAndroid Build Coastguard Worker     /// - 'None': hotplug bus isn't match with host pci device
229*bb4ee6a4SAndroid Build Coastguard Worker     /// - 'Some(bus_num)': hotplug bus is match and put the device at bus_num
is_match(&self, host_addr: PciAddress) -> Option<u8>230*bb4ee6a4SAndroid Build Coastguard Worker     fn is_match(&self, host_addr: PciAddress) -> Option<u8>;
231*bb4ee6a4SAndroid Build Coastguard Worker     /// Gets the upstream PCI Address of the hotplug bus
get_address(&self) -> Option<PciAddress>232*bb4ee6a4SAndroid Build Coastguard Worker     fn get_address(&self) -> Option<PciAddress>;
233*bb4ee6a4SAndroid Build Coastguard Worker     /// Gets the secondary bus number of this bus
get_secondary_bus_number(&self) -> Option<u8>234*bb4ee6a4SAndroid Build Coastguard Worker     fn get_secondary_bus_number(&self) -> Option<u8>;
235*bb4ee6a4SAndroid Build Coastguard Worker     /// Add hotplug device into this bus
236*bb4ee6a4SAndroid Build Coastguard Worker     /// * 'hotplug_key' - the key to identify hotplug device from host view
237*bb4ee6a4SAndroid Build Coastguard Worker     /// * 'guest_addr' - the guest pci address for hotplug device
add_hotplug_device(&mut self, hotplug_key: HotPlugKey, guest_addr: PciAddress)238*bb4ee6a4SAndroid Build Coastguard Worker     fn add_hotplug_device(&mut self, hotplug_key: HotPlugKey, guest_addr: PciAddress);
239*bb4ee6a4SAndroid Build Coastguard Worker     /// get guest pci address from the specified hotplug_key
get_hotplug_device(&self, hotplug_key: HotPlugKey) -> Option<PciAddress>240*bb4ee6a4SAndroid Build Coastguard Worker     fn get_hotplug_device(&self, hotplug_key: HotPlugKey) -> Option<PciAddress>;
241*bb4ee6a4SAndroid Build Coastguard Worker     /// Check whether this hotplug bus is empty
is_empty(&self) -> bool242*bb4ee6a4SAndroid Build Coastguard Worker     fn is_empty(&self) -> bool;
243*bb4ee6a4SAndroid Build Coastguard Worker     /// Get hotplug key of this hotplug bus
get_hotplug_key(&self) -> Option<HotPlugKey>244*bb4ee6a4SAndroid Build Coastguard Worker     fn get_hotplug_key(&self) -> Option<HotPlugKey>;
245*bb4ee6a4SAndroid Build Coastguard Worker }
246*bb4ee6a4SAndroid Build Coastguard Worker 
247*bb4ee6a4SAndroid Build Coastguard Worker /// Trait for generic device abstraction, that is, all devices that reside on BusDevice and want
248*bb4ee6a4SAndroid Build Coastguard Worker /// to be converted back to its original type. Each new foo device must provide
249*bb4ee6a4SAndroid Build Coastguard Worker /// as_foo_device() + as_foo_device_mut() + into_foo_device(), default impl methods return None.
250*bb4ee6a4SAndroid Build Coastguard Worker pub trait BusDeviceObj {
as_pci_device(&self) -> Option<&dyn PciDevice>251*bb4ee6a4SAndroid Build Coastguard Worker     fn as_pci_device(&self) -> Option<&dyn PciDevice> {
252*bb4ee6a4SAndroid Build Coastguard Worker         None
253*bb4ee6a4SAndroid Build Coastguard Worker     }
as_pci_device_mut(&mut self) -> Option<&mut dyn PciDevice>254*bb4ee6a4SAndroid Build Coastguard Worker     fn as_pci_device_mut(&mut self) -> Option<&mut dyn PciDevice> {
255*bb4ee6a4SAndroid Build Coastguard Worker         None
256*bb4ee6a4SAndroid Build Coastguard Worker     }
into_pci_device(self: Box<Self>) -> Option<Box<dyn PciDevice>>257*bb4ee6a4SAndroid Build Coastguard Worker     fn into_pci_device(self: Box<Self>) -> Option<Box<dyn PciDevice>> {
258*bb4ee6a4SAndroid Build Coastguard Worker         None
259*bb4ee6a4SAndroid Build Coastguard Worker     }
260*bb4ee6a4SAndroid Build Coastguard Worker     #[cfg(any(target_os = "android", target_os = "linux"))]
as_platform_device(&self) -> Option<&VfioPlatformDevice>261*bb4ee6a4SAndroid Build Coastguard Worker     fn as_platform_device(&self) -> Option<&VfioPlatformDevice> {
262*bb4ee6a4SAndroid Build Coastguard Worker         None
263*bb4ee6a4SAndroid Build Coastguard Worker     }
264*bb4ee6a4SAndroid Build Coastguard Worker     #[cfg(any(target_os = "android", target_os = "linux"))]
as_platform_device_mut(&mut self) -> Option<&mut VfioPlatformDevice>265*bb4ee6a4SAndroid Build Coastguard Worker     fn as_platform_device_mut(&mut self) -> Option<&mut VfioPlatformDevice> {
266*bb4ee6a4SAndroid Build Coastguard Worker         None
267*bb4ee6a4SAndroid Build Coastguard Worker     }
268*bb4ee6a4SAndroid Build Coastguard Worker     #[cfg(any(target_os = "android", target_os = "linux"))]
into_platform_device(self: Box<Self>) -> Option<Box<VfioPlatformDevice>>269*bb4ee6a4SAndroid Build Coastguard Worker     fn into_platform_device(self: Box<Self>) -> Option<Box<VfioPlatformDevice>> {
270*bb4ee6a4SAndroid Build Coastguard Worker         None
271*bb4ee6a4SAndroid Build Coastguard Worker     }
as_virtio_mmio_device(&self) -> Option<&VirtioMmioDevice>272*bb4ee6a4SAndroid Build Coastguard Worker     fn as_virtio_mmio_device(&self) -> Option<&VirtioMmioDevice> {
273*bb4ee6a4SAndroid Build Coastguard Worker         None
274*bb4ee6a4SAndroid Build Coastguard Worker     }
as_virtio_mmio_device_mut(&mut self) -> Option<&mut VirtioMmioDevice>275*bb4ee6a4SAndroid Build Coastguard Worker     fn as_virtio_mmio_device_mut(&mut self) -> Option<&mut VirtioMmioDevice> {
276*bb4ee6a4SAndroid Build Coastguard Worker         None
277*bb4ee6a4SAndroid Build Coastguard Worker     }
into_virtio_mmio_device(self: Box<Self>) -> Option<Box<VirtioMmioDevice>>278*bb4ee6a4SAndroid Build Coastguard Worker     fn into_virtio_mmio_device(self: Box<Self>) -> Option<Box<VirtioMmioDevice>> {
279*bb4ee6a4SAndroid Build Coastguard Worker         None
280*bb4ee6a4SAndroid Build Coastguard Worker     }
281*bb4ee6a4SAndroid Build Coastguard Worker }
282*bb4ee6a4SAndroid Build Coastguard Worker 
283*bb4ee6a4SAndroid Build Coastguard Worker #[sorted]
284*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Error, Debug)]
285*bb4ee6a4SAndroid Build Coastguard Worker pub enum Error {
286*bb4ee6a4SAndroid Build Coastguard Worker     #[error("Bus Range not found")]
287*bb4ee6a4SAndroid Build Coastguard Worker     Empty,
288*bb4ee6a4SAndroid Build Coastguard Worker     /// The insertion failed because the new device overlapped with an old device.
289*bb4ee6a4SAndroid Build Coastguard Worker     #[error("new device {base},{len} overlaps with an old device {other_base},{other_len}")]
290*bb4ee6a4SAndroid Build Coastguard Worker     Overlap {
291*bb4ee6a4SAndroid Build Coastguard Worker         base: u64,
292*bb4ee6a4SAndroid Build Coastguard Worker         len: u64,
293*bb4ee6a4SAndroid Build Coastguard Worker         other_base: u64,
294*bb4ee6a4SAndroid Build Coastguard Worker         other_len: u64,
295*bb4ee6a4SAndroid Build Coastguard Worker     },
296*bb4ee6a4SAndroid Build Coastguard Worker }
297*bb4ee6a4SAndroid Build Coastguard Worker 
298*bb4ee6a4SAndroid Build Coastguard Worker pub type Result<T> = result::Result<T, Error>;
299*bb4ee6a4SAndroid Build Coastguard Worker 
300*bb4ee6a4SAndroid Build Coastguard Worker /// Holds a base and length representing the address space occupied by a `BusDevice`.
301*bb4ee6a4SAndroid Build Coastguard Worker ///
302*bb4ee6a4SAndroid Build Coastguard Worker /// * base - The address at which the range start.
303*bb4ee6a4SAndroid Build Coastguard Worker /// * len - The length of the range in bytes.
304*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Copy, Clone, Serialize, Deserialize)]
305*bb4ee6a4SAndroid Build Coastguard Worker pub struct BusRange {
306*bb4ee6a4SAndroid Build Coastguard Worker     pub base: u64,
307*bb4ee6a4SAndroid Build Coastguard Worker     pub len: u64,
308*bb4ee6a4SAndroid Build Coastguard Worker }
309*bb4ee6a4SAndroid Build Coastguard Worker 
310*bb4ee6a4SAndroid Build Coastguard Worker impl BusRange {
311*bb4ee6a4SAndroid Build Coastguard Worker     /// Returns true if `addr` is within the range.
contains(&self, addr: u64) -> bool312*bb4ee6a4SAndroid Build Coastguard Worker     pub fn contains(&self, addr: u64) -> bool {
313*bb4ee6a4SAndroid Build Coastguard Worker         self.base <= addr && addr < self.base.saturating_add(self.len)
314*bb4ee6a4SAndroid Build Coastguard Worker     }
315*bb4ee6a4SAndroid Build Coastguard Worker 
316*bb4ee6a4SAndroid Build Coastguard Worker     /// Returns true if there is overlap with the given range.
overlaps(&self, base: u64, len: u64) -> bool317*bb4ee6a4SAndroid Build Coastguard Worker     pub fn overlaps(&self, base: u64, len: u64) -> bool {
318*bb4ee6a4SAndroid Build Coastguard Worker         self.base < base.saturating_add(len) && base < self.base.saturating_add(self.len)
319*bb4ee6a4SAndroid Build Coastguard Worker     }
320*bb4ee6a4SAndroid Build Coastguard Worker }
321*bb4ee6a4SAndroid Build Coastguard Worker 
322*bb4ee6a4SAndroid Build Coastguard Worker impl Eq for BusRange {}
323*bb4ee6a4SAndroid Build Coastguard Worker 
324*bb4ee6a4SAndroid Build Coastguard Worker impl PartialEq for BusRange {
eq(&self, other: &BusRange) -> bool325*bb4ee6a4SAndroid Build Coastguard Worker     fn eq(&self, other: &BusRange) -> bool {
326*bb4ee6a4SAndroid Build Coastguard Worker         self.base == other.base
327*bb4ee6a4SAndroid Build Coastguard Worker     }
328*bb4ee6a4SAndroid Build Coastguard Worker }
329*bb4ee6a4SAndroid Build Coastguard Worker 
330*bb4ee6a4SAndroid Build Coastguard Worker impl Ord for BusRange {
cmp(&self, other: &BusRange) -> Ordering331*bb4ee6a4SAndroid Build Coastguard Worker     fn cmp(&self, other: &BusRange) -> Ordering {
332*bb4ee6a4SAndroid Build Coastguard Worker         self.base.cmp(&other.base)
333*bb4ee6a4SAndroid Build Coastguard Worker     }
334*bb4ee6a4SAndroid Build Coastguard Worker }
335*bb4ee6a4SAndroid Build Coastguard Worker 
336*bb4ee6a4SAndroid Build Coastguard Worker impl PartialOrd for BusRange {
partial_cmp(&self, other: &BusRange) -> Option<Ordering>337*bb4ee6a4SAndroid Build Coastguard Worker     fn partial_cmp(&self, other: &BusRange) -> Option<Ordering> {
338*bb4ee6a4SAndroid Build Coastguard Worker         Some(self.cmp(other))
339*bb4ee6a4SAndroid Build Coastguard Worker     }
340*bb4ee6a4SAndroid Build Coastguard Worker }
341*bb4ee6a4SAndroid Build Coastguard Worker 
342*bb4ee6a4SAndroid Build Coastguard Worker impl std::fmt::Debug for BusRange {
fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result343*bb4ee6a4SAndroid Build Coastguard Worker     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
344*bb4ee6a4SAndroid Build Coastguard Worker         write!(f, "{:#x}..+{:#x}", self.base, self.len)
345*bb4ee6a4SAndroid Build Coastguard Worker     }
346*bb4ee6a4SAndroid Build Coastguard Worker }
347*bb4ee6a4SAndroid Build Coastguard Worker 
348*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Clone)]
349*bb4ee6a4SAndroid Build Coastguard Worker struct BusEntry {
350*bb4ee6a4SAndroid Build Coastguard Worker     #[cfg(feature = "stats")]
351*bb4ee6a4SAndroid Build Coastguard Worker     index: usize,
352*bb4ee6a4SAndroid Build Coastguard Worker     device: BusDeviceEntry,
353*bb4ee6a4SAndroid Build Coastguard Worker }
354*bb4ee6a4SAndroid Build Coastguard Worker 
355*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Clone)]
356*bb4ee6a4SAndroid Build Coastguard Worker enum BusDeviceEntry {
357*bb4ee6a4SAndroid Build Coastguard Worker     OuterSync(Arc<Mutex<dyn BusDevice>>),
358*bb4ee6a4SAndroid Build Coastguard Worker     InnerSync(Arc<dyn BusDeviceSync>),
359*bb4ee6a4SAndroid Build Coastguard Worker }
360*bb4ee6a4SAndroid Build Coastguard Worker 
361*bb4ee6a4SAndroid Build Coastguard Worker /// A device container for routing reads and writes over some address space.
362*bb4ee6a4SAndroid Build Coastguard Worker ///
363*bb4ee6a4SAndroid Build Coastguard Worker /// This doesn't have any restrictions on what kind of device or address space this applies to. The
364*bb4ee6a4SAndroid Build Coastguard Worker /// only restriction is that no two devices can overlap in this address space.
365*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Clone)]
366*bb4ee6a4SAndroid Build Coastguard Worker pub struct Bus {
367*bb4ee6a4SAndroid Build Coastguard Worker     devices: Arc<Mutex<BTreeMap<BusRange, BusEntry>>>,
368*bb4ee6a4SAndroid Build Coastguard Worker     access_id: usize,
369*bb4ee6a4SAndroid Build Coastguard Worker     #[cfg(feature = "stats")]
370*bb4ee6a4SAndroid Build Coastguard Worker     pub stats: Arc<Mutex<BusStatistics>>,
371*bb4ee6a4SAndroid Build Coastguard Worker     bus_type: BusType,
372*bb4ee6a4SAndroid Build Coastguard Worker }
373*bb4ee6a4SAndroid Build Coastguard Worker 
374*bb4ee6a4SAndroid Build Coastguard Worker impl Bus {
375*bb4ee6a4SAndroid Build Coastguard Worker     /// Constructs an a bus with an empty address space.
new(bus_type: BusType) -> Bus376*bb4ee6a4SAndroid Build Coastguard Worker     pub fn new(bus_type: BusType) -> Bus {
377*bb4ee6a4SAndroid Build Coastguard Worker         Bus {
378*bb4ee6a4SAndroid Build Coastguard Worker             devices: Arc::new(Mutex::new(BTreeMap::new())),
379*bb4ee6a4SAndroid Build Coastguard Worker             access_id: 0,
380*bb4ee6a4SAndroid Build Coastguard Worker             #[cfg(feature = "stats")]
381*bb4ee6a4SAndroid Build Coastguard Worker             stats: Arc::new(Mutex::new(BusStatistics::new())),
382*bb4ee6a4SAndroid Build Coastguard Worker             bus_type,
383*bb4ee6a4SAndroid Build Coastguard Worker         }
384*bb4ee6a4SAndroid Build Coastguard Worker     }
385*bb4ee6a4SAndroid Build Coastguard Worker 
386*bb4ee6a4SAndroid Build Coastguard Worker     /// Gets the bus type
get_bus_type(&self) -> BusType387*bb4ee6a4SAndroid Build Coastguard Worker     pub fn get_bus_type(&self) -> BusType {
388*bb4ee6a4SAndroid Build Coastguard Worker         self.bus_type
389*bb4ee6a4SAndroid Build Coastguard Worker     }
390*bb4ee6a4SAndroid Build Coastguard Worker 
391*bb4ee6a4SAndroid Build Coastguard Worker     /// Sets the id that will be used for BusAccessInfo.
set_access_id(&mut self, id: usize)392*bb4ee6a4SAndroid Build Coastguard Worker     pub fn set_access_id(&mut self, id: usize) {
393*bb4ee6a4SAndroid Build Coastguard Worker         self.access_id = id;
394*bb4ee6a4SAndroid Build Coastguard Worker     }
395*bb4ee6a4SAndroid Build Coastguard Worker 
first_before(&self, addr: u64) -> Option<(BusRange, BusEntry)>396*bb4ee6a4SAndroid Build Coastguard Worker     fn first_before(&self, addr: u64) -> Option<(BusRange, BusEntry)> {
397*bb4ee6a4SAndroid Build Coastguard Worker         let devices = self.devices.lock();
398*bb4ee6a4SAndroid Build Coastguard Worker         let (range, entry) = devices
399*bb4ee6a4SAndroid Build Coastguard Worker             .range(..=BusRange { base: addr, len: 1 })
400*bb4ee6a4SAndroid Build Coastguard Worker             .next_back()?;
401*bb4ee6a4SAndroid Build Coastguard Worker         Some((*range, entry.clone()))
402*bb4ee6a4SAndroid Build Coastguard Worker     }
403*bb4ee6a4SAndroid Build Coastguard Worker 
get_device(&self, addr: u64) -> Option<(u64, u64, BusEntry)>404*bb4ee6a4SAndroid Build Coastguard Worker     fn get_device(&self, addr: u64) -> Option<(u64, u64, BusEntry)> {
405*bb4ee6a4SAndroid Build Coastguard Worker         if let Some((range, entry)) = self.first_before(addr) {
406*bb4ee6a4SAndroid Build Coastguard Worker             let offset = addr - range.base;
407*bb4ee6a4SAndroid Build Coastguard Worker             if offset < range.len {
408*bb4ee6a4SAndroid Build Coastguard Worker                 return Some((offset, addr, entry));
409*bb4ee6a4SAndroid Build Coastguard Worker             }
410*bb4ee6a4SAndroid Build Coastguard Worker         }
411*bb4ee6a4SAndroid Build Coastguard Worker         None
412*bb4ee6a4SAndroid Build Coastguard Worker     }
413*bb4ee6a4SAndroid Build Coastguard Worker 
414*bb4ee6a4SAndroid Build Coastguard Worker     /// There is no unique ID for device instances. For now we use the Arc pointers to dedup them.
415*bb4ee6a4SAndroid Build Coastguard Worker     ///
416*bb4ee6a4SAndroid Build Coastguard Worker     /// See virtio-gpu for an example of a single device instance with multiple bus entries.
417*bb4ee6a4SAndroid Build Coastguard Worker     ///
418*bb4ee6a4SAndroid Build Coastguard Worker     /// TODO: Add a unique ID to BusDevice and use that instead of pointers.
unique_devices(&self) -> Vec<BusDeviceEntry>419*bb4ee6a4SAndroid Build Coastguard Worker     fn unique_devices(&self) -> Vec<BusDeviceEntry> {
420*bb4ee6a4SAndroid Build Coastguard Worker         let mut seen_ptrs = BTreeSet::new();
421*bb4ee6a4SAndroid Build Coastguard Worker         self.devices
422*bb4ee6a4SAndroid Build Coastguard Worker             .lock()
423*bb4ee6a4SAndroid Build Coastguard Worker             .iter()
424*bb4ee6a4SAndroid Build Coastguard Worker             .map(|(_, bus_entry)| bus_entry.device.clone())
425*bb4ee6a4SAndroid Build Coastguard Worker             .filter(|dev| match dev {
426*bb4ee6a4SAndroid Build Coastguard Worker                 BusDeviceEntry::OuterSync(dev) => seen_ptrs.insert(Arc::as_ptr(dev) as *const u8),
427*bb4ee6a4SAndroid Build Coastguard Worker                 BusDeviceEntry::InnerSync(dev) => seen_ptrs.insert(Arc::as_ptr(dev) as *const u8),
428*bb4ee6a4SAndroid Build Coastguard Worker             })
429*bb4ee6a4SAndroid Build Coastguard Worker             .collect()
430*bb4ee6a4SAndroid Build Coastguard Worker     }
431*bb4ee6a4SAndroid Build Coastguard Worker 
432*bb4ee6a4SAndroid Build Coastguard Worker     /// Same as `unique_devices`, but also calculates the "snapshot key" for each device.
433*bb4ee6a4SAndroid Build Coastguard Worker     ///
434*bb4ee6a4SAndroid Build Coastguard Worker     /// The keys are used to associate a particular device with data in a serialized snapshot. The
435*bb4ee6a4SAndroid Build Coastguard Worker     /// keys need to be stable across multiple runs of the same crosvm binary.
436*bb4ee6a4SAndroid Build Coastguard Worker     ///
437*bb4ee6a4SAndroid Build Coastguard Worker     /// It is most convienent to calculate all the snapshot keys at once, because the keys are
438*bb4ee6a4SAndroid Build Coastguard Worker     /// dependant on the order of devices on the bus.
unique_devices_with_snapshot_key(&self) -> Vec<(String, BusDeviceEntry)>439*bb4ee6a4SAndroid Build Coastguard Worker     fn unique_devices_with_snapshot_key(&self) -> Vec<(String, BusDeviceEntry)> {
440*bb4ee6a4SAndroid Build Coastguard Worker         let mut next_ids = BTreeMap::<String, usize>::new();
441*bb4ee6a4SAndroid Build Coastguard Worker         let mut choose_key = |debug_label: String| -> String {
442*bb4ee6a4SAndroid Build Coastguard Worker             let label = debug_label.replace(char::is_whitespace, "-");
443*bb4ee6a4SAndroid Build Coastguard Worker             let id = next_ids.entry(label.clone()).or_default();
444*bb4ee6a4SAndroid Build Coastguard Worker             let key = format!("{}-{}", label, id);
445*bb4ee6a4SAndroid Build Coastguard Worker             *id += 1;
446*bb4ee6a4SAndroid Build Coastguard Worker             key
447*bb4ee6a4SAndroid Build Coastguard Worker         };
448*bb4ee6a4SAndroid Build Coastguard Worker 
449*bb4ee6a4SAndroid Build Coastguard Worker         let mut result = Vec::new();
450*bb4ee6a4SAndroid Build Coastguard Worker         for device_entry in self.unique_devices() {
451*bb4ee6a4SAndroid Build Coastguard Worker             let key = match &device_entry {
452*bb4ee6a4SAndroid Build Coastguard Worker                 BusDeviceEntry::OuterSync(d) => choose_key(d.lock().debug_label()),
453*bb4ee6a4SAndroid Build Coastguard Worker                 BusDeviceEntry::InnerSync(d) => choose_key(d.debug_label()),
454*bb4ee6a4SAndroid Build Coastguard Worker             };
455*bb4ee6a4SAndroid Build Coastguard Worker             result.push((key, device_entry));
456*bb4ee6a4SAndroid Build Coastguard Worker         }
457*bb4ee6a4SAndroid Build Coastguard Worker         result
458*bb4ee6a4SAndroid Build Coastguard Worker     }
459*bb4ee6a4SAndroid Build Coastguard Worker 
sleep_devices(&self) -> anyhow::Result<()>460*bb4ee6a4SAndroid Build Coastguard Worker     pub fn sleep_devices(&self) -> anyhow::Result<()> {
461*bb4ee6a4SAndroid Build Coastguard Worker         for device_entry in self.unique_devices() {
462*bb4ee6a4SAndroid Build Coastguard Worker             match device_entry {
463*bb4ee6a4SAndroid Build Coastguard Worker                 BusDeviceEntry::OuterSync(dev) => {
464*bb4ee6a4SAndroid Build Coastguard Worker                     let mut dev = (*dev).lock();
465*bb4ee6a4SAndroid Build Coastguard Worker                     debug!("Sleep on device: {}", dev.debug_label());
466*bb4ee6a4SAndroid Build Coastguard Worker                     dev.sleep()
467*bb4ee6a4SAndroid Build Coastguard Worker                         .with_context(|| format!("failed to sleep {}", dev.debug_label()))?;
468*bb4ee6a4SAndroid Build Coastguard Worker                 }
469*bb4ee6a4SAndroid Build Coastguard Worker                 BusDeviceEntry::InnerSync(dev) => {
470*bb4ee6a4SAndroid Build Coastguard Worker                     debug!("Sleep on device: {}", dev.debug_label());
471*bb4ee6a4SAndroid Build Coastguard Worker                     dev.sleep_sync()
472*bb4ee6a4SAndroid Build Coastguard Worker                         .with_context(|| format!("failed to sleep {}", dev.debug_label()))?;
473*bb4ee6a4SAndroid Build Coastguard Worker                 }
474*bb4ee6a4SAndroid Build Coastguard Worker             }
475*bb4ee6a4SAndroid Build Coastguard Worker         }
476*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
477*bb4ee6a4SAndroid Build Coastguard Worker     }
478*bb4ee6a4SAndroid Build Coastguard Worker 
wake_devices(&self) -> anyhow::Result<()>479*bb4ee6a4SAndroid Build Coastguard Worker     pub fn wake_devices(&self) -> anyhow::Result<()> {
480*bb4ee6a4SAndroid Build Coastguard Worker         for device_entry in self.unique_devices() {
481*bb4ee6a4SAndroid Build Coastguard Worker             match device_entry {
482*bb4ee6a4SAndroid Build Coastguard Worker                 BusDeviceEntry::OuterSync(dev) => {
483*bb4ee6a4SAndroid Build Coastguard Worker                     let mut dev = dev.lock();
484*bb4ee6a4SAndroid Build Coastguard Worker                     debug!("Wake on device: {}", dev.debug_label());
485*bb4ee6a4SAndroid Build Coastguard Worker                     dev.wake()
486*bb4ee6a4SAndroid Build Coastguard Worker                         .with_context(|| format!("failed to wake {}", dev.debug_label()))?;
487*bb4ee6a4SAndroid Build Coastguard Worker                 }
488*bb4ee6a4SAndroid Build Coastguard Worker                 BusDeviceEntry::InnerSync(dev) => {
489*bb4ee6a4SAndroid Build Coastguard Worker                     debug!("Wake on device: {}", dev.debug_label());
490*bb4ee6a4SAndroid Build Coastguard Worker                     dev.wake_sync()
491*bb4ee6a4SAndroid Build Coastguard Worker                         .with_context(|| format!("failed to wake {}", dev.debug_label()))?;
492*bb4ee6a4SAndroid Build Coastguard Worker                 }
493*bb4ee6a4SAndroid Build Coastguard Worker             }
494*bb4ee6a4SAndroid Build Coastguard Worker         }
495*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
496*bb4ee6a4SAndroid Build Coastguard Worker     }
497*bb4ee6a4SAndroid Build Coastguard Worker 
snapshot_devices( &self, snapshot_writer: &vm_control::SnapshotWriter, ) -> anyhow::Result<()>498*bb4ee6a4SAndroid Build Coastguard Worker     pub fn snapshot_devices(
499*bb4ee6a4SAndroid Build Coastguard Worker         &self,
500*bb4ee6a4SAndroid Build Coastguard Worker         snapshot_writer: &vm_control::SnapshotWriter,
501*bb4ee6a4SAndroid Build Coastguard Worker     ) -> anyhow::Result<()> {
502*bb4ee6a4SAndroid Build Coastguard Worker         for (snapshot_key, device_entry) in self.unique_devices_with_snapshot_key() {
503*bb4ee6a4SAndroid Build Coastguard Worker             match device_entry {
504*bb4ee6a4SAndroid Build Coastguard Worker                 BusDeviceEntry::OuterSync(dev) => {
505*bb4ee6a4SAndroid Build Coastguard Worker                     let mut dev = dev.lock();
506*bb4ee6a4SAndroid Build Coastguard Worker                     debug!("Snapshot on device: {}", dev.debug_label());
507*bb4ee6a4SAndroid Build Coastguard Worker                     snapshot_writer.write_fragment(
508*bb4ee6a4SAndroid Build Coastguard Worker                         &snapshot_key,
509*bb4ee6a4SAndroid Build Coastguard Worker                         &(*dev)
510*bb4ee6a4SAndroid Build Coastguard Worker                             .snapshot()
511*bb4ee6a4SAndroid Build Coastguard Worker                             .with_context(|| format!("failed to snapshot {}", dev.debug_label()))?,
512*bb4ee6a4SAndroid Build Coastguard Worker                     )?;
513*bb4ee6a4SAndroid Build Coastguard Worker                 }
514*bb4ee6a4SAndroid Build Coastguard Worker                 BusDeviceEntry::InnerSync(dev) => {
515*bb4ee6a4SAndroid Build Coastguard Worker                     debug!("Snapshot on device: {}", dev.debug_label());
516*bb4ee6a4SAndroid Build Coastguard Worker                     snapshot_writer.write_fragment(
517*bb4ee6a4SAndroid Build Coastguard Worker                         &snapshot_key,
518*bb4ee6a4SAndroid Build Coastguard Worker                         &dev.snapshot_sync()
519*bb4ee6a4SAndroid Build Coastguard Worker                             .with_context(|| format!("failed to snapshot {}", dev.debug_label()))?,
520*bb4ee6a4SAndroid Build Coastguard Worker                     )?;
521*bb4ee6a4SAndroid Build Coastguard Worker                 }
522*bb4ee6a4SAndroid Build Coastguard Worker             }
523*bb4ee6a4SAndroid Build Coastguard Worker         }
524*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
525*bb4ee6a4SAndroid Build Coastguard Worker     }
526*bb4ee6a4SAndroid Build Coastguard Worker 
restore_devices( &self, snapshot_reader: &vm_control::SnapshotReader, ) -> anyhow::Result<()>527*bb4ee6a4SAndroid Build Coastguard Worker     pub fn restore_devices(
528*bb4ee6a4SAndroid Build Coastguard Worker         &self,
529*bb4ee6a4SAndroid Build Coastguard Worker         snapshot_reader: &vm_control::SnapshotReader,
530*bb4ee6a4SAndroid Build Coastguard Worker     ) -> anyhow::Result<()> {
531*bb4ee6a4SAndroid Build Coastguard Worker         let mut unused_keys: BTreeSet<String> =
532*bb4ee6a4SAndroid Build Coastguard Worker             snapshot_reader.list_fragments()?.into_iter().collect();
533*bb4ee6a4SAndroid Build Coastguard Worker         for (snapshot_key, device_entry) in self.unique_devices_with_snapshot_key() {
534*bb4ee6a4SAndroid Build Coastguard Worker             unused_keys.remove(&snapshot_key);
535*bb4ee6a4SAndroid Build Coastguard Worker             match device_entry {
536*bb4ee6a4SAndroid Build Coastguard Worker                 BusDeviceEntry::OuterSync(dev) => {
537*bb4ee6a4SAndroid Build Coastguard Worker                     let mut dev = dev.lock();
538*bb4ee6a4SAndroid Build Coastguard Worker                     debug!("Restore on device: {}", dev.debug_label());
539*bb4ee6a4SAndroid Build Coastguard Worker                     dev.restore(snapshot_reader.read_fragment(&snapshot_key)?)
540*bb4ee6a4SAndroid Build Coastguard Worker                         .with_context(|| {
541*bb4ee6a4SAndroid Build Coastguard Worker                             format!("restore failed for device {}", dev.debug_label())
542*bb4ee6a4SAndroid Build Coastguard Worker                         })?;
543*bb4ee6a4SAndroid Build Coastguard Worker                 }
544*bb4ee6a4SAndroid Build Coastguard Worker                 BusDeviceEntry::InnerSync(dev) => {
545*bb4ee6a4SAndroid Build Coastguard Worker                     debug!("Restore on device: {}", dev.debug_label());
546*bb4ee6a4SAndroid Build Coastguard Worker                     dev.restore_sync(snapshot_reader.read_fragment(&snapshot_key)?)
547*bb4ee6a4SAndroid Build Coastguard Worker                         .with_context(|| {
548*bb4ee6a4SAndroid Build Coastguard Worker                             format!("restore failed for device {}", dev.debug_label())
549*bb4ee6a4SAndroid Build Coastguard Worker                         })?;
550*bb4ee6a4SAndroid Build Coastguard Worker                 }
551*bb4ee6a4SAndroid Build Coastguard Worker             }
552*bb4ee6a4SAndroid Build Coastguard Worker         }
553*bb4ee6a4SAndroid Build Coastguard Worker 
554*bb4ee6a4SAndroid Build Coastguard Worker         if !unused_keys.is_empty() {
555*bb4ee6a4SAndroid Build Coastguard Worker             error!(
556*bb4ee6a4SAndroid Build Coastguard Worker                 "unused restore data in bus, devices might be missing: {:?}",
557*bb4ee6a4SAndroid Build Coastguard Worker                 unused_keys
558*bb4ee6a4SAndroid Build Coastguard Worker             );
559*bb4ee6a4SAndroid Build Coastguard Worker         }
560*bb4ee6a4SAndroid Build Coastguard Worker 
561*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
562*bb4ee6a4SAndroid Build Coastguard Worker     }
563*bb4ee6a4SAndroid Build Coastguard Worker 
564*bb4ee6a4SAndroid Build Coastguard Worker     /// Puts the given device at the given address space.
insert(&self, device: Arc<Mutex<dyn BusDevice>>, base: u64, len: u64) -> Result<()>565*bb4ee6a4SAndroid Build Coastguard Worker     pub fn insert(&self, device: Arc<Mutex<dyn BusDevice>>, base: u64, len: u64) -> Result<()> {
566*bb4ee6a4SAndroid Build Coastguard Worker         if len == 0 {
567*bb4ee6a4SAndroid Build Coastguard Worker             return Err(Error::Overlap {
568*bb4ee6a4SAndroid Build Coastguard Worker                 base,
569*bb4ee6a4SAndroid Build Coastguard Worker                 len,
570*bb4ee6a4SAndroid Build Coastguard Worker                 other_base: 0,
571*bb4ee6a4SAndroid Build Coastguard Worker                 other_len: 0,
572*bb4ee6a4SAndroid Build Coastguard Worker             });
573*bb4ee6a4SAndroid Build Coastguard Worker         }
574*bb4ee6a4SAndroid Build Coastguard Worker 
575*bb4ee6a4SAndroid Build Coastguard Worker         // Reject all cases where the new device's range overlaps with an existing device.
576*bb4ee6a4SAndroid Build Coastguard Worker         let mut devices = self.devices.lock();
577*bb4ee6a4SAndroid Build Coastguard Worker         devices.iter().try_for_each(|(range, _dev)| {
578*bb4ee6a4SAndroid Build Coastguard Worker             if range.overlaps(base, len) {
579*bb4ee6a4SAndroid Build Coastguard Worker                 Err(Error::Overlap {
580*bb4ee6a4SAndroid Build Coastguard Worker                     base,
581*bb4ee6a4SAndroid Build Coastguard Worker                     len,
582*bb4ee6a4SAndroid Build Coastguard Worker                     other_base: range.base,
583*bb4ee6a4SAndroid Build Coastguard Worker                     other_len: range.len,
584*bb4ee6a4SAndroid Build Coastguard Worker                 })
585*bb4ee6a4SAndroid Build Coastguard Worker             } else {
586*bb4ee6a4SAndroid Build Coastguard Worker                 Ok(())
587*bb4ee6a4SAndroid Build Coastguard Worker             }
588*bb4ee6a4SAndroid Build Coastguard Worker         })?;
589*bb4ee6a4SAndroid Build Coastguard Worker 
590*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(feature = "stats")]
591*bb4ee6a4SAndroid Build Coastguard Worker         let name = device.lock().debug_label();
592*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(feature = "stats")]
593*bb4ee6a4SAndroid Build Coastguard Worker         let device_id = device.lock().device_id();
594*bb4ee6a4SAndroid Build Coastguard Worker         if devices
595*bb4ee6a4SAndroid Build Coastguard Worker             .insert(
596*bb4ee6a4SAndroid Build Coastguard Worker                 BusRange { base, len },
597*bb4ee6a4SAndroid Build Coastguard Worker                 BusEntry {
598*bb4ee6a4SAndroid Build Coastguard Worker                     #[cfg(feature = "stats")]
599*bb4ee6a4SAndroid Build Coastguard Worker                     index: self
600*bb4ee6a4SAndroid Build Coastguard Worker                         .stats
601*bb4ee6a4SAndroid Build Coastguard Worker                         .lock()
602*bb4ee6a4SAndroid Build Coastguard Worker                         .next_device_index(name, device_id.into(), base, len),
603*bb4ee6a4SAndroid Build Coastguard Worker                     device: BusDeviceEntry::OuterSync(device),
604*bb4ee6a4SAndroid Build Coastguard Worker                 },
605*bb4ee6a4SAndroid Build Coastguard Worker             )
606*bb4ee6a4SAndroid Build Coastguard Worker             .is_some()
607*bb4ee6a4SAndroid Build Coastguard Worker         {
608*bb4ee6a4SAndroid Build Coastguard Worker             return Err(Error::Overlap {
609*bb4ee6a4SAndroid Build Coastguard Worker                 base,
610*bb4ee6a4SAndroid Build Coastguard Worker                 len,
611*bb4ee6a4SAndroid Build Coastguard Worker                 other_base: base,
612*bb4ee6a4SAndroid Build Coastguard Worker                 other_len: len,
613*bb4ee6a4SAndroid Build Coastguard Worker             });
614*bb4ee6a4SAndroid Build Coastguard Worker         }
615*bb4ee6a4SAndroid Build Coastguard Worker 
616*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
617*bb4ee6a4SAndroid Build Coastguard Worker     }
618*bb4ee6a4SAndroid Build Coastguard Worker 
619*bb4ee6a4SAndroid Build Coastguard Worker     /// Puts the given device that implements BusDeviceSync at the given address space. Devices
620*bb4ee6a4SAndroid Build Coastguard Worker     /// that implement BusDeviceSync manage thread safety internally, and thus can be written to
621*bb4ee6a4SAndroid Build Coastguard Worker     /// by multiple threads simultaneously.
insert_sync(&self, device: Arc<dyn BusDeviceSync>, base: u64, len: u64) -> Result<()>622*bb4ee6a4SAndroid Build Coastguard Worker     pub fn insert_sync(&self, device: Arc<dyn BusDeviceSync>, base: u64, len: u64) -> Result<()> {
623*bb4ee6a4SAndroid Build Coastguard Worker         if len == 0 {
624*bb4ee6a4SAndroid Build Coastguard Worker             return Err(Error::Overlap {
625*bb4ee6a4SAndroid Build Coastguard Worker                 base,
626*bb4ee6a4SAndroid Build Coastguard Worker                 len,
627*bb4ee6a4SAndroid Build Coastguard Worker                 other_base: 0,
628*bb4ee6a4SAndroid Build Coastguard Worker                 other_len: 0,
629*bb4ee6a4SAndroid Build Coastguard Worker             });
630*bb4ee6a4SAndroid Build Coastguard Worker         }
631*bb4ee6a4SAndroid Build Coastguard Worker 
632*bb4ee6a4SAndroid Build Coastguard Worker         // Reject all cases where the new device's range overlaps with an existing device.
633*bb4ee6a4SAndroid Build Coastguard Worker         let mut devices = self.devices.lock();
634*bb4ee6a4SAndroid Build Coastguard Worker         devices.iter().try_for_each(|(range, _dev)| {
635*bb4ee6a4SAndroid Build Coastguard Worker             if range.overlaps(base, len) {
636*bb4ee6a4SAndroid Build Coastguard Worker                 Err(Error::Overlap {
637*bb4ee6a4SAndroid Build Coastguard Worker                     base,
638*bb4ee6a4SAndroid Build Coastguard Worker                     len,
639*bb4ee6a4SAndroid Build Coastguard Worker                     other_base: range.base,
640*bb4ee6a4SAndroid Build Coastguard Worker                     other_len: range.len,
641*bb4ee6a4SAndroid Build Coastguard Worker                 })
642*bb4ee6a4SAndroid Build Coastguard Worker             } else {
643*bb4ee6a4SAndroid Build Coastguard Worker                 Ok(())
644*bb4ee6a4SAndroid Build Coastguard Worker             }
645*bb4ee6a4SAndroid Build Coastguard Worker         })?;
646*bb4ee6a4SAndroid Build Coastguard Worker 
647*bb4ee6a4SAndroid Build Coastguard Worker         if devices
648*bb4ee6a4SAndroid Build Coastguard Worker             .insert(
649*bb4ee6a4SAndroid Build Coastguard Worker                 BusRange { base, len },
650*bb4ee6a4SAndroid Build Coastguard Worker                 BusEntry {
651*bb4ee6a4SAndroid Build Coastguard Worker                     #[cfg(feature = "stats")]
652*bb4ee6a4SAndroid Build Coastguard Worker                     index: self.stats.lock().next_device_index(
653*bb4ee6a4SAndroid Build Coastguard Worker                         device.debug_label(),
654*bb4ee6a4SAndroid Build Coastguard Worker                         device.device_id().into(),
655*bb4ee6a4SAndroid Build Coastguard Worker                         base,
656*bb4ee6a4SAndroid Build Coastguard Worker                         len,
657*bb4ee6a4SAndroid Build Coastguard Worker                     ),
658*bb4ee6a4SAndroid Build Coastguard Worker                     device: BusDeviceEntry::InnerSync(device),
659*bb4ee6a4SAndroid Build Coastguard Worker                 },
660*bb4ee6a4SAndroid Build Coastguard Worker             )
661*bb4ee6a4SAndroid Build Coastguard Worker             .is_some()
662*bb4ee6a4SAndroid Build Coastguard Worker         {
663*bb4ee6a4SAndroid Build Coastguard Worker             return Err(Error::Overlap {
664*bb4ee6a4SAndroid Build Coastguard Worker                 base,
665*bb4ee6a4SAndroid Build Coastguard Worker                 len,
666*bb4ee6a4SAndroid Build Coastguard Worker                 other_base: base,
667*bb4ee6a4SAndroid Build Coastguard Worker                 other_len: len,
668*bb4ee6a4SAndroid Build Coastguard Worker             });
669*bb4ee6a4SAndroid Build Coastguard Worker         }
670*bb4ee6a4SAndroid Build Coastguard Worker 
671*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
672*bb4ee6a4SAndroid Build Coastguard Worker     }
673*bb4ee6a4SAndroid Build Coastguard Worker 
674*bb4ee6a4SAndroid Build Coastguard Worker     /// Remove the given device at the given address space.
remove(&self, base: u64, len: u64) -> Result<()>675*bb4ee6a4SAndroid Build Coastguard Worker     pub fn remove(&self, base: u64, len: u64) -> Result<()> {
676*bb4ee6a4SAndroid Build Coastguard Worker         if len == 0 {
677*bb4ee6a4SAndroid Build Coastguard Worker             return Err(Error::Overlap {
678*bb4ee6a4SAndroid Build Coastguard Worker                 base,
679*bb4ee6a4SAndroid Build Coastguard Worker                 len,
680*bb4ee6a4SAndroid Build Coastguard Worker                 other_base: 0,
681*bb4ee6a4SAndroid Build Coastguard Worker                 other_len: 0,
682*bb4ee6a4SAndroid Build Coastguard Worker             });
683*bb4ee6a4SAndroid Build Coastguard Worker         }
684*bb4ee6a4SAndroid Build Coastguard Worker 
685*bb4ee6a4SAndroid Build Coastguard Worker         let mut devices = self.devices.lock();
686*bb4ee6a4SAndroid Build Coastguard Worker         if devices
687*bb4ee6a4SAndroid Build Coastguard Worker             .iter()
688*bb4ee6a4SAndroid Build Coastguard Worker             .any(|(range, _dev)| range.base == base && range.len == len)
689*bb4ee6a4SAndroid Build Coastguard Worker         {
690*bb4ee6a4SAndroid Build Coastguard Worker             let ret = devices.remove(&BusRange { base, len });
691*bb4ee6a4SAndroid Build Coastguard Worker             if ret.is_some() {
692*bb4ee6a4SAndroid Build Coastguard Worker                 Ok(())
693*bb4ee6a4SAndroid Build Coastguard Worker             } else {
694*bb4ee6a4SAndroid Build Coastguard Worker                 Err(Error::Empty)
695*bb4ee6a4SAndroid Build Coastguard Worker             }
696*bb4ee6a4SAndroid Build Coastguard Worker         } else {
697*bb4ee6a4SAndroid Build Coastguard Worker             Err(Error::Empty)
698*bb4ee6a4SAndroid Build Coastguard Worker         }
699*bb4ee6a4SAndroid Build Coastguard Worker     }
700*bb4ee6a4SAndroid Build Coastguard Worker 
701*bb4ee6a4SAndroid Build Coastguard Worker     /// Reads data from the device that owns the range containing `addr` and puts it into `data`.
702*bb4ee6a4SAndroid Build Coastguard Worker     ///
703*bb4ee6a4SAndroid Build Coastguard Worker     /// Returns true on success, otherwise `data` is filled with zeroes.
read(&self, addr: u64, data: &mut [u8]) -> bool704*bb4ee6a4SAndroid Build Coastguard Worker     pub fn read(&self, addr: u64, data: &mut [u8]) -> bool {
705*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(feature = "stats")]
706*bb4ee6a4SAndroid Build Coastguard Worker         let start = self.stats.lock().start_stat();
707*bb4ee6a4SAndroid Build Coastguard Worker 
708*bb4ee6a4SAndroid Build Coastguard Worker         // Initialize `data` with all zeroes to ensure consistent results even if device `read()`
709*bb4ee6a4SAndroid Build Coastguard Worker         // implementations don't always fill every byte.
710*bb4ee6a4SAndroid Build Coastguard Worker         data.fill(0);
711*bb4ee6a4SAndroid Build Coastguard Worker 
712*bb4ee6a4SAndroid Build Coastguard Worker         let device_index = if let Some((offset, address, entry)) = self.get_device(addr) {
713*bb4ee6a4SAndroid Build Coastguard Worker             let io = BusAccessInfo {
714*bb4ee6a4SAndroid Build Coastguard Worker                 address,
715*bb4ee6a4SAndroid Build Coastguard Worker                 offset,
716*bb4ee6a4SAndroid Build Coastguard Worker                 id: self.access_id,
717*bb4ee6a4SAndroid Build Coastguard Worker             };
718*bb4ee6a4SAndroid Build Coastguard Worker 
719*bb4ee6a4SAndroid Build Coastguard Worker             match &entry.device {
720*bb4ee6a4SAndroid Build Coastguard Worker                 BusDeviceEntry::OuterSync(dev) => dev.lock().read(io, data),
721*bb4ee6a4SAndroid Build Coastguard Worker                 BusDeviceEntry::InnerSync(dev) => dev.read(io, data),
722*bb4ee6a4SAndroid Build Coastguard Worker             }
723*bb4ee6a4SAndroid Build Coastguard Worker             #[cfg(feature = "stats")]
724*bb4ee6a4SAndroid Build Coastguard Worker             let index = Some(entry.index);
725*bb4ee6a4SAndroid Build Coastguard Worker             #[cfg(not(feature = "stats"))]
726*bb4ee6a4SAndroid Build Coastguard Worker             let index = Some(());
727*bb4ee6a4SAndroid Build Coastguard Worker             index
728*bb4ee6a4SAndroid Build Coastguard Worker         } else {
729*bb4ee6a4SAndroid Build Coastguard Worker             None
730*bb4ee6a4SAndroid Build Coastguard Worker         };
731*bb4ee6a4SAndroid Build Coastguard Worker 
732*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(feature = "stats")]
733*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(device_index) = device_index {
734*bb4ee6a4SAndroid Build Coastguard Worker             self.stats
735*bb4ee6a4SAndroid Build Coastguard Worker                 .lock()
736*bb4ee6a4SAndroid Build Coastguard Worker                 .end_stat(BusOperation::Write, start, device_index);
737*bb4ee6a4SAndroid Build Coastguard Worker             return true;
738*bb4ee6a4SAndroid Build Coastguard Worker         }
739*bb4ee6a4SAndroid Build Coastguard Worker 
740*bb4ee6a4SAndroid Build Coastguard Worker         device_index.is_some()
741*bb4ee6a4SAndroid Build Coastguard Worker     }
742*bb4ee6a4SAndroid Build Coastguard Worker 
743*bb4ee6a4SAndroid Build Coastguard Worker     /// Writes `data` to the device that owns the range containing `addr`.
744*bb4ee6a4SAndroid Build Coastguard Worker     ///
745*bb4ee6a4SAndroid Build Coastguard Worker     /// Returns true on success, otherwise `data` is untouched.
write(&self, addr: u64, data: &[u8]) -> bool746*bb4ee6a4SAndroid Build Coastguard Worker     pub fn write(&self, addr: u64, data: &[u8]) -> bool {
747*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(feature = "stats")]
748*bb4ee6a4SAndroid Build Coastguard Worker         let start = self.stats.lock().start_stat();
749*bb4ee6a4SAndroid Build Coastguard Worker 
750*bb4ee6a4SAndroid Build Coastguard Worker         let device_index = if let Some((offset, address, entry)) = self.get_device(addr) {
751*bb4ee6a4SAndroid Build Coastguard Worker             let io = BusAccessInfo {
752*bb4ee6a4SAndroid Build Coastguard Worker                 address,
753*bb4ee6a4SAndroid Build Coastguard Worker                 offset,
754*bb4ee6a4SAndroid Build Coastguard Worker                 id: self.access_id,
755*bb4ee6a4SAndroid Build Coastguard Worker             };
756*bb4ee6a4SAndroid Build Coastguard Worker 
757*bb4ee6a4SAndroid Build Coastguard Worker             match &entry.device {
758*bb4ee6a4SAndroid Build Coastguard Worker                 BusDeviceEntry::OuterSync(dev) => dev.lock().write(io, data),
759*bb4ee6a4SAndroid Build Coastguard Worker                 BusDeviceEntry::InnerSync(dev) => dev.write(io, data),
760*bb4ee6a4SAndroid Build Coastguard Worker             }
761*bb4ee6a4SAndroid Build Coastguard Worker 
762*bb4ee6a4SAndroid Build Coastguard Worker             #[cfg(feature = "stats")]
763*bb4ee6a4SAndroid Build Coastguard Worker             let index = Some(entry.index);
764*bb4ee6a4SAndroid Build Coastguard Worker             #[cfg(not(feature = "stats"))]
765*bb4ee6a4SAndroid Build Coastguard Worker             let index = Some(());
766*bb4ee6a4SAndroid Build Coastguard Worker             index
767*bb4ee6a4SAndroid Build Coastguard Worker         } else {
768*bb4ee6a4SAndroid Build Coastguard Worker             None
769*bb4ee6a4SAndroid Build Coastguard Worker         };
770*bb4ee6a4SAndroid Build Coastguard Worker 
771*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(feature = "stats")]
772*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(device_index) = device_index {
773*bb4ee6a4SAndroid Build Coastguard Worker             self.stats
774*bb4ee6a4SAndroid Build Coastguard Worker                 .lock()
775*bb4ee6a4SAndroid Build Coastguard Worker                 .end_stat(BusOperation::Write, start, device_index);
776*bb4ee6a4SAndroid Build Coastguard Worker         }
777*bb4ee6a4SAndroid Build Coastguard Worker         device_index.is_some()
778*bb4ee6a4SAndroid Build Coastguard Worker     }
779*bb4ee6a4SAndroid Build Coastguard Worker }
780*bb4ee6a4SAndroid Build Coastguard Worker 
781*bb4ee6a4SAndroid Build Coastguard Worker impl Default for Bus {
default() -> Self782*bb4ee6a4SAndroid Build Coastguard Worker     fn default() -> Self {
783*bb4ee6a4SAndroid Build Coastguard Worker         Self::new(BusType::Io)
784*bb4ee6a4SAndroid Build Coastguard Worker     }
785*bb4ee6a4SAndroid Build Coastguard Worker }
786*bb4ee6a4SAndroid Build Coastguard Worker 
787*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(test)]
788*bb4ee6a4SAndroid Build Coastguard Worker mod tests {
789*bb4ee6a4SAndroid Build Coastguard Worker     use anyhow::Result as AnyhowResult;
790*bb4ee6a4SAndroid Build Coastguard Worker 
791*bb4ee6a4SAndroid Build Coastguard Worker     use super::*;
792*bb4ee6a4SAndroid Build Coastguard Worker     use crate::pci::CrosvmDeviceId;
793*bb4ee6a4SAndroid Build Coastguard Worker     use crate::suspendable::Suspendable;
794*bb4ee6a4SAndroid Build Coastguard Worker     use crate::suspendable_tests;
795*bb4ee6a4SAndroid Build Coastguard Worker 
796*bb4ee6a4SAndroid Build Coastguard Worker     #[derive(Copy, Clone, Serialize, Deserialize, Eq, PartialEq, Debug)]
797*bb4ee6a4SAndroid Build Coastguard Worker     struct DummyDevice;
798*bb4ee6a4SAndroid Build Coastguard Worker 
799*bb4ee6a4SAndroid Build Coastguard Worker     impl BusDevice for DummyDevice {
device_id(&self) -> DeviceId800*bb4ee6a4SAndroid Build Coastguard Worker         fn device_id(&self) -> DeviceId {
801*bb4ee6a4SAndroid Build Coastguard Worker             CrosvmDeviceId::Cmos.into()
802*bb4ee6a4SAndroid Build Coastguard Worker         }
debug_label(&self) -> String803*bb4ee6a4SAndroid Build Coastguard Worker         fn debug_label(&self) -> String {
804*bb4ee6a4SAndroid Build Coastguard Worker             "dummy device".to_owned()
805*bb4ee6a4SAndroid Build Coastguard Worker         }
806*bb4ee6a4SAndroid Build Coastguard Worker     }
807*bb4ee6a4SAndroid Build Coastguard Worker 
808*bb4ee6a4SAndroid Build Coastguard Worker     impl Suspendable for DummyDevice {
snapshot(&mut self) -> AnyhowResult<serde_json::Value>809*bb4ee6a4SAndroid Build Coastguard Worker         fn snapshot(&mut self) -> AnyhowResult<serde_json::Value> {
810*bb4ee6a4SAndroid Build Coastguard Worker             serde_json::to_value(self).context("error serializing")
811*bb4ee6a4SAndroid Build Coastguard Worker         }
812*bb4ee6a4SAndroid Build Coastguard Worker 
restore(&mut self, data: serde_json::Value) -> AnyhowResult<()>813*bb4ee6a4SAndroid Build Coastguard Worker         fn restore(&mut self, data: serde_json::Value) -> AnyhowResult<()> {
814*bb4ee6a4SAndroid Build Coastguard Worker             *self = serde_json::from_value(data).context("error deserializing")?;
815*bb4ee6a4SAndroid Build Coastguard Worker             Ok(())
816*bb4ee6a4SAndroid Build Coastguard Worker         }
817*bb4ee6a4SAndroid Build Coastguard Worker 
sleep(&mut self) -> AnyhowResult<()>818*bb4ee6a4SAndroid Build Coastguard Worker         fn sleep(&mut self) -> AnyhowResult<()> {
819*bb4ee6a4SAndroid Build Coastguard Worker             Ok(())
820*bb4ee6a4SAndroid Build Coastguard Worker         }
821*bb4ee6a4SAndroid Build Coastguard Worker 
wake(&mut self) -> AnyhowResult<()>822*bb4ee6a4SAndroid Build Coastguard Worker         fn wake(&mut self) -> AnyhowResult<()> {
823*bb4ee6a4SAndroid Build Coastguard Worker             Ok(())
824*bb4ee6a4SAndroid Build Coastguard Worker         }
825*bb4ee6a4SAndroid Build Coastguard Worker     }
826*bb4ee6a4SAndroid Build Coastguard Worker 
827*bb4ee6a4SAndroid Build Coastguard Worker     #[derive(Copy, Clone, Serialize, Deserialize, Eq, PartialEq, Debug)]
828*bb4ee6a4SAndroid Build Coastguard Worker     struct ConstantDevice {
829*bb4ee6a4SAndroid Build Coastguard Worker         uses_full_addr: bool,
830*bb4ee6a4SAndroid Build Coastguard Worker     }
831*bb4ee6a4SAndroid Build Coastguard Worker 
832*bb4ee6a4SAndroid Build Coastguard Worker     impl BusDevice for ConstantDevice {
device_id(&self) -> DeviceId833*bb4ee6a4SAndroid Build Coastguard Worker         fn device_id(&self) -> DeviceId {
834*bb4ee6a4SAndroid Build Coastguard Worker             CrosvmDeviceId::Cmos.into()
835*bb4ee6a4SAndroid Build Coastguard Worker         }
836*bb4ee6a4SAndroid Build Coastguard Worker 
debug_label(&self) -> String837*bb4ee6a4SAndroid Build Coastguard Worker         fn debug_label(&self) -> String {
838*bb4ee6a4SAndroid Build Coastguard Worker             "constant device".to_owned()
839*bb4ee6a4SAndroid Build Coastguard Worker         }
840*bb4ee6a4SAndroid Build Coastguard Worker 
read(&mut self, info: BusAccessInfo, data: &mut [u8])841*bb4ee6a4SAndroid Build Coastguard Worker         fn read(&mut self, info: BusAccessInfo, data: &mut [u8]) {
842*bb4ee6a4SAndroid Build Coastguard Worker             let addr = if self.uses_full_addr {
843*bb4ee6a4SAndroid Build Coastguard Worker                 info.address
844*bb4ee6a4SAndroid Build Coastguard Worker             } else {
845*bb4ee6a4SAndroid Build Coastguard Worker                 info.offset
846*bb4ee6a4SAndroid Build Coastguard Worker             };
847*bb4ee6a4SAndroid Build Coastguard Worker             for (i, v) in data.iter_mut().enumerate() {
848*bb4ee6a4SAndroid Build Coastguard Worker                 *v = (addr as u8) + (i as u8);
849*bb4ee6a4SAndroid Build Coastguard Worker             }
850*bb4ee6a4SAndroid Build Coastguard Worker         }
851*bb4ee6a4SAndroid Build Coastguard Worker 
write(&mut self, info: BusAccessInfo, data: &[u8])852*bb4ee6a4SAndroid Build Coastguard Worker         fn write(&mut self, info: BusAccessInfo, data: &[u8]) {
853*bb4ee6a4SAndroid Build Coastguard Worker             let addr = if self.uses_full_addr {
854*bb4ee6a4SAndroid Build Coastguard Worker                 info.address
855*bb4ee6a4SAndroid Build Coastguard Worker             } else {
856*bb4ee6a4SAndroid Build Coastguard Worker                 info.offset
857*bb4ee6a4SAndroid Build Coastguard Worker             };
858*bb4ee6a4SAndroid Build Coastguard Worker             for (i, v) in data.iter().enumerate() {
859*bb4ee6a4SAndroid Build Coastguard Worker                 assert_eq!(*v, (addr as u8) + (i as u8))
860*bb4ee6a4SAndroid Build Coastguard Worker             }
861*bb4ee6a4SAndroid Build Coastguard Worker         }
862*bb4ee6a4SAndroid Build Coastguard Worker     }
863*bb4ee6a4SAndroid Build Coastguard Worker 
864*bb4ee6a4SAndroid Build Coastguard Worker     impl Suspendable for ConstantDevice {
snapshot(&mut self) -> AnyhowResult<serde_json::Value>865*bb4ee6a4SAndroid Build Coastguard Worker         fn snapshot(&mut self) -> AnyhowResult<serde_json::Value> {
866*bb4ee6a4SAndroid Build Coastguard Worker             serde_json::to_value(self).context("error serializing")
867*bb4ee6a4SAndroid Build Coastguard Worker         }
868*bb4ee6a4SAndroid Build Coastguard Worker 
restore(&mut self, data: serde_json::Value) -> AnyhowResult<()>869*bb4ee6a4SAndroid Build Coastguard Worker         fn restore(&mut self, data: serde_json::Value) -> AnyhowResult<()> {
870*bb4ee6a4SAndroid Build Coastguard Worker             *self = serde_json::from_value(data).context("error deserializing")?;
871*bb4ee6a4SAndroid Build Coastguard Worker             Ok(())
872*bb4ee6a4SAndroid Build Coastguard Worker         }
873*bb4ee6a4SAndroid Build Coastguard Worker 
sleep(&mut self) -> AnyhowResult<()>874*bb4ee6a4SAndroid Build Coastguard Worker         fn sleep(&mut self) -> AnyhowResult<()> {
875*bb4ee6a4SAndroid Build Coastguard Worker             Ok(())
876*bb4ee6a4SAndroid Build Coastguard Worker         }
877*bb4ee6a4SAndroid Build Coastguard Worker 
wake(&mut self) -> AnyhowResult<()>878*bb4ee6a4SAndroid Build Coastguard Worker         fn wake(&mut self) -> AnyhowResult<()> {
879*bb4ee6a4SAndroid Build Coastguard Worker             Ok(())
880*bb4ee6a4SAndroid Build Coastguard Worker         }
881*bb4ee6a4SAndroid Build Coastguard Worker     }
882*bb4ee6a4SAndroid Build Coastguard Worker 
modify_constant_device(constant: &mut ConstantDevice)883*bb4ee6a4SAndroid Build Coastguard Worker     fn modify_constant_device(constant: &mut ConstantDevice) {
884*bb4ee6a4SAndroid Build Coastguard Worker         constant.uses_full_addr = !constant.uses_full_addr;
885*bb4ee6a4SAndroid Build Coastguard Worker     }
886*bb4ee6a4SAndroid Build Coastguard Worker 
887*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
bus_insert()888*bb4ee6a4SAndroid Build Coastguard Worker     fn bus_insert() {
889*bb4ee6a4SAndroid Build Coastguard Worker         let bus = Bus::new(BusType::Io);
890*bb4ee6a4SAndroid Build Coastguard Worker         let dummy = Arc::new(Mutex::new(DummyDevice));
891*bb4ee6a4SAndroid Build Coastguard Worker         assert!(bus.insert(dummy.clone(), 0x10, 0).is_err());
892*bb4ee6a4SAndroid Build Coastguard Worker         assert!(bus.insert(dummy.clone(), 0x10, 0x10).is_ok());
893*bb4ee6a4SAndroid Build Coastguard Worker         assert!(bus.insert(dummy.clone(), 0x0f, 0x10).is_err());
894*bb4ee6a4SAndroid Build Coastguard Worker         assert!(bus.insert(dummy.clone(), 0x10, 0x10).is_err());
895*bb4ee6a4SAndroid Build Coastguard Worker         assert!(bus.insert(dummy.clone(), 0x10, 0x15).is_err());
896*bb4ee6a4SAndroid Build Coastguard Worker         assert!(bus.insert(dummy.clone(), 0x12, 0x15).is_err());
897*bb4ee6a4SAndroid Build Coastguard Worker         assert!(bus.insert(dummy.clone(), 0x12, 0x01).is_err());
898*bb4ee6a4SAndroid Build Coastguard Worker         assert!(bus.insert(dummy.clone(), 0x0, 0x20).is_err());
899*bb4ee6a4SAndroid Build Coastguard Worker         assert!(bus.insert(dummy.clone(), 0x20, 0x05).is_ok());
900*bb4ee6a4SAndroid Build Coastguard Worker         assert!(bus.insert(dummy.clone(), 0x25, 0x05).is_ok());
901*bb4ee6a4SAndroid Build Coastguard Worker         assert!(bus.insert(dummy, 0x0, 0x10).is_ok());
902*bb4ee6a4SAndroid Build Coastguard Worker     }
903*bb4ee6a4SAndroid Build Coastguard Worker 
904*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
bus_insert_full_addr()905*bb4ee6a4SAndroid Build Coastguard Worker     fn bus_insert_full_addr() {
906*bb4ee6a4SAndroid Build Coastguard Worker         let bus = Bus::new(BusType::Io);
907*bb4ee6a4SAndroid Build Coastguard Worker         let dummy = Arc::new(Mutex::new(DummyDevice));
908*bb4ee6a4SAndroid Build Coastguard Worker         assert!(bus.insert(dummy.clone(), 0x10, 0).is_err());
909*bb4ee6a4SAndroid Build Coastguard Worker         assert!(bus.insert(dummy.clone(), 0x10, 0x10).is_ok());
910*bb4ee6a4SAndroid Build Coastguard Worker         assert!(bus.insert(dummy.clone(), 0x0f, 0x10).is_err());
911*bb4ee6a4SAndroid Build Coastguard Worker         assert!(bus.insert(dummy.clone(), 0x10, 0x10).is_err());
912*bb4ee6a4SAndroid Build Coastguard Worker         assert!(bus.insert(dummy.clone(), 0x10, 0x15).is_err());
913*bb4ee6a4SAndroid Build Coastguard Worker         assert!(bus.insert(dummy.clone(), 0x12, 0x15).is_err());
914*bb4ee6a4SAndroid Build Coastguard Worker         assert!(bus.insert(dummy.clone(), 0x12, 0x01).is_err());
915*bb4ee6a4SAndroid Build Coastguard Worker         assert!(bus.insert(dummy.clone(), 0x0, 0x20).is_err());
916*bb4ee6a4SAndroid Build Coastguard Worker         assert!(bus.insert(dummy.clone(), 0x20, 0x05).is_ok());
917*bb4ee6a4SAndroid Build Coastguard Worker         assert!(bus.insert(dummy.clone(), 0x25, 0x05).is_ok());
918*bb4ee6a4SAndroid Build Coastguard Worker         assert!(bus.insert(dummy, 0x0, 0x10).is_ok());
919*bb4ee6a4SAndroid Build Coastguard Worker     }
920*bb4ee6a4SAndroid Build Coastguard Worker 
921*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
bus_read_write()922*bb4ee6a4SAndroid Build Coastguard Worker     fn bus_read_write() {
923*bb4ee6a4SAndroid Build Coastguard Worker         let bus = Bus::new(BusType::Io);
924*bb4ee6a4SAndroid Build Coastguard Worker         let dummy = Arc::new(Mutex::new(DummyDevice));
925*bb4ee6a4SAndroid Build Coastguard Worker         assert!(bus.insert(dummy, 0x10, 0x10).is_ok());
926*bb4ee6a4SAndroid Build Coastguard Worker         assert!(bus.read(0x10, &mut [0, 0, 0, 0]));
927*bb4ee6a4SAndroid Build Coastguard Worker         assert!(bus.write(0x10, &[0, 0, 0, 0]));
928*bb4ee6a4SAndroid Build Coastguard Worker         assert!(bus.read(0x11, &mut [0, 0, 0, 0]));
929*bb4ee6a4SAndroid Build Coastguard Worker         assert!(bus.write(0x11, &[0, 0, 0, 0]));
930*bb4ee6a4SAndroid Build Coastguard Worker         assert!(bus.read(0x16, &mut [0, 0, 0, 0]));
931*bb4ee6a4SAndroid Build Coastguard Worker         assert!(bus.write(0x16, &[0, 0, 0, 0]));
932*bb4ee6a4SAndroid Build Coastguard Worker         assert!(!bus.read(0x20, &mut [0, 0, 0, 0]));
933*bb4ee6a4SAndroid Build Coastguard Worker         assert!(!bus.write(0x20, &[0, 0, 0, 0]));
934*bb4ee6a4SAndroid Build Coastguard Worker         assert!(!bus.read(0x06, &mut [0, 0, 0, 0]));
935*bb4ee6a4SAndroid Build Coastguard Worker         assert!(!bus.write(0x06, &[0, 0, 0, 0]));
936*bb4ee6a4SAndroid Build Coastguard Worker     }
937*bb4ee6a4SAndroid Build Coastguard Worker 
938*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
bus_read_write_values()939*bb4ee6a4SAndroid Build Coastguard Worker     fn bus_read_write_values() {
940*bb4ee6a4SAndroid Build Coastguard Worker         let bus = Bus::new(BusType::Io);
941*bb4ee6a4SAndroid Build Coastguard Worker         let dummy = Arc::new(Mutex::new(ConstantDevice {
942*bb4ee6a4SAndroid Build Coastguard Worker             uses_full_addr: false,
943*bb4ee6a4SAndroid Build Coastguard Worker         }));
944*bb4ee6a4SAndroid Build Coastguard Worker         assert!(bus.insert(dummy, 0x10, 0x10).is_ok());
945*bb4ee6a4SAndroid Build Coastguard Worker 
946*bb4ee6a4SAndroid Build Coastguard Worker         let mut values = [0, 1, 2, 3];
947*bb4ee6a4SAndroid Build Coastguard Worker         assert!(bus.read(0x10, &mut values));
948*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(values, [0, 1, 2, 3]);
949*bb4ee6a4SAndroid Build Coastguard Worker         assert!(bus.write(0x10, &values));
950*bb4ee6a4SAndroid Build Coastguard Worker         assert!(bus.read(0x15, &mut values));
951*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(values, [5, 6, 7, 8]);
952*bb4ee6a4SAndroid Build Coastguard Worker         assert!(bus.write(0x15, &values));
953*bb4ee6a4SAndroid Build Coastguard Worker     }
954*bb4ee6a4SAndroid Build Coastguard Worker 
955*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
bus_read_write_full_addr_values()956*bb4ee6a4SAndroid Build Coastguard Worker     fn bus_read_write_full_addr_values() {
957*bb4ee6a4SAndroid Build Coastguard Worker         let bus = Bus::new(BusType::Io);
958*bb4ee6a4SAndroid Build Coastguard Worker         let dummy = Arc::new(Mutex::new(ConstantDevice {
959*bb4ee6a4SAndroid Build Coastguard Worker             uses_full_addr: true,
960*bb4ee6a4SAndroid Build Coastguard Worker         }));
961*bb4ee6a4SAndroid Build Coastguard Worker         assert!(bus.insert(dummy, 0x10, 0x10).is_ok());
962*bb4ee6a4SAndroid Build Coastguard Worker 
963*bb4ee6a4SAndroid Build Coastguard Worker         let mut values = [0u8; 4];
964*bb4ee6a4SAndroid Build Coastguard Worker         assert!(bus.read(0x10, &mut values));
965*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(values, [0x10, 0x11, 0x12, 0x13]);
966*bb4ee6a4SAndroid Build Coastguard Worker         assert!(bus.write(0x10, &values));
967*bb4ee6a4SAndroid Build Coastguard Worker         assert!(bus.read(0x15, &mut values));
968*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(values, [0x15, 0x16, 0x17, 0x18]);
969*bb4ee6a4SAndroid Build Coastguard Worker         assert!(bus.write(0x15, &values));
970*bb4ee6a4SAndroid Build Coastguard Worker     }
971*bb4ee6a4SAndroid Build Coastguard Worker 
972*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
bus_read_no_device()973*bb4ee6a4SAndroid Build Coastguard Worker     fn bus_read_no_device() {
974*bb4ee6a4SAndroid Build Coastguard Worker         let bus = Bus::new(BusType::Io);
975*bb4ee6a4SAndroid Build Coastguard Worker 
976*bb4ee6a4SAndroid Build Coastguard Worker         // read() should return false, since there is no device at address 0x10, but it should
977*bb4ee6a4SAndroid Build Coastguard Worker         // also fill the data with 0s.
978*bb4ee6a4SAndroid Build Coastguard Worker         let mut values = [1, 2, 3, 4];
979*bb4ee6a4SAndroid Build Coastguard Worker         assert!(!bus.read(0x10, &mut values));
980*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(values, [0, 0, 0, 0]);
981*bb4ee6a4SAndroid Build Coastguard Worker     }
982*bb4ee6a4SAndroid Build Coastguard Worker 
983*bb4ee6a4SAndroid Build Coastguard Worker     suspendable_tests!(
984*bb4ee6a4SAndroid Build Coastguard Worker         constant_device_true,
985*bb4ee6a4SAndroid Build Coastguard Worker         ConstantDevice {
986*bb4ee6a4SAndroid Build Coastguard Worker             uses_full_addr: true,
987*bb4ee6a4SAndroid Build Coastguard Worker         },
988*bb4ee6a4SAndroid Build Coastguard Worker         modify_constant_device
989*bb4ee6a4SAndroid Build Coastguard Worker     );
990*bb4ee6a4SAndroid Build Coastguard Worker 
991*bb4ee6a4SAndroid Build Coastguard Worker     suspendable_tests!(
992*bb4ee6a4SAndroid Build Coastguard Worker         constant_device_false,
993*bb4ee6a4SAndroid Build Coastguard Worker         ConstantDevice {
994*bb4ee6a4SAndroid Build Coastguard Worker             uses_full_addr: false,
995*bb4ee6a4SAndroid Build Coastguard Worker         },
996*bb4ee6a4SAndroid Build Coastguard Worker         modify_constant_device
997*bb4ee6a4SAndroid Build Coastguard Worker     );
998*bb4ee6a4SAndroid Build Coastguard Worker 
999*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
bus_range_contains()1000*bb4ee6a4SAndroid Build Coastguard Worker     fn bus_range_contains() {
1001*bb4ee6a4SAndroid Build Coastguard Worker         let a = BusRange {
1002*bb4ee6a4SAndroid Build Coastguard Worker             base: 0x1000,
1003*bb4ee6a4SAndroid Build Coastguard Worker             len: 0x400,
1004*bb4ee6a4SAndroid Build Coastguard Worker         };
1005*bb4ee6a4SAndroid Build Coastguard Worker         assert!(a.contains(0x1000));
1006*bb4ee6a4SAndroid Build Coastguard Worker         assert!(a.contains(0x13ff));
1007*bb4ee6a4SAndroid Build Coastguard Worker         assert!(!a.contains(0xfff));
1008*bb4ee6a4SAndroid Build Coastguard Worker         assert!(!a.contains(0x1400));
1009*bb4ee6a4SAndroid Build Coastguard Worker         assert!(a.contains(0x1200));
1010*bb4ee6a4SAndroid Build Coastguard Worker     }
1011*bb4ee6a4SAndroid Build Coastguard Worker 
1012*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
bus_range_overlap()1013*bb4ee6a4SAndroid Build Coastguard Worker     fn bus_range_overlap() {
1014*bb4ee6a4SAndroid Build Coastguard Worker         let a = BusRange {
1015*bb4ee6a4SAndroid Build Coastguard Worker             base: 0x1000,
1016*bb4ee6a4SAndroid Build Coastguard Worker             len: 0x400,
1017*bb4ee6a4SAndroid Build Coastguard Worker         };
1018*bb4ee6a4SAndroid Build Coastguard Worker         assert!(a.overlaps(0x1000, 0x400));
1019*bb4ee6a4SAndroid Build Coastguard Worker         assert!(a.overlaps(0xf00, 0x400));
1020*bb4ee6a4SAndroid Build Coastguard Worker         assert!(a.overlaps(0x1000, 0x01));
1021*bb4ee6a4SAndroid Build Coastguard Worker         assert!(a.overlaps(0xfff, 0x02));
1022*bb4ee6a4SAndroid Build Coastguard Worker         assert!(a.overlaps(0x1100, 0x100));
1023*bb4ee6a4SAndroid Build Coastguard Worker         assert!(a.overlaps(0x13ff, 0x100));
1024*bb4ee6a4SAndroid Build Coastguard Worker         assert!(!a.overlaps(0x1400, 0x100));
1025*bb4ee6a4SAndroid Build Coastguard Worker         assert!(!a.overlaps(0xf00, 0x100));
1026*bb4ee6a4SAndroid Build Coastguard Worker     }
1027*bb4ee6a4SAndroid Build Coastguard Worker }
1028