xref: /cloud-hypervisor/vm-device/src/bus.rs (revision a007b750ffc61c7c7f867bf3013de0ca900ed81d)
11853b350SSamuel Ortiz // Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
21853b350SSamuel Ortiz // SPDX-License-Identifier: Apache-2.0
31853b350SSamuel Ortiz //
41853b350SSamuel Ortiz // Portions Copyright 2017 The Chromium OS Authors. All rights reserved.
51853b350SSamuel Ortiz // Use of this source code is governed by a BSD-style license that can be
6040ea543SSamuel Ortiz // found in the LICENSE-BSD-3-Clause file.
71853b350SSamuel Ortiz 
81853b350SSamuel Ortiz //! Handles routing to devices in an address space.
91853b350SSamuel Ortiz 
10adb318f4SRob Bradford use std::cmp::Ordering;
111853b350SSamuel Ortiz use std::collections::btree_map::BTreeMap;
121fc6d50fSRob Bradford use std::sync::{Arc, Barrier, Mutex, RwLock, Weak};
13*a007b750SPhilipp Schuster use std::{convert, io, result};
14*a007b750SPhilipp Schuster 
15*a007b750SPhilipp Schuster use thiserror::Error;
161853b350SSamuel Ortiz 
171853b350SSamuel Ortiz /// Trait for devices that respond to reads or writes in an arbitrary address space.
181853b350SSamuel Ortiz ///
191853b350SSamuel Ortiz /// The device does not care where it exists in address space as each method is only given an offset
201853b350SSamuel Ortiz /// into its allocated portion of address space.
211853b350SSamuel Ortiz #[allow(unused_variables)]
221853b350SSamuel Ortiz pub trait BusDevice: Send {
231853b350SSamuel Ortiz     /// Reads at `offset` from this device
read(&mut self, base: u64, offset: u64, data: &mut [u8])248173e1ccSSamuel Ortiz     fn read(&mut self, base: u64, offset: u64, data: &mut [u8]) {}
251853b350SSamuel Ortiz     /// Writes at `offset` into this device
write(&mut self, base: u64, offset: u64, data: &[u8]) -> Option<Arc<Barrier>>261fc6d50fSRob Bradford     fn write(&mut self, base: u64, offset: u64, data: &[u8]) -> Option<Arc<Barrier>> {
271fc6d50fSRob Bradford         None
281fc6d50fSRob Bradford     }
291853b350SSamuel Ortiz }
301853b350SSamuel Ortiz 
31954f3dd0SYuanchu Xie #[allow(unused_variables)]
32954f3dd0SYuanchu Xie pub trait BusDeviceSync: Send + Sync {
33954f3dd0SYuanchu Xie     /// Reads at `offset` from this device
read(&self, base: u64, offset: u64, data: &mut [u8])34954f3dd0SYuanchu Xie     fn read(&self, base: u64, offset: u64, data: &mut [u8]) {}
35954f3dd0SYuanchu Xie     /// Writes at `offset` into this device
write(&self, base: u64, offset: u64, data: &[u8]) -> Option<Arc<Barrier>>36954f3dd0SYuanchu Xie     fn write(&self, base: u64, offset: u64, data: &[u8]) -> Option<Arc<Barrier>> {
37954f3dd0SYuanchu Xie         None
38954f3dd0SYuanchu Xie     }
39954f3dd0SYuanchu Xie }
40954f3dd0SYuanchu Xie 
41954f3dd0SYuanchu Xie impl<B: BusDevice> BusDeviceSync for Mutex<B> {
42954f3dd0SYuanchu Xie     /// Reads at `offset` from this device
read(&self, base: u64, offset: u64, data: &mut [u8])43954f3dd0SYuanchu Xie     fn read(&self, base: u64, offset: u64, data: &mut [u8]) {
44954f3dd0SYuanchu Xie         self.lock()
45954f3dd0SYuanchu Xie             .expect("Failed to acquire device lock")
46954f3dd0SYuanchu Xie             .read(base, offset, data)
47954f3dd0SYuanchu Xie     }
48954f3dd0SYuanchu Xie     /// Writes at `offset` into this device
write(&self, base: u64, offset: u64, data: &[u8]) -> Option<Arc<Barrier>>49954f3dd0SYuanchu Xie     fn write(&self, base: u64, offset: u64, data: &[u8]) -> Option<Arc<Barrier>> {
50954f3dd0SYuanchu Xie         self.lock()
51954f3dd0SYuanchu Xie             .expect("Failed to acquire device lock")
52954f3dd0SYuanchu Xie             .write(base, offset, data)
53954f3dd0SYuanchu Xie     }
54954f3dd0SYuanchu Xie }
55954f3dd0SYuanchu Xie 
56*a007b750SPhilipp Schuster #[derive(Error, Debug)]
571853b350SSamuel Ortiz pub enum Error {
581853b350SSamuel Ortiz     /// The insertion failed because the new device overlapped with an old device.
59*a007b750SPhilipp Schuster     #[error("The insertion failed because the new device overlapped with an old device")]
601853b350SSamuel Ortiz     Overlap,
61733e636fSSebastien Boeuf     /// Failed to operate on zero sized range.
62*a007b750SPhilipp Schuster     #[error("Failed to operate on zero sized range")]
63733e636fSSebastien Boeuf     ZeroSizedRange,
64733e636fSSebastien Boeuf     /// Failed to find address range.
65*a007b750SPhilipp Schuster     #[error("Failed to find address range")]
66733e636fSSebastien Boeuf     MissingAddressRange,
671853b350SSamuel Ortiz }
681853b350SSamuel Ortiz 
691853b350SSamuel Ortiz pub type Result<T> = result::Result<T, Error>;
701853b350SSamuel Ortiz 
71d6c68e47SSebastien Boeuf impl convert::From<Error> for io::Error {
from(e: Error) -> Self72d6c68e47SSebastien Boeuf     fn from(e: Error) -> Self {
73ea4693a0SJinank Jain         io::Error::other(e)
74d6c68e47SSebastien Boeuf     }
75d6c68e47SSebastien Boeuf }
76d6c68e47SSebastien Boeuf 
7733796c4bSSamuel Ortiz /// Holds a base and length representing the address space occupied by a `BusDevice`.
7833796c4bSSamuel Ortiz ///
7933796c4bSSamuel Ortiz /// * base - The address at which the range start.
8033796c4bSSamuel Ortiz /// * len - The length of the range in bytes.
811853b350SSamuel Ortiz #[derive(Debug, Copy, Clone)]
8233796c4bSSamuel Ortiz pub struct BusRange {
8333796c4bSSamuel Ortiz     pub base: u64,
8433796c4bSSamuel Ortiz     pub len: u64,
8533796c4bSSamuel Ortiz }
8633796c4bSSamuel Ortiz 
8733796c4bSSamuel Ortiz impl BusRange {
8833796c4bSSamuel Ortiz     /// Returns true if there is overlap with the given range.
overlaps(&self, base: u64, len: u64) -> bool8933796c4bSSamuel Ortiz     pub fn overlaps(&self, base: u64, len: u64) -> bool {
9033796c4bSSamuel Ortiz         self.base < (base + len) && base < self.base + self.len
9133796c4bSSamuel Ortiz     }
9233796c4bSSamuel Ortiz }
931853b350SSamuel Ortiz 
941853b350SSamuel Ortiz impl Eq for BusRange {}
951853b350SSamuel Ortiz 
961853b350SSamuel Ortiz impl PartialEq for BusRange {
eq(&self, other: &BusRange) -> bool971853b350SSamuel Ortiz     fn eq(&self, other: &BusRange) -> bool {
9833796c4bSSamuel Ortiz         self.base == other.base
991853b350SSamuel Ortiz     }
1001853b350SSamuel Ortiz }
1011853b350SSamuel Ortiz 
1021853b350SSamuel Ortiz impl Ord for BusRange {
cmp(&self, other: &BusRange) -> Ordering1031853b350SSamuel Ortiz     fn cmp(&self, other: &BusRange) -> Ordering {
10433796c4bSSamuel Ortiz         self.base.cmp(&other.base)
1051853b350SSamuel Ortiz     }
1061853b350SSamuel Ortiz }
1071853b350SSamuel Ortiz 
1081853b350SSamuel Ortiz impl PartialOrd for BusRange {
partial_cmp(&self, other: &BusRange) -> Option<Ordering>1091853b350SSamuel Ortiz     fn partial_cmp(&self, other: &BusRange) -> Option<Ordering> {
110cc4422d5SRob Bradford         Some(self.cmp(other))
1111853b350SSamuel Ortiz     }
1121853b350SSamuel Ortiz }
1131853b350SSamuel Ortiz 
1141853b350SSamuel Ortiz /// A device container for routing reads and writes over some address space.
1151853b350SSamuel Ortiz ///
1161853b350SSamuel Ortiz /// This doesn't have any restrictions on what kind of device or address space this applies to. The
1171853b350SSamuel Ortiz /// only restriction is that no two devices can overlap in this address space.
1181870eb42SSebastien Boeuf #[derive(Default)]
1191853b350SSamuel Ortiz pub struct Bus {
120954f3dd0SYuanchu Xie     devices: RwLock<BTreeMap<BusRange, Weak<dyn BusDeviceSync>>>,
1211853b350SSamuel Ortiz }
1221853b350SSamuel Ortiz 
1231853b350SSamuel Ortiz impl Bus {
1241853b350SSamuel Ortiz     /// Constructs an a bus with an empty address space.
new() -> Bus1251853b350SSamuel Ortiz     pub fn new() -> Bus {
1261853b350SSamuel Ortiz         Bus {
1271870eb42SSebastien Boeuf             devices: RwLock::new(BTreeMap::new()),
1281853b350SSamuel Ortiz         }
1291853b350SSamuel Ortiz     }
1301853b350SSamuel Ortiz 
first_before(&self, addr: u64) -> Option<(BusRange, Arc<dyn BusDeviceSync>)>131954f3dd0SYuanchu Xie     fn first_before(&self, addr: u64) -> Option<(BusRange, Arc<dyn BusDeviceSync>)> {
1321870eb42SSebastien Boeuf         let devices = self.devices.read().unwrap();
1331870eb42SSebastien Boeuf         let (range, dev) = devices
13433796c4bSSamuel Ortiz             .range(..=BusRange { base: addr, len: 1 })
13589e658d9SRob Bradford             .next_back()?;
1369fc2613bSRob Bradford         dev.upgrade().map(|d| (*range, d.clone()))
1371853b350SSamuel Ortiz     }
1381853b350SSamuel Ortiz 
139733e636fSSebastien Boeuf     #[allow(clippy::type_complexity)]
resolve(&self, addr: u64) -> Option<(u64, u64, Arc<dyn BusDeviceSync>)>140954f3dd0SYuanchu Xie     fn resolve(&self, addr: u64) -> Option<(u64, u64, Arc<dyn BusDeviceSync>)> {
14133796c4bSSamuel Ortiz         if let Some((range, dev)) = self.first_before(addr) {
14233796c4bSSamuel Ortiz             let offset = addr - range.base;
14333796c4bSSamuel Ortiz             if offset < range.len {
14442e54580SSamuel Ortiz                 return Some((range.base, offset, dev));
1451853b350SSamuel Ortiz             }
1461853b350SSamuel Ortiz         }
1471853b350SSamuel Ortiz         None
1481853b350SSamuel Ortiz     }
1491853b350SSamuel Ortiz 
insert(&self, device: Arc<dyn BusDeviceSync>, base: u64, len: u64) -> Result<()>150954f3dd0SYuanchu Xie     pub fn insert(&self, device: Arc<dyn BusDeviceSync>, base: u64, len: u64) -> Result<()> {
1511853b350SSamuel Ortiz         if len == 0 {
152733e636fSSebastien Boeuf             return Err(Error::ZeroSizedRange);
1531853b350SSamuel Ortiz         }
1541853b350SSamuel Ortiz 
15533796c4bSSamuel Ortiz         // Reject all cases where the new device's range overlaps with an existing device.
15633796c4bSSamuel Ortiz         if self
15733796c4bSSamuel Ortiz             .devices
1581870eb42SSebastien Boeuf             .read()
1591870eb42SSebastien Boeuf             .unwrap()
16033796c4bSSamuel Ortiz             .iter()
16133796c4bSSamuel Ortiz             .any(|(range, _dev)| range.overlaps(base, len))
16233796c4bSSamuel Ortiz         {
1631853b350SSamuel Ortiz             return Err(Error::Overlap);
1641853b350SSamuel Ortiz         }
1651853b350SSamuel Ortiz 
16633796c4bSSamuel Ortiz         if self
16733796c4bSSamuel Ortiz             .devices
1681870eb42SSebastien Boeuf             .write()
1691870eb42SSebastien Boeuf             .unwrap()
170ca426cfdSSebastien Boeuf             .insert(BusRange { base, len }, Arc::downgrade(&device))
17133796c4bSSamuel Ortiz             .is_some()
17233796c4bSSamuel Ortiz         {
1731853b350SSamuel Ortiz             return Err(Error::Overlap);
1741853b350SSamuel Ortiz         }
1751853b350SSamuel Ortiz 
1761853b350SSamuel Ortiz         Ok(())
1771853b350SSamuel Ortiz     }
1781853b350SSamuel Ortiz 
179733e636fSSebastien Boeuf     /// Removes the device at the given address space range.
remove(&self, base: u64, len: u64) -> Result<()>1801870eb42SSebastien Boeuf     pub fn remove(&self, base: u64, len: u64) -> Result<()> {
181733e636fSSebastien Boeuf         if len == 0 {
182733e636fSSebastien Boeuf             return Err(Error::ZeroSizedRange);
183733e636fSSebastien Boeuf         }
184733e636fSSebastien Boeuf 
185733e636fSSebastien Boeuf         let bus_range = BusRange { base, len };
186733e636fSSebastien Boeuf 
1871870eb42SSebastien Boeuf         if self.devices.write().unwrap().remove(&bus_range).is_none() {
188733e636fSSebastien Boeuf             return Err(Error::MissingAddressRange);
189733e636fSSebastien Boeuf         }
190733e636fSSebastien Boeuf 
191733e636fSSebastien Boeuf         Ok(())
192733e636fSSebastien Boeuf     }
193733e636fSSebastien Boeuf 
1940e21c32cSSebastien Boeuf     /// Removes all entries referencing the given device.
remove_by_device(&self, device: &Arc<dyn BusDeviceSync>) -> Result<()>195954f3dd0SYuanchu Xie     pub fn remove_by_device(&self, device: &Arc<dyn BusDeviceSync>) -> Result<()> {
1960e21c32cSSebastien Boeuf         let mut device_list = self.devices.write().unwrap();
1970e21c32cSSebastien Boeuf         let mut remove_key_list = Vec::new();
1980e21c32cSSebastien Boeuf 
1990e21c32cSSebastien Boeuf         for (key, value) in device_list.iter() {
2000e21c32cSSebastien Boeuf             if Arc::ptr_eq(&value.upgrade().unwrap(), device) {
2010e21c32cSSebastien Boeuf                 remove_key_list.push(*key);
2020e21c32cSSebastien Boeuf             }
2030e21c32cSSebastien Boeuf         }
2040e21c32cSSebastien Boeuf 
2050e21c32cSSebastien Boeuf         for key in remove_key_list.iter() {
2060e21c32cSSebastien Boeuf             device_list.remove(key);
2070e21c32cSSebastien Boeuf         }
2080e21c32cSSebastien Boeuf 
2090e21c32cSSebastien Boeuf         Ok(())
2100e21c32cSSebastien Boeuf     }
2110e21c32cSSebastien Boeuf 
212733e636fSSebastien Boeuf     /// Updates the address range for an existing device.
update_range( &self, old_base: u64, old_len: u64, new_base: u64, new_len: u64, ) -> Result<()>213733e636fSSebastien Boeuf     pub fn update_range(
2141870eb42SSebastien Boeuf         &self,
215733e636fSSebastien Boeuf         old_base: u64,
216733e636fSSebastien Boeuf         old_len: u64,
217733e636fSSebastien Boeuf         new_base: u64,
218733e636fSSebastien Boeuf         new_len: u64,
219733e636fSSebastien Boeuf     ) -> Result<()> {
220733e636fSSebastien Boeuf         // Retrieve the device corresponding to the range
221733e636fSSebastien Boeuf         let device = if let Some((_, _, dev)) = self.resolve(old_base) {
222733e636fSSebastien Boeuf             dev.clone()
223733e636fSSebastien Boeuf         } else {
224733e636fSSebastien Boeuf             return Err(Error::MissingAddressRange);
225733e636fSSebastien Boeuf         };
226733e636fSSebastien Boeuf 
227733e636fSSebastien Boeuf         // Remove the old address range
228733e636fSSebastien Boeuf         self.remove(old_base, old_len)?;
229733e636fSSebastien Boeuf 
230733e636fSSebastien Boeuf         // Insert the new address range
231733e636fSSebastien Boeuf         self.insert(device, new_base, new_len)
232733e636fSSebastien Boeuf     }
233733e636fSSebastien Boeuf 
2341853b350SSamuel Ortiz     /// Reads data from the device that owns the range containing `addr` and puts it into `data`.
2351853b350SSamuel Ortiz     ///
2361853b350SSamuel Ortiz     /// Returns true on success, otherwise `data` is untouched.
read(&self, addr: u64, data: &mut [u8]) -> Result<()>237e5ce6dc4SSamuel Ortiz     pub fn read(&self, addr: u64, data: &mut [u8]) -> Result<()> {
2388173e1ccSSamuel Ortiz         if let Some((base, offset, dev)) = self.resolve(addr) {
2391853b350SSamuel Ortiz             // OK to unwrap as lock() failing is a serious error condition and should panic.
240954f3dd0SYuanchu Xie             dev.read(base, offset, data);
241e5ce6dc4SSamuel Ortiz             Ok(())
2421853b350SSamuel Ortiz         } else {
243e5ce6dc4SSamuel Ortiz             Err(Error::MissingAddressRange)
2441853b350SSamuel Ortiz         }
2451853b350SSamuel Ortiz     }
2461853b350SSamuel Ortiz 
2471853b350SSamuel Ortiz     /// Writes `data` to the device that owns the range containing `addr`.
2481853b350SSamuel Ortiz     ///
2491853b350SSamuel Ortiz     /// Returns true on success, otherwise `data` is untouched.
write(&self, addr: u64, data: &[u8]) -> Result<Option<Arc<Barrier>>>250a8643dc5SRob Bradford     pub fn write(&self, addr: u64, data: &[u8]) -> Result<Option<Arc<Barrier>>> {
2518173e1ccSSamuel Ortiz         if let Some((base, offset, dev)) = self.resolve(addr) {
2521853b350SSamuel Ortiz             // OK to unwrap as lock() failing is a serious error condition and should panic.
253954f3dd0SYuanchu Xie             Ok(dev.write(base, offset, data))
2541853b350SSamuel Ortiz         } else {
255e5ce6dc4SSamuel Ortiz             Err(Error::MissingAddressRange)
2561853b350SSamuel Ortiz         }
2571853b350SSamuel Ortiz     }
2581853b350SSamuel Ortiz }
2591853b350SSamuel Ortiz 
2601853b350SSamuel Ortiz #[cfg(test)]
2611853b350SSamuel Ortiz mod tests {
2621853b350SSamuel Ortiz     use super::*;
2631853b350SSamuel Ortiz 
2641853b350SSamuel Ortiz     struct DummyDevice;
265954f3dd0SYuanchu Xie     impl BusDeviceSync for DummyDevice {}
2661853b350SSamuel Ortiz 
2671853b350SSamuel Ortiz     struct ConstantDevice;
268954f3dd0SYuanchu Xie     impl BusDeviceSync for ConstantDevice {
read(&self, _base: u64, offset: u64, data: &mut [u8])269954f3dd0SYuanchu Xie         fn read(&self, _base: u64, offset: u64, data: &mut [u8]) {
2701853b350SSamuel Ortiz             for (i, v) in data.iter_mut().enumerate() {
2711853b350SSamuel Ortiz                 *v = (offset as u8) + (i as u8);
2721853b350SSamuel Ortiz             }
2731853b350SSamuel Ortiz         }
2741853b350SSamuel Ortiz 
write(&self, _base: u64, offset: u64, data: &[u8]) -> Option<Arc<Barrier>>275954f3dd0SYuanchu Xie         fn write(&self, _base: u64, offset: u64, data: &[u8]) -> Option<Arc<Barrier>> {
2761853b350SSamuel Ortiz             for (i, v) in data.iter().enumerate() {
2771853b350SSamuel Ortiz                 assert_eq!(*v, (offset as u8) + (i as u8))
2781853b350SSamuel Ortiz             }
2791fc6d50fSRob Bradford 
2801fc6d50fSRob Bradford             None
2811853b350SSamuel Ortiz         }
2821853b350SSamuel Ortiz     }
2831853b350SSamuel Ortiz 
2841853b350SSamuel Ortiz     #[test]
bus_insert()2851853b350SSamuel Ortiz     fn bus_insert() {
2861870eb42SSebastien Boeuf         let bus = Bus::new();
287954f3dd0SYuanchu Xie         let dummy = Arc::new(DummyDevice);
288297236a7SRuoqing He         bus.insert(dummy.clone(), 0x10, 0).unwrap_err();
289297236a7SRuoqing He         bus.insert(dummy.clone(), 0x10, 0x10).unwrap();
2901853b350SSamuel Ortiz 
2911853b350SSamuel Ortiz         let result = bus.insert(dummy.clone(), 0x0f, 0x10);
2925e527294SRob Bradford         assert_eq!(format!("{result:?}"), "Err(Overlap)");
2931853b350SSamuel Ortiz 
294297236a7SRuoqing He         bus.insert(dummy.clone(), 0x10, 0x10).unwrap_err();
295297236a7SRuoqing He         bus.insert(dummy.clone(), 0x10, 0x15).unwrap_err();
296297236a7SRuoqing He         bus.insert(dummy.clone(), 0x12, 0x15).unwrap_err();
297297236a7SRuoqing He         bus.insert(dummy.clone(), 0x12, 0x01).unwrap_err();
298297236a7SRuoqing He         bus.insert(dummy.clone(), 0x0, 0x20).unwrap_err();
299297236a7SRuoqing He         bus.insert(dummy.clone(), 0x20, 0x05).unwrap();
300297236a7SRuoqing He         bus.insert(dummy.clone(), 0x25, 0x05).unwrap();
301297236a7SRuoqing He         bus.insert(dummy, 0x0, 0x10).unwrap();
3021853b350SSamuel Ortiz     }
3031853b350SSamuel Ortiz 
3041853b350SSamuel Ortiz     #[test]
30574fe0328SRob Bradford     #[allow(clippy::redundant_clone)]
bus_read_write()3061853b350SSamuel Ortiz     fn bus_read_write() {
3071870eb42SSebastien Boeuf         let bus = Bus::new();
308954f3dd0SYuanchu Xie         let dummy = Arc::new(DummyDevice);
309297236a7SRuoqing He         bus.insert(dummy.clone(), 0x10, 0x10).unwrap();
310297236a7SRuoqing He         bus.read(0x10, &mut [0, 0, 0, 0]).unwrap();
311297236a7SRuoqing He         bus.write(0x10, &[0, 0, 0, 0]).unwrap();
312297236a7SRuoqing He         bus.read(0x11, &mut [0, 0, 0, 0]).unwrap();
313297236a7SRuoqing He         bus.write(0x11, &[0, 0, 0, 0]).unwrap();
314297236a7SRuoqing He         bus.read(0x16, &mut [0, 0, 0, 0]).unwrap();
315297236a7SRuoqing He         bus.write(0x16, &[0, 0, 0, 0]).unwrap();
316297236a7SRuoqing He         bus.read(0x20, &mut [0, 0, 0, 0]).unwrap_err();
317297236a7SRuoqing He         bus.write(0x20, &[0, 0, 0, 0]).unwrap_err();
318297236a7SRuoqing He         bus.read(0x06, &mut [0, 0, 0, 0]).unwrap_err();
319297236a7SRuoqing He         bus.write(0x06, &[0, 0, 0, 0]).unwrap_err();
3201853b350SSamuel Ortiz     }
3211853b350SSamuel Ortiz 
3221853b350SSamuel Ortiz     #[test]
32374fe0328SRob Bradford     #[allow(clippy::redundant_clone)]
bus_read_write_values()3241853b350SSamuel Ortiz     fn bus_read_write_values() {
3251870eb42SSebastien Boeuf         let bus = Bus::new();
326954f3dd0SYuanchu Xie         let dummy = Arc::new(ConstantDevice);
327297236a7SRuoqing He         bus.insert(dummy.clone(), 0x10, 0x10).unwrap();
3281853b350SSamuel Ortiz 
3291853b350SSamuel Ortiz         let mut values = [0, 1, 2, 3];
330297236a7SRuoqing He         bus.read(0x10, &mut values).unwrap();
3311853b350SSamuel Ortiz         assert_eq!(values, [0, 1, 2, 3]);
332297236a7SRuoqing He         bus.write(0x10, &values).unwrap();
333297236a7SRuoqing He         bus.read(0x15, &mut values).unwrap();
3341853b350SSamuel Ortiz         assert_eq!(values, [5, 6, 7, 8]);
335297236a7SRuoqing He         bus.write(0x15, &values).unwrap();
3361853b350SSamuel Ortiz     }
3371853b350SSamuel Ortiz 
3381853b350SSamuel Ortiz     #[test]
33974fe0328SRob Bradford     #[allow(clippy::redundant_clone)]
busrange_cmp()3401870eb42SSebastien Boeuf     fn busrange_cmp() {
34133796c4bSSamuel Ortiz         let range = BusRange { base: 0x10, len: 2 };
34233796c4bSSamuel Ortiz         assert_eq!(range, BusRange { base: 0x10, len: 3 });
34333796c4bSSamuel Ortiz         assert_eq!(range, BusRange { base: 0x10, len: 2 });
3441853b350SSamuel Ortiz 
34533796c4bSSamuel Ortiz         assert!(range < BusRange { base: 0x12, len: 1 });
34633796c4bSSamuel Ortiz         assert!(range < BusRange { base: 0x12, len: 3 });
3471853b350SSamuel Ortiz 
34833796c4bSSamuel Ortiz         assert_eq!(range, range.clone());
3491853b350SSamuel Ortiz 
3501870eb42SSebastien Boeuf         let bus = Bus::new();
3511853b350SSamuel Ortiz         let mut data = [1, 2, 3, 4];
352954f3dd0SYuanchu Xie         let device = Arc::new(DummyDevice);
353297236a7SRuoqing He         bus.insert(device.clone(), 0x10, 0x10).unwrap();
354297236a7SRuoqing He         bus.write(0x10, &data).unwrap();
355297236a7SRuoqing He         bus.read(0x10, &mut data).unwrap();
3561853b350SSamuel Ortiz         assert_eq!(data, [1, 2, 3, 4]);
3571853b350SSamuel Ortiz     }
35833796c4bSSamuel Ortiz 
35933796c4bSSamuel Ortiz     #[test]
bus_range_overlap()36033796c4bSSamuel Ortiz     fn bus_range_overlap() {
36133796c4bSSamuel Ortiz         let a = BusRange {
36233796c4bSSamuel Ortiz             base: 0x1000,
36333796c4bSSamuel Ortiz             len: 0x400,
36433796c4bSSamuel Ortiz         };
36533796c4bSSamuel Ortiz         assert!(a.overlaps(0x1000, 0x400));
36633796c4bSSamuel Ortiz         assert!(a.overlaps(0xf00, 0x400));
36733796c4bSSamuel Ortiz         assert!(a.overlaps(0x1000, 0x01));
36833796c4bSSamuel Ortiz         assert!(a.overlaps(0xfff, 0x02));
36933796c4bSSamuel Ortiz         assert!(a.overlaps(0x1100, 0x100));
37033796c4bSSamuel Ortiz         assert!(a.overlaps(0x13ff, 0x100));
37133796c4bSSamuel Ortiz         assert!(!a.overlaps(0x1400, 0x100));
37233796c4bSSamuel Ortiz         assert!(!a.overlaps(0xf00, 0x100));
37333796c4bSSamuel Ortiz     }
3741853b350SSamuel Ortiz }
375