• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 The Chromium OS Authors. All rights reserved.
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 
7 use std::cmp::{Ord, Ordering, PartialEq, PartialOrd};
8 use std::collections::btree_map::BTreeMap;
9 use std::fmt;
10 use std::result;
11 use std::sync::Arc;
12 
13 use remain::sorted;
14 use serde::{Deserialize, Serialize};
15 use sync::Mutex;
16 use thiserror::Error;
17 
18 use crate::{PciAddress, PciDevice, VfioPlatformDevice};
19 
20 /// Information about how a device was accessed.
21 #[derive(Copy, Clone, Eq, PartialEq, Debug, Serialize, Deserialize)]
22 pub struct BusAccessInfo {
23     /// Offset from base address that the device was accessed at.
24     pub offset: u64,
25     /// Absolute address of the device's access in its address space.
26     pub address: u64,
27     /// ID of the entity requesting a device access, usually the VCPU id.
28     pub id: usize,
29 }
30 
31 // Implement `Display` for `MinMax`.
32 impl std::fmt::Display for BusAccessInfo {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result33     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
34         write!(f, "{:?}", self)
35     }
36 }
37 
38 /// Result of a write to a device's PCI configuration space.
39 /// This value represents the state change(s) that occurred due to the write.
40 #[derive(Clone, Debug, Default, PartialEq)]
41 pub struct ConfigWriteResult {
42     /// The BusRange in the vector will be removed from mmio_bus
43     pub mmio_remove: Vec<BusRange>,
44 
45     /// The BusRange in the vector will be added into mmio_bus
46     pub mmio_add: Vec<BusRange>,
47 
48     /// The BusRange in the vector will be removed from io_bus
49     pub io_remove: Vec<BusRange>,
50 
51     /// The BusRange in the vector will be added into io_bus
52     pub io_add: Vec<BusRange>,
53 
54     /// Device specified at PciAddress will be removed after this config write
55     /// - 'Vec<PciAddress>>': specified device will be removed after this config write
56     pub removed_pci_devices: Vec<PciAddress>,
57 }
58 
59 #[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
60 pub enum BusType {
61     Mmio,
62     Io,
63 }
64 
65 /// Trait for devices that respond to reads or writes in an arbitrary address space.
66 ///
67 /// The device does not care where it exists in address space as each method is only given an offset
68 /// into its allocated portion of address space.
69 #[allow(unused_variables)]
70 pub trait BusDevice: Send {
71     /// Returns a label suitable for debug output.
debug_label(&self) -> String72     fn debug_label(&self) -> String;
73 
74     /// Returns a unique id per device type suitable for metrics gathering.
75     // TODO(225991065): Remove this default implementation when all of the crate is upstreamed.
device_id(&self) -> u3276     fn device_id(&self) -> u32 {
77         0
78     }
79     /// Reads at `offset` from this device
read(&mut self, offset: BusAccessInfo, data: &mut [u8])80     fn read(&mut self, offset: BusAccessInfo, data: &mut [u8]) {}
81     /// Writes at `offset` into this device
write(&mut self, offset: BusAccessInfo, data: &[u8])82     fn write(&mut self, offset: BusAccessInfo, data: &[u8]) {}
83     /// Sets a register in the configuration space. Only used by PCI.
84     /// * `reg_idx` - The index of the config register to modify.
85     /// * `offset` - Offset in to the register.
config_register_write( &mut self, reg_idx: usize, offset: u64, data: &[u8], ) -> ConfigWriteResult86     fn config_register_write(
87         &mut self,
88         reg_idx: usize,
89         offset: u64,
90         data: &[u8],
91     ) -> ConfigWriteResult {
92         ConfigWriteResult {
93             ..Default::default()
94         }
95     }
96     /// Gets a register from the configuration space. Only used by PCI.
97     /// * `reg_idx` - The index of the config register to read.
config_register_read(&self, reg_idx: usize) -> u3298     fn config_register_read(&self, reg_idx: usize) -> u32 {
99         0
100     }
101     /// Sets a register in the virtual config space. Only used by PCI.
102     /// * `reg_idx` - The index of the config register to modify.
103     /// * `value` - The value to be written.
virtual_config_register_write(&mut self, reg_idx: usize, value: u32)104     fn virtual_config_register_write(&mut self, reg_idx: usize, value: u32) {}
105     /// Gets a register from the virtual config space. Only used by PCI.
106     /// * `reg_idx` - The index of the config register to read.
virtual_config_register_read(&self, reg_idx: usize) -> u32107     fn virtual_config_register_read(&self, reg_idx: usize) -> u32 {
108         0
109     }
110     /// Invoked when the device is sandboxed.
on_sandboxed(&mut self)111     fn on_sandboxed(&mut self) {}
112 
113     /// Gets a list of all ranges registered by this BusDevice.
get_ranges(&self) -> Vec<(BusRange, BusType)>114     fn get_ranges(&self) -> Vec<(BusRange, BusType)> {
115         Vec::new()
116     }
117 
118     /// Invoked when the device is destroyed
destroy_device(&mut self)119     fn destroy_device(&mut self) {}
120 }
121 
122 pub trait BusDeviceSync: BusDevice + Sync {
read(&self, offset: BusAccessInfo, data: &mut [u8])123     fn read(&self, offset: BusAccessInfo, data: &mut [u8]);
write(&self, offset: BusAccessInfo, data: &[u8])124     fn write(&self, offset: BusAccessInfo, data: &[u8]);
125 }
126 
127 pub trait BusResumeDevice: Send {
128     /// notify the devices which are invoked
129     /// before the VM resumes form suspend.
resume_imminent(&mut self)130     fn resume_imminent(&mut self) {}
131 }
132 
133 /// The key to identify hotplug device from host view.
134 /// like host sysfs path for vfio pci device, host disk file
135 /// path for virtio block device
136 #[derive(Copy, Clone)]
137 pub enum HostHotPlugKey {
138     Vfio { host_addr: PciAddress },
139 }
140 
141 /// Trait for devices that notify hotplug event into guest
142 pub trait HotPlugBus {
143     /// Notify hotplug in event into guest
144     /// * 'addr' - the guest pci address for hotplug in device
hot_plug(&mut self, addr: PciAddress)145     fn hot_plug(&mut self, addr: PciAddress);
146     /// Notify hotplug out event into guest
147     /// * 'addr' - the guest pci address for hotplug out device
hot_unplug(&mut self, addr: PciAddress)148     fn hot_unplug(&mut self, addr: PciAddress);
149     /// Check whether the hotplug bus is available to add the new device
150     ///
151     /// - 'None': hotplug bus isn't match with host pci device
152     /// - 'Some(bus_num)': hotplug bus is match and put the device at bus_num
is_match(&self, host_addr: PciAddress) -> Option<u8>153     fn is_match(&self, host_addr: PciAddress) -> Option<u8>;
154     /// Add hotplug device into this bus
155     /// * 'host_key' - the key to identify hotplug device from host view
156     /// * 'guest_addr' - the guest pci address for hotplug device
add_hotplug_device(&mut self, host_key: HostHotPlugKey, guest_addr: PciAddress)157     fn add_hotplug_device(&mut self, host_key: HostHotPlugKey, guest_addr: PciAddress);
158     /// get guest pci address from the specified host_key
get_hotplug_device(&self, host_key: HostHotPlugKey) -> Option<PciAddress>159     fn get_hotplug_device(&self, host_key: HostHotPlugKey) -> Option<PciAddress>;
160 }
161 
162 /// Trait for generic device abstraction, that is, all devices that reside on BusDevice and want
163 /// to be converted back to its original type. Each new foo device must provide
164 /// as_foo_device() + as_foo_device_mut() + into_foo_device(), default impl methods return None.
165 pub trait BusDeviceObj {
as_pci_device(&self) -> Option<&dyn PciDevice>166     fn as_pci_device(&self) -> Option<&dyn PciDevice> {
167         None
168     }
as_pci_device_mut(&mut self) -> Option<&mut dyn PciDevice>169     fn as_pci_device_mut(&mut self) -> Option<&mut dyn PciDevice> {
170         None
171     }
into_pci_device(self: Box<Self>) -> Option<Box<dyn PciDevice>>172     fn into_pci_device(self: Box<Self>) -> Option<Box<dyn PciDevice>> {
173         None
174     }
175 
as_platform_device(&self) -> Option<&VfioPlatformDevice>176     fn as_platform_device(&self) -> Option<&VfioPlatformDevice> {
177         None
178     }
as_platform_device_mut(&mut self) -> Option<&mut VfioPlatformDevice>179     fn as_platform_device_mut(&mut self) -> Option<&mut VfioPlatformDevice> {
180         None
181     }
into_platform_device(self: Box<Self>) -> Option<Box<VfioPlatformDevice>>182     fn into_platform_device(self: Box<Self>) -> Option<Box<VfioPlatformDevice>> {
183         None
184     }
185 }
186 
187 #[sorted]
188 #[derive(Error, Debug)]
189 pub enum Error {
190     #[error("Bus Range not found")]
191     Empty,
192     /// The insertion failed because the new device overlapped with an old device.
193     #[error("new device overlaps with an old device")]
194     Overlap,
195 }
196 
197 pub type Result<T> = result::Result<T, Error>;
198 
199 /// Holds a base and length representing the address space occupied by a `BusDevice`.
200 ///
201 /// * base - The address at which the range start.
202 /// * len - The length of the range in bytes.
203 #[derive(Debug, Copy, Clone, Serialize, Deserialize)]
204 pub struct BusRange {
205     pub base: u64,
206     pub len: u64,
207 }
208 
209 impl BusRange {
210     /// Returns true if `addr` is within the range.
contains(&self, addr: u64) -> bool211     pub fn contains(&self, addr: u64) -> bool {
212         self.base <= addr && addr < self.base + self.len
213     }
214 
215     /// Returns true if there is overlap with the given range.
overlaps(&self, base: u64, len: u64) -> bool216     pub fn overlaps(&self, base: u64, len: u64) -> bool {
217         self.base < (base + len) && base < self.base + self.len
218     }
219 }
220 
221 impl Eq for BusRange {}
222 
223 impl PartialEq for BusRange {
eq(&self, other: &BusRange) -> bool224     fn eq(&self, other: &BusRange) -> bool {
225         self.base == other.base
226     }
227 }
228 
229 impl Ord for BusRange {
cmp(&self, other: &BusRange) -> Ordering230     fn cmp(&self, other: &BusRange) -> Ordering {
231         self.base.cmp(&other.base)
232     }
233 }
234 
235 impl PartialOrd for BusRange {
partial_cmp(&self, other: &BusRange) -> Option<Ordering>236     fn partial_cmp(&self, other: &BusRange) -> Option<Ordering> {
237         self.base.partial_cmp(&other.base)
238     }
239 }
240 
241 #[derive(Clone)]
242 enum BusDeviceEntry {
243     OuterSync(Arc<Mutex<dyn BusDevice>>),
244     InnerSync(Arc<dyn BusDeviceSync>),
245 }
246 
247 /// A device container for routing reads and writes over some address space.
248 ///
249 /// This doesn't have any restrictions on what kind of device or address space this applies to. The
250 /// only restriction is that no two devices can overlap in this address space.
251 #[derive(Clone)]
252 pub struct Bus {
253     devices: Arc<Mutex<BTreeMap<BusRange, BusDeviceEntry>>>,
254     access_id: usize,
255 }
256 
257 impl Bus {
258     /// Constructs an a bus with an empty address space.
new() -> Bus259     pub fn new() -> Bus {
260         Bus {
261             devices: Arc::new(Mutex::new(BTreeMap::new())),
262             access_id: 0,
263         }
264     }
265 
266     /// Sets the id that will be used for BusAccessInfo.
set_access_id(&mut self, id: usize)267     pub fn set_access_id(&mut self, id: usize) {
268         self.access_id = id;
269     }
270 
first_before(&self, addr: u64) -> Option<(BusRange, BusDeviceEntry)>271     fn first_before(&self, addr: u64) -> Option<(BusRange, BusDeviceEntry)> {
272         let devices = self.devices.lock();
273         let (range, dev) = devices
274             .range(..=BusRange { base: addr, len: 1 })
275             .rev()
276             .next()?;
277         Some((*range, dev.clone()))
278     }
279 
get_device(&self, addr: u64) -> Option<(u64, u64, BusDeviceEntry)>280     fn get_device(&self, addr: u64) -> Option<(u64, u64, BusDeviceEntry)> {
281         if let Some((range, dev)) = self.first_before(addr) {
282             let offset = addr - range.base;
283             if offset < range.len {
284                 return Some((offset, addr, dev));
285             }
286         }
287         None
288     }
289 
290     /// Puts the given device at the given address space.
insert(&self, device: Arc<Mutex<dyn BusDevice>>, base: u64, len: u64) -> Result<()>291     pub fn insert(&self, device: Arc<Mutex<dyn BusDevice>>, base: u64, len: u64) -> Result<()> {
292         if len == 0 {
293             return Err(Error::Overlap);
294         }
295 
296         // Reject all cases where the new device's range overlaps with an existing device.
297         let mut devices = self.devices.lock();
298         if devices
299             .iter()
300             .any(|(range, _dev)| range.overlaps(base, len))
301         {
302             return Err(Error::Overlap);
303         }
304 
305         if devices
306             .insert(BusRange { base, len }, BusDeviceEntry::OuterSync(device))
307             .is_some()
308         {
309             return Err(Error::Overlap);
310         }
311 
312         Ok(())
313     }
314 
315     /// Puts the given device that implements BusDeviceSync at the given address space. Devices
316     /// that implement BusDeviceSync manage thread safety internally, and thus can be written to
317     /// by multiple threads simultaneously.
insert_sync(&self, device: Arc<dyn BusDeviceSync>, base: u64, len: u64) -> Result<()>318     pub fn insert_sync(&self, device: Arc<dyn BusDeviceSync>, base: u64, len: u64) -> Result<()> {
319         if len == 0 {
320             return Err(Error::Overlap);
321         }
322 
323         // Reject all cases where the new device's range overlaps with an existing device.
324         let mut devices = self.devices.lock();
325         if devices
326             .iter()
327             .any(|(range, _dev)| range.overlaps(base, len))
328         {
329             return Err(Error::Overlap);
330         }
331 
332         if devices
333             .insert(BusRange { base, len }, BusDeviceEntry::InnerSync(device))
334             .is_some()
335         {
336             return Err(Error::Overlap);
337         }
338 
339         Ok(())
340     }
341 
342     /// Remove the given device at the given address space.
remove(&self, base: u64, len: u64) -> Result<()>343     pub fn remove(&self, base: u64, len: u64) -> Result<()> {
344         if len == 0 {
345             return Err(Error::Overlap);
346         }
347 
348         let mut devices = self.devices.lock();
349         if devices
350             .iter()
351             .any(|(range, _dev)| range.base == base && range.len == len)
352         {
353             let ret = devices.remove(&BusRange { base, len });
354             if ret.is_some() {
355                 Ok(())
356             } else {
357                 Err(Error::Empty)
358             }
359         } else {
360             Err(Error::Empty)
361         }
362     }
363 
364     /// Reads data from the device that owns the range containing `addr` and puts it into `data`.
365     ///
366     /// Returns true on success, otherwise `data` is untouched.
read(&self, addr: u64, data: &mut [u8]) -> bool367     pub fn read(&self, addr: u64, data: &mut [u8]) -> bool {
368         if let Some((offset, address, dev)) = self.get_device(addr) {
369             let io = BusAccessInfo {
370                 address,
371                 offset,
372                 id: self.access_id,
373             };
374             match dev {
375                 BusDeviceEntry::OuterSync(dev) => dev.lock().read(io, data),
376                 BusDeviceEntry::InnerSync(dev) => dev.read(io, data),
377             }
378             true
379         } else {
380             false
381         }
382     }
383 
384     /// Writes `data` to the device that owns the range containing `addr`.
385     ///
386     /// Returns true on success, otherwise `data` is untouched.
write(&self, addr: u64, data: &[u8]) -> bool387     pub fn write(&self, addr: u64, data: &[u8]) -> bool {
388         if let Some((offset, address, dev)) = self.get_device(addr) {
389             let io = BusAccessInfo {
390                 address,
391                 offset,
392                 id: self.access_id,
393             };
394             match dev {
395                 BusDeviceEntry::OuterSync(dev) => dev.lock().write(io, data),
396                 BusDeviceEntry::InnerSync(dev) => dev.write(io, data),
397             }
398             true
399         } else {
400             false
401         }
402     }
403 }
404 
405 #[cfg(test)]
406 mod tests {
407     use super::*;
408 
409     struct DummyDevice;
410     impl BusDevice for DummyDevice {
debug_label(&self) -> String411         fn debug_label(&self) -> String {
412             "dummy device".to_owned()
413         }
414     }
415 
416     struct ConstantDevice {
417         uses_full_addr: bool,
418     }
419 
420     impl BusDevice for ConstantDevice {
debug_label(&self) -> String421         fn debug_label(&self) -> String {
422             "constant device".to_owned()
423         }
424 
read(&mut self, info: BusAccessInfo, data: &mut [u8])425         fn read(&mut self, info: BusAccessInfo, data: &mut [u8]) {
426             let addr = if self.uses_full_addr {
427                 info.address
428             } else {
429                 info.offset
430             };
431             for (i, v) in data.iter_mut().enumerate() {
432                 *v = (addr as u8) + (i as u8);
433             }
434         }
435 
write(&mut self, info: BusAccessInfo, data: &[u8])436         fn write(&mut self, info: BusAccessInfo, data: &[u8]) {
437             let addr = if self.uses_full_addr {
438                 info.address
439             } else {
440                 info.offset
441             };
442             for (i, v) in data.iter().enumerate() {
443                 assert_eq!(*v, (addr as u8) + (i as u8))
444             }
445         }
446     }
447 
448     #[test]
bus_insert()449     fn bus_insert() {
450         let bus = Bus::new();
451         let dummy = Arc::new(Mutex::new(DummyDevice));
452         assert!(bus.insert(dummy.clone(), 0x10, 0).is_err());
453         assert!(bus.insert(dummy.clone(), 0x10, 0x10).is_ok());
454         assert!(bus.insert(dummy.clone(), 0x0f, 0x10).is_err());
455         assert!(bus.insert(dummy.clone(), 0x10, 0x10).is_err());
456         assert!(bus.insert(dummy.clone(), 0x10, 0x15).is_err());
457         assert!(bus.insert(dummy.clone(), 0x12, 0x15).is_err());
458         assert!(bus.insert(dummy.clone(), 0x12, 0x01).is_err());
459         assert!(bus.insert(dummy.clone(), 0x0, 0x20).is_err());
460         assert!(bus.insert(dummy.clone(), 0x20, 0x05).is_ok());
461         assert!(bus.insert(dummy.clone(), 0x25, 0x05).is_ok());
462         assert!(bus.insert(dummy, 0x0, 0x10).is_ok());
463     }
464 
465     #[test]
bus_insert_full_addr()466     fn bus_insert_full_addr() {
467         let bus = Bus::new();
468         let dummy = Arc::new(Mutex::new(DummyDevice));
469         assert!(bus.insert(dummy.clone(), 0x10, 0).is_err());
470         assert!(bus.insert(dummy.clone(), 0x10, 0x10).is_ok());
471         assert!(bus.insert(dummy.clone(), 0x0f, 0x10).is_err());
472         assert!(bus.insert(dummy.clone(), 0x10, 0x10).is_err());
473         assert!(bus.insert(dummy.clone(), 0x10, 0x15).is_err());
474         assert!(bus.insert(dummy.clone(), 0x12, 0x15).is_err());
475         assert!(bus.insert(dummy.clone(), 0x12, 0x01).is_err());
476         assert!(bus.insert(dummy.clone(), 0x0, 0x20).is_err());
477         assert!(bus.insert(dummy.clone(), 0x20, 0x05).is_ok());
478         assert!(bus.insert(dummy.clone(), 0x25, 0x05).is_ok());
479         assert!(bus.insert(dummy, 0x0, 0x10).is_ok());
480     }
481 
482     #[test]
bus_read_write()483     fn bus_read_write() {
484         let bus = Bus::new();
485         let dummy = Arc::new(Mutex::new(DummyDevice));
486         assert!(bus.insert(dummy, 0x10, 0x10).is_ok());
487         assert!(bus.read(0x10, &mut [0, 0, 0, 0]));
488         assert!(bus.write(0x10, &[0, 0, 0, 0]));
489         assert!(bus.read(0x11, &mut [0, 0, 0, 0]));
490         assert!(bus.write(0x11, &[0, 0, 0, 0]));
491         assert!(bus.read(0x16, &mut [0, 0, 0, 0]));
492         assert!(bus.write(0x16, &[0, 0, 0, 0]));
493         assert!(!bus.read(0x20, &mut [0, 0, 0, 0]));
494         assert!(!bus.write(0x20, &[0, 0, 0, 0]));
495         assert!(!bus.read(0x06, &mut [0, 0, 0, 0]));
496         assert!(!bus.write(0x06, &[0, 0, 0, 0]));
497     }
498 
499     #[test]
bus_read_write_values()500     fn bus_read_write_values() {
501         let bus = Bus::new();
502         let dummy = Arc::new(Mutex::new(ConstantDevice {
503             uses_full_addr: false,
504         }));
505         assert!(bus.insert(dummy, 0x10, 0x10).is_ok());
506 
507         let mut values = [0, 1, 2, 3];
508         assert!(bus.read(0x10, &mut values));
509         assert_eq!(values, [0, 1, 2, 3]);
510         assert!(bus.write(0x10, &values));
511         assert!(bus.read(0x15, &mut values));
512         assert_eq!(values, [5, 6, 7, 8]);
513         assert!(bus.write(0x15, &values));
514     }
515 
516     #[test]
bus_read_write_full_addr_values()517     fn bus_read_write_full_addr_values() {
518         let bus = Bus::new();
519         let dummy = Arc::new(Mutex::new(ConstantDevice {
520             uses_full_addr: true,
521         }));
522         assert!(bus.insert(dummy, 0x10, 0x10).is_ok());
523 
524         let mut values = [0u8; 4];
525         assert!(bus.read(0x10, &mut values));
526         assert_eq!(values, [0x10, 0x11, 0x12, 0x13]);
527         assert!(bus.write(0x10, &values));
528         assert!(bus.read(0x15, &mut values));
529         assert_eq!(values, [0x15, 0x16, 0x17, 0x18]);
530         assert!(bus.write(0x15, &values));
531     }
532 
533     #[test]
bus_range_contains()534     fn bus_range_contains() {
535         let a = BusRange {
536             base: 0x1000,
537             len: 0x400,
538         };
539         assert!(a.contains(0x1000));
540         assert!(a.contains(0x13ff));
541         assert!(!a.contains(0xfff));
542         assert!(!a.contains(0x1400));
543         assert!(a.contains(0x1200));
544     }
545 
546     #[test]
bus_range_overlap()547     fn bus_range_overlap() {
548         let a = BusRange {
549             base: 0x1000,
550             len: 0x400,
551         };
552         assert!(a.overlaps(0x1000, 0x400));
553         assert!(a.overlaps(0xf00, 0x400));
554         assert!(a.overlaps(0x1000, 0x01));
555         assert!(a.overlaps(0xfff, 0x02));
556         assert!(a.overlaps(0x1100, 0x100));
557         assert!(a.overlaps(0x13ff, 0x100));
558         assert!(!a.overlaps(0x1400, 0x100));
559         assert!(!a.overlaps(0xf00, 0x100));
560     }
561 }
562