Coverage Report

Created: 2026-08-14 06:27

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