vmm/vstate/
bus.rs

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