xref: /cloud-hypervisor/vm-device/src/bus.rs (revision adb318f4cd0079246b3cb07e01c4e978330445d2)
1 // Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2 // SPDX-License-Identifier: Apache-2.0
3 //
4 // Portions Copyright 2017 The Chromium OS Authors. All rights reserved.
5 // Use of this source code is governed by a BSD-style license that can be
6 // found in the LICENSE-BSD-3-Clause file.
7 
8 //! Handles routing to devices in an address space.
9 
10 use std::cmp::Ordering;
11 use std::collections::btree_map::BTreeMap;
12 use std::sync::{Arc, Barrier, Mutex, RwLock, Weak};
13 use std::{convert, error, fmt, io, result};
14 
15 /// Trait for devices that respond to reads or writes in an arbitrary address space.
16 ///
17 /// The device does not care where it exists in address space as each method is only given an offset
18 /// into its allocated portion of address space.
19 #[allow(unused_variables)]
20 pub trait BusDevice: Send {
21     /// Reads at `offset` from this device
22     fn read(&mut self, base: u64, offset: u64, data: &mut [u8]) {}
23     /// Writes at `offset` into this device
24     fn write(&mut self, base: u64, offset: u64, data: &[u8]) -> Option<Arc<Barrier>> {
25         None
26     }
27 }
28 
29 #[derive(Debug)]
30 pub enum Error {
31     /// The insertion failed because the new device overlapped with an old device.
32     Overlap,
33     /// Failed to operate on zero sized range.
34     ZeroSizedRange,
35     /// Failed to find address range.
36     MissingAddressRange,
37 }
38 
39 pub type Result<T> = result::Result<T, Error>;
40 
41 impl fmt::Display for Error {
42     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
43         write!(f, "bus_error: {self:?}")
44     }
45 }
46 
47 impl error::Error for Error {}
48 
49 impl convert::From<Error> for io::Error {
50     fn from(e: Error) -> Self {
51         io::Error::new(io::ErrorKind::Other, e)
52     }
53 }
54 
55 /// Holds a base and length representing the address space occupied by a `BusDevice`.
56 ///
57 /// * base - The address at which the range start.
58 /// * len - The length of the range in bytes.
59 #[derive(Debug, Copy, Clone)]
60 pub struct BusRange {
61     pub base: u64,
62     pub len: u64,
63 }
64 
65 impl BusRange {
66     /// Returns true if there is overlap with the given range.
67     pub fn overlaps(&self, base: u64, len: u64) -> bool {
68         self.base < (base + len) && base < self.base + self.len
69     }
70 }
71 
72 impl Eq for BusRange {}
73 
74 impl PartialEq for BusRange {
75     fn eq(&self, other: &BusRange) -> bool {
76         self.base == other.base
77     }
78 }
79 
80 impl Ord for BusRange {
81     fn cmp(&self, other: &BusRange) -> Ordering {
82         self.base.cmp(&other.base)
83     }
84 }
85 
86 impl PartialOrd for BusRange {
87     fn partial_cmp(&self, other: &BusRange) -> Option<Ordering> {
88         Some(self.cmp(other))
89     }
90 }
91 
92 /// A device container for routing reads and writes over some address space.
93 ///
94 /// This doesn't have any restrictions on what kind of device or address space this applies to. The
95 /// only restriction is that no two devices can overlap in this address space.
96 #[derive(Default)]
97 pub struct Bus {
98     devices: RwLock<BTreeMap<BusRange, Weak<Mutex<dyn BusDevice>>>>,
99 }
100 
101 impl Bus {
102     /// Constructs an a bus with an empty address space.
103     pub fn new() -> Bus {
104         Bus {
105             devices: RwLock::new(BTreeMap::new()),
106         }
107     }
108 
109     fn first_before(&self, addr: u64) -> Option<(BusRange, Arc<Mutex<dyn BusDevice>>)> {
110         let devices = self.devices.read().unwrap();
111         let (range, dev) = devices
112             .range(..=BusRange { base: addr, len: 1 })
113             .next_back()?;
114         dev.upgrade().map(|d| (*range, d.clone()))
115     }
116 
117     #[allow(clippy::type_complexity)]
118     pub fn resolve(&self, addr: u64) -> Option<(u64, u64, Arc<Mutex<dyn BusDevice>>)> {
119         if let Some((range, dev)) = self.first_before(addr) {
120             let offset = addr - range.base;
121             if offset < range.len {
122                 return Some((range.base, offset, dev));
123             }
124         }
125         None
126     }
127 
128     /// Puts the given device at the given address space.
129     pub fn insert(&self, device: Arc<Mutex<dyn BusDevice>>, base: u64, len: u64) -> Result<()> {
130         if len == 0 {
131             return Err(Error::ZeroSizedRange);
132         }
133 
134         // Reject all cases where the new device's range overlaps with an existing device.
135         if self
136             .devices
137             .read()
138             .unwrap()
139             .iter()
140             .any(|(range, _dev)| range.overlaps(base, len))
141         {
142             return Err(Error::Overlap);
143         }
144 
145         if self
146             .devices
147             .write()
148             .unwrap()
149             .insert(BusRange { base, len }, Arc::downgrade(&device))
150             .is_some()
151         {
152             return Err(Error::Overlap);
153         }
154 
155         Ok(())
156     }
157 
158     /// Removes the device at the given address space range.
159     pub fn remove(&self, base: u64, len: u64) -> Result<()> {
160         if len == 0 {
161             return Err(Error::ZeroSizedRange);
162         }
163 
164         let bus_range = BusRange { base, len };
165 
166         if self.devices.write().unwrap().remove(&bus_range).is_none() {
167             return Err(Error::MissingAddressRange);
168         }
169 
170         Ok(())
171     }
172 
173     /// Removes all entries referencing the given device.
174     pub fn remove_by_device(&self, device: &Arc<Mutex<dyn BusDevice>>) -> Result<()> {
175         let mut device_list = self.devices.write().unwrap();
176         let mut remove_key_list = Vec::new();
177 
178         for (key, value) in device_list.iter() {
179             if Arc::ptr_eq(&value.upgrade().unwrap(), device) {
180                 remove_key_list.push(*key);
181             }
182         }
183 
184         for key in remove_key_list.iter() {
185             device_list.remove(key);
186         }
187 
188         Ok(())
189     }
190 
191     /// Updates the address range for an existing device.
192     pub fn update_range(
193         &self,
194         old_base: u64,
195         old_len: u64,
196         new_base: u64,
197         new_len: u64,
198     ) -> Result<()> {
199         // Retrieve the device corresponding to the range
200         let device = if let Some((_, _, dev)) = self.resolve(old_base) {
201             dev.clone()
202         } else {
203             return Err(Error::MissingAddressRange);
204         };
205 
206         // Remove the old address range
207         self.remove(old_base, old_len)?;
208 
209         // Insert the new address range
210         self.insert(device, new_base, new_len)
211     }
212 
213     /// Reads data from the device that owns the range containing `addr` and puts it into `data`.
214     ///
215     /// Returns true on success, otherwise `data` is untouched.
216     pub fn read(&self, addr: u64, data: &mut [u8]) -> Result<()> {
217         if let Some((base, offset, dev)) = self.resolve(addr) {
218             // OK to unwrap as lock() failing is a serious error condition and should panic.
219             dev.lock()
220                 .expect("Failed to acquire device lock")
221                 .read(base, offset, data);
222             Ok(())
223         } else {
224             Err(Error::MissingAddressRange)
225         }
226     }
227 
228     /// Writes `data` to the device that owns the range containing `addr`.
229     ///
230     /// Returns true on success, otherwise `data` is untouched.
231     pub fn write(&self, addr: u64, data: &[u8]) -> Result<Option<Arc<Barrier>>> {
232         if let Some((base, offset, dev)) = self.resolve(addr) {
233             // OK to unwrap as lock() failing is a serious error condition and should panic.
234             Ok(dev
235                 .lock()
236                 .expect("Failed to acquire device lock")
237                 .write(base, offset, data))
238         } else {
239             Err(Error::MissingAddressRange)
240         }
241     }
242 }
243 
244 #[cfg(test)]
245 mod tests {
246     use super::*;
247 
248     struct DummyDevice;
249     impl BusDevice for DummyDevice {}
250 
251     struct ConstantDevice;
252     impl BusDevice for ConstantDevice {
253         fn read(&mut self, _base: u64, offset: u64, data: &mut [u8]) {
254             for (i, v) in data.iter_mut().enumerate() {
255                 *v = (offset as u8) + (i as u8);
256             }
257         }
258 
259         fn write(&mut self, _base: u64, offset: u64, data: &[u8]) -> Option<Arc<Barrier>> {
260             for (i, v) in data.iter().enumerate() {
261                 assert_eq!(*v, (offset as u8) + (i as u8))
262             }
263 
264             None
265         }
266     }
267 
268     #[test]
269     fn bus_insert() {
270         let bus = Bus::new();
271         let dummy = Arc::new(Mutex::new(DummyDevice));
272         assert!(bus.insert(dummy.clone(), 0x10, 0).is_err());
273         assert!(bus.insert(dummy.clone(), 0x10, 0x10).is_ok());
274 
275         let result = bus.insert(dummy.clone(), 0x0f, 0x10);
276         assert!(result.is_err());
277         assert_eq!(format!("{result:?}"), "Err(Overlap)");
278 
279         assert!(bus.insert(dummy.clone(), 0x10, 0x10).is_err());
280         assert!(bus.insert(dummy.clone(), 0x10, 0x15).is_err());
281         assert!(bus.insert(dummy.clone(), 0x12, 0x15).is_err());
282         assert!(bus.insert(dummy.clone(), 0x12, 0x01).is_err());
283         assert!(bus.insert(dummy.clone(), 0x0, 0x20).is_err());
284         assert!(bus.insert(dummy.clone(), 0x20, 0x05).is_ok());
285         assert!(bus.insert(dummy.clone(), 0x25, 0x05).is_ok());
286         assert!(bus.insert(dummy, 0x0, 0x10).is_ok());
287     }
288 
289     #[test]
290     #[allow(clippy::redundant_clone)]
291     fn bus_read_write() {
292         let bus = Bus::new();
293         let dummy = Arc::new(Mutex::new(DummyDevice));
294         assert!(bus.insert(dummy.clone(), 0x10, 0x10).is_ok());
295         assert!(bus.read(0x10, &mut [0, 0, 0, 0]).is_ok());
296         assert!(bus.write(0x10, &[0, 0, 0, 0]).is_ok());
297         assert!(bus.read(0x11, &mut [0, 0, 0, 0]).is_ok());
298         assert!(bus.write(0x11, &[0, 0, 0, 0]).is_ok());
299         assert!(bus.read(0x16, &mut [0, 0, 0, 0]).is_ok());
300         assert!(bus.write(0x16, &[0, 0, 0, 0]).is_ok());
301         assert!(bus.read(0x20, &mut [0, 0, 0, 0]).is_err());
302         assert!(bus.write(0x20, &[0, 0, 0, 0]).is_err());
303         assert!(bus.read(0x06, &mut [0, 0, 0, 0]).is_err());
304         assert!(bus.write(0x06, &[0, 0, 0, 0]).is_err());
305     }
306 
307     #[test]
308     #[allow(clippy::redundant_clone)]
309     fn bus_read_write_values() {
310         let bus = Bus::new();
311         let dummy = Arc::new(Mutex::new(ConstantDevice));
312         assert!(bus.insert(dummy.clone(), 0x10, 0x10).is_ok());
313 
314         let mut values = [0, 1, 2, 3];
315         assert!(bus.read(0x10, &mut values).is_ok());
316         assert_eq!(values, [0, 1, 2, 3]);
317         assert!(bus.write(0x10, &values).is_ok());
318         assert!(bus.read(0x15, &mut values).is_ok());
319         assert_eq!(values, [5, 6, 7, 8]);
320         assert!(bus.write(0x15, &values).is_ok());
321     }
322 
323     #[test]
324     #[allow(clippy::redundant_clone)]
325     fn busrange_cmp() {
326         let range = BusRange { base: 0x10, len: 2 };
327         assert_eq!(range, BusRange { base: 0x10, len: 3 });
328         assert_eq!(range, BusRange { base: 0x10, len: 2 });
329 
330         assert!(range < BusRange { base: 0x12, len: 1 });
331         assert!(range < BusRange { base: 0x12, len: 3 });
332 
333         assert_eq!(range, range.clone());
334 
335         let bus = Bus::new();
336         let mut data = [1, 2, 3, 4];
337         let device = Arc::new(Mutex::new(DummyDevice));
338         assert!(bus.insert(device.clone(), 0x10, 0x10).is_ok());
339         assert!(bus.write(0x10, &data).is_ok());
340         assert!(bus.read(0x10, &mut data).is_ok());
341         assert_eq!(data, [1, 2, 3, 4]);
342     }
343 
344     #[test]
345     fn bus_range_overlap() {
346         let a = BusRange {
347             base: 0x1000,
348             len: 0x400,
349         };
350         assert!(a.overlaps(0x1000, 0x400));
351         assert!(a.overlaps(0xf00, 0x400));
352         assert!(a.overlaps(0x1000, 0x01));
353         assert!(a.overlaps(0xfff, 0x02));
354         assert!(a.overlaps(0x1100, 0x100));
355         assert!(a.overlaps(0x13ff, 0x100));
356         assert!(!a.overlaps(0x1400, 0x100));
357         assert!(!a.overlaps(0xf00, 0x100));
358     }
359 }
360