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