devices/
bus.rs

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