1 // Copyright 2017 The ChromiumOS Authors 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; 8 use std::cmp::Ordering; 9 use std::cmp::PartialEq; 10 use std::cmp::PartialOrd; 11 use std::collections::BTreeMap; 12 use std::collections::BTreeSet; 13 use std::fmt; 14 use std::result; 15 use std::sync::Arc; 16 17 use anyhow::anyhow; 18 use anyhow::Context; 19 use base::debug; 20 use base::error; 21 use base::Event; 22 use base::SharedMemory; 23 use remain::sorted; 24 use serde::Deserialize; 25 use serde::Serialize; 26 use snapshot::AnySnapshot; 27 use sync::Mutex; 28 use thiserror::Error; 29 30 #[cfg(feature = "stats")] 31 use crate::bus_stats::BusOperation; 32 #[cfg(feature = "stats")] 33 use crate::BusStatistics; 34 use crate::DeviceId; 35 use crate::PciAddress; 36 use crate::PciDevice; 37 use crate::Suspendable; 38 #[cfg(any(target_os = "android", target_os = "linux"))] 39 use crate::VfioPlatformDevice; 40 41 /// Information about how a device was accessed. 42 #[derive(Copy, Clone, Eq, PartialEq, Debug, Serialize, Deserialize)] 43 pub struct BusAccessInfo { 44 /// Offset from base address that the device was accessed at. 45 pub offset: u64, 46 /// Absolute address of the device's access in its address space. 47 pub address: u64, 48 /// ID of the entity requesting a device access, usually the VCPU id. 49 pub id: usize, 50 } 51 52 // Implement `Display` for `MinMax`. 53 impl std::fmt::Display for BusAccessInfo { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result54 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 55 write!(f, "{:?}", self) 56 } 57 } 58 59 /// Result of a write to a device's PCI configuration space. 60 /// This value represents the state change(s) that occurred due to the write. 61 #[derive(Clone, Debug, Default, PartialEq, Eq)] 62 pub struct ConfigWriteResult { 63 /// The BusRange in the vector will be removed from mmio_bus 64 pub mmio_remove: Vec<BusRange>, 65 66 /// The BusRange in the vector will be added into mmio_bus 67 pub mmio_add: Vec<BusRange>, 68 69 /// The BusRange in the vector will be removed from io_bus 70 pub io_remove: Vec<BusRange>, 71 72 /// The BusRange in the vector will be added into io_bus 73 pub io_add: Vec<BusRange>, 74 75 /// Device specified at PciAddress will be removed after this config write 76 /// - `Vec<PciAddress>>`: specified device will be removed after this config write 77 pub removed_pci_devices: Vec<PciAddress>, 78 } 79 80 #[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize, PartialOrd, Ord)] 81 pub enum BusType { 82 Mmio, 83 Io, 84 } 85 86 /// Trait for devices that respond to reads or writes in an arbitrary address space. 87 /// 88 /// The device does not care where it exists in address space as each method is only given an offset 89 /// into its allocated portion of address space. 90 #[allow(unused_variables)] 91 pub trait BusDevice: Send + Suspendable { 92 /// Returns a label suitable for debug output. debug_label(&self) -> String93 fn debug_label(&self) -> String; 94 /// Returns a unique id per device type suitable for metrics gathering. device_id(&self) -> DeviceId95 fn device_id(&self) -> DeviceId; 96 /// Reads at `offset` from this device read(&mut self, offset: BusAccessInfo, data: &mut [u8])97 fn read(&mut self, offset: BusAccessInfo, data: &mut [u8]) {} 98 /// Writes at `offset` into this device write(&mut self, offset: BusAccessInfo, data: &[u8])99 fn write(&mut self, offset: BusAccessInfo, data: &[u8]) {} 100 /// Sets a register in the configuration space. Only used by PCI. 101 /// * `reg_idx` - The index of the config register to modify. 102 /// * `offset` - Offset in to the register. config_register_write( &mut self, reg_idx: usize, offset: u64, data: &[u8], ) -> ConfigWriteResult103 fn config_register_write( 104 &mut self, 105 reg_idx: usize, 106 offset: u64, 107 data: &[u8], 108 ) -> ConfigWriteResult { 109 ConfigWriteResult { 110 ..Default::default() 111 } 112 } 113 /// Gets a register from the configuration space. Only used by PCI. 114 /// * `reg_idx` - The index of the config register to read. config_register_read(&self, reg_idx: usize) -> u32115 fn config_register_read(&self, reg_idx: usize) -> u32 { 116 0 117 } 118 /// Provides a memory region to back MMIO access to the configuration 119 /// space. If the device can keep the memory region up to date, then it 120 /// should return true, after which no more calls to config_register_read 121 /// will be made. Otherwise the device should return false. 122 /// 123 /// The device must set the header type register (0x0E) before returning 124 /// from this function, and must make no further modifications to it 125 /// after returning. This is to allow the caller to manage the multi- 126 /// function device bit without worrying about race conditions. 127 /// 128 /// * `shmem` - The shared memory to use for the configuration space. 129 /// * `base` - The base address of the memory region in shmem. 130 /// * `len` - The length of the memory region. init_pci_config_mapping(&mut self, shmem: &SharedMemory, base: usize, len: usize) -> bool131 fn init_pci_config_mapping(&mut self, shmem: &SharedMemory, base: usize, len: usize) -> bool { 132 false 133 } 134 /// Sets a register in the virtual config space. Only used by PCI. 135 /// * `reg_idx` - The index of the config register to modify. 136 /// * `value` - The value to be written. virtual_config_register_write(&mut self, reg_idx: usize, value: u32)137 fn virtual_config_register_write(&mut self, reg_idx: usize, value: u32) {} 138 /// Gets a register from the virtual config space. Only used by PCI. 139 /// * `reg_idx` - The index of the config register to read. virtual_config_register_read(&self, reg_idx: usize) -> u32140 fn virtual_config_register_read(&self, reg_idx: usize) -> u32 { 141 0 142 } 143 /// Invoked when the device is sandboxed. on_sandboxed(&mut self)144 fn on_sandboxed(&mut self) {} 145 146 /// Gets a list of all ranges registered by this BusDevice. get_ranges(&self) -> Vec<(BusRange, BusType)>147 fn get_ranges(&self) -> Vec<(BusRange, BusType)> { 148 Vec::new() 149 } 150 151 /// Invoked when the device is destroyed destroy_device(&mut self)152 fn destroy_device(&mut self) {} 153 154 /// Returns the secondary bus number if this bus device is pci bridge is_bridge(&self) -> Option<u8>155 fn is_bridge(&self) -> Option<u8> { 156 None 157 } 158 } 159 160 pub trait BusDeviceSync: BusDevice + Sync { read(&self, offset: BusAccessInfo, data: &mut [u8])161 fn read(&self, offset: BusAccessInfo, data: &mut [u8]); write(&self, offset: BusAccessInfo, data: &[u8])162 fn write(&self, offset: BusAccessInfo, data: &[u8]); snapshot_sync(&self) -> anyhow::Result<AnySnapshot>163 fn snapshot_sync(&self) -> anyhow::Result<AnySnapshot> { 164 Err(anyhow!( 165 "snapshot_sync not implemented for {}", 166 std::any::type_name::<Self>() 167 )) 168 } 169 /// Load a saved snapshot of an image. restore_sync(&self, _data: AnySnapshot) -> anyhow::Result<()>170 fn restore_sync(&self, _data: AnySnapshot) -> anyhow::Result<()> { 171 Err(anyhow!( 172 "restore_sync not implemented for {}", 173 std::any::type_name::<Self>() 174 )) 175 } 176 /// Stop all threads related to the device. 177 /// Sleep should be idempotent. sleep_sync(&self) -> anyhow::Result<()>178 fn sleep_sync(&self) -> anyhow::Result<()> { 179 Err(anyhow!( 180 "sleep_sync not implemented for {}", 181 std::any::type_name::<Self>() 182 )) 183 } 184 /// Create/Resume all threads related to the device. 185 /// Wake should be idempotent. wake_sync(&self) -> anyhow::Result<()>186 fn wake_sync(&self) -> anyhow::Result<()> { 187 Err(anyhow!( 188 "wake_sync not implemented for {}", 189 std::any::type_name::<Self>() 190 )) 191 } 192 } 193 194 pub trait BusResumeDevice: Send { 195 /// notify the devices which are invoked 196 /// before the VM resumes form suspend. resume_imminent(&mut self)197 fn resume_imminent(&mut self) {} 198 } 199 200 /// The key to identify hotplug device from host view. 201 /// like host sysfs path for vfio pci device, host disk file 202 /// path for virtio block device 203 #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] 204 pub enum HotPlugKey { 205 HostUpstreamPort { host_addr: PciAddress }, 206 HostDownstreamPort { host_addr: PciAddress }, 207 HostVfio { host_addr: PciAddress }, 208 GuestDevice { guest_addr: PciAddress }, 209 } 210 211 /// Trait for devices that notify hotplug event into guest 212 pub trait HotPlugBus: Send { 213 /// Request hot plug event. Returns error if the request is not sent. Upon success, optionally 214 /// returns an event, which is triggerred once when the guest OS completes the request (by 215 /// sending PCI_EXP_SLTCTL_CCIE). Returns None if no such mechanism is provided. 216 /// * 'addr' - the guest pci address for hotplug in device hot_plug(&mut self, addr: PciAddress) -> anyhow::Result<Option<Event>>217 fn hot_plug(&mut self, addr: PciAddress) -> anyhow::Result<Option<Event>>; 218 /// Request hot unplug event. Returns error if the request is not sent. Upon success, optionally 219 /// returns an event, which is triggerred once when the guest OS completes the request (by 220 /// sending PCI_EXP_SLTCTL_CCIE). Returns None if no such mechanism is provided. 221 /// * 'addr' - the guest pci address for hotplug out device hot_unplug(&mut self, addr: PciAddress) -> anyhow::Result<Option<Event>>222 fn hot_unplug(&mut self, addr: PciAddress) -> anyhow::Result<Option<Event>>; 223 /// Get a notification event when the HotPlugBus is ready for hot plug commands. If the port is 224 /// already ready, then the notification event is triggerred immediately. get_ready_notification(&mut self) -> anyhow::Result<Event>225 fn get_ready_notification(&mut self) -> anyhow::Result<Event>; 226 /// Check whether the hotplug bus is available to add the new device 227 /// 228 /// - 'None': hotplug bus isn't match with host pci device 229 /// - 'Some(bus_num)': hotplug bus is match and put the device at bus_num is_match(&self, host_addr: PciAddress) -> Option<u8>230 fn is_match(&self, host_addr: PciAddress) -> Option<u8>; 231 /// Gets the upstream PCI Address of the hotplug bus get_address(&self) -> Option<PciAddress>232 fn get_address(&self) -> Option<PciAddress>; 233 /// Gets the secondary bus number of this bus get_secondary_bus_number(&self) -> Option<u8>234 fn get_secondary_bus_number(&self) -> Option<u8>; 235 /// Add hotplug device into this bus 236 /// * 'hotplug_key' - the key to identify hotplug device from host view 237 /// * 'guest_addr' - the guest pci address for hotplug device add_hotplug_device(&mut self, hotplug_key: HotPlugKey, guest_addr: PciAddress)238 fn add_hotplug_device(&mut self, hotplug_key: HotPlugKey, guest_addr: PciAddress); 239 /// get guest pci address from the specified hotplug_key get_hotplug_device(&self, hotplug_key: HotPlugKey) -> Option<PciAddress>240 fn get_hotplug_device(&self, hotplug_key: HotPlugKey) -> Option<PciAddress>; 241 /// Check whether this hotplug bus is empty is_empty(&self) -> bool242 fn is_empty(&self) -> bool; 243 /// Get hotplug key of this hotplug bus get_hotplug_key(&self) -> Option<HotPlugKey>244 fn get_hotplug_key(&self) -> Option<HotPlugKey>; 245 } 246 247 /// Trait for generic device abstraction, that is, all devices that reside on BusDevice and want 248 /// to be converted back to its original type. Each new foo device must provide 249 /// as_foo_device() + as_foo_device_mut() + into_foo_device(), default impl methods return None. 250 pub trait BusDeviceObj { as_pci_device(&self) -> Option<&dyn PciDevice>251 fn as_pci_device(&self) -> Option<&dyn PciDevice> { 252 None 253 } as_pci_device_mut(&mut self) -> Option<&mut dyn PciDevice>254 fn as_pci_device_mut(&mut self) -> Option<&mut dyn PciDevice> { 255 None 256 } into_pci_device(self: Box<Self>) -> Option<Box<dyn PciDevice>>257 fn into_pci_device(self: Box<Self>) -> Option<Box<dyn PciDevice>> { 258 None 259 } 260 #[cfg(any(target_os = "android", target_os = "linux"))] as_platform_device(&self) -> Option<&VfioPlatformDevice>261 fn as_platform_device(&self) -> Option<&VfioPlatformDevice> { 262 None 263 } 264 #[cfg(any(target_os = "android", target_os = "linux"))] as_platform_device_mut(&mut self) -> Option<&mut VfioPlatformDevice>265 fn as_platform_device_mut(&mut self) -> Option<&mut VfioPlatformDevice> { 266 None 267 } 268 #[cfg(any(target_os = "android", target_os = "linux"))] into_platform_device(self: Box<Self>) -> Option<Box<VfioPlatformDevice>>269 fn into_platform_device(self: Box<Self>) -> Option<Box<VfioPlatformDevice>> { 270 None 271 } 272 } 273 274 #[sorted] 275 #[derive(Error, Debug)] 276 pub enum Error { 277 #[error("Bus Range not found")] 278 Empty, 279 /// The insertion failed because the new device overlapped with an old device. 280 #[error("new device {base},{len} overlaps with an old device {other_base},{other_len}")] 281 Overlap { 282 base: u64, 283 len: u64, 284 other_base: u64, 285 other_len: u64, 286 }, 287 } 288 289 pub type Result<T> = result::Result<T, Error>; 290 291 /// Holds a base and length representing the address space occupied by a `BusDevice`. 292 /// 293 /// * base - The address at which the range start. 294 /// * len - The length of the range in bytes. 295 #[derive(Copy, Clone, Serialize, Deserialize)] 296 pub struct BusRange { 297 pub base: u64, 298 pub len: u64, 299 } 300 301 impl BusRange { 302 /// Returns true if `addr` is within the range. contains(&self, addr: u64) -> bool303 pub fn contains(&self, addr: u64) -> bool { 304 self.base <= addr && addr < self.base.saturating_add(self.len) 305 } 306 307 /// Returns true if there is overlap with the given range. overlaps(&self, base: u64, len: u64) -> bool308 pub fn overlaps(&self, base: u64, len: u64) -> bool { 309 self.base < base.saturating_add(len) && base < self.base.saturating_add(self.len) 310 } 311 } 312 313 impl Eq for BusRange {} 314 315 impl PartialEq for BusRange { eq(&self, other: &BusRange) -> bool316 fn eq(&self, other: &BusRange) -> bool { 317 self.base == other.base 318 } 319 } 320 321 impl Ord for BusRange { cmp(&self, other: &BusRange) -> Ordering322 fn cmp(&self, other: &BusRange) -> Ordering { 323 self.base.cmp(&other.base) 324 } 325 } 326 327 impl PartialOrd for BusRange { partial_cmp(&self, other: &BusRange) -> Option<Ordering>328 fn partial_cmp(&self, other: &BusRange) -> Option<Ordering> { 329 Some(self.cmp(other)) 330 } 331 } 332 333 impl std::fmt::Debug for BusRange { fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result334 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 335 write!(f, "{:#x}..+{:#x}", self.base, self.len) 336 } 337 } 338 339 #[derive(Clone)] 340 struct BusEntry { 341 #[cfg(feature = "stats")] 342 index: usize, 343 device: BusDeviceEntry, 344 } 345 346 #[derive(Clone)] 347 enum BusDeviceEntry { 348 OuterSync(Arc<Mutex<dyn BusDevice>>), 349 InnerSync(Arc<dyn BusDeviceSync>), 350 } 351 352 /// A device container for routing reads and writes over some address space. 353 /// 354 /// This doesn't have any restrictions on what kind of device or address space this applies to. The 355 /// only restriction is that no two devices can overlap in this address space. 356 #[derive(Clone)] 357 pub struct Bus { 358 devices: Arc<Mutex<BTreeMap<BusRange, BusEntry>>>, 359 access_id: usize, 360 #[cfg(feature = "stats")] 361 pub stats: Arc<Mutex<BusStatistics>>, 362 bus_type: BusType, 363 } 364 365 impl Bus { 366 /// Constructs an a bus with an empty address space. new(bus_type: BusType) -> Bus367 pub fn new(bus_type: BusType) -> Bus { 368 Bus { 369 devices: Arc::new(Mutex::new(BTreeMap::new())), 370 access_id: 0, 371 #[cfg(feature = "stats")] 372 stats: Arc::new(Mutex::new(BusStatistics::new())), 373 bus_type, 374 } 375 } 376 377 /// Gets the bus type get_bus_type(&self) -> BusType378 pub fn get_bus_type(&self) -> BusType { 379 self.bus_type 380 } 381 382 /// Sets the id that will be used for BusAccessInfo. set_access_id(&mut self, id: usize)383 pub fn set_access_id(&mut self, id: usize) { 384 self.access_id = id; 385 } 386 first_before(&self, addr: u64) -> Option<(BusRange, BusEntry)>387 fn first_before(&self, addr: u64) -> Option<(BusRange, BusEntry)> { 388 let devices = self.devices.lock(); 389 let (range, entry) = devices 390 .range(..=BusRange { base: addr, len: 1 }) 391 .next_back()?; 392 Some((*range, entry.clone())) 393 } 394 get_device(&self, addr: u64) -> Option<(u64, u64, BusEntry)>395 fn get_device(&self, addr: u64) -> Option<(u64, u64, BusEntry)> { 396 if let Some((range, entry)) = self.first_before(addr) { 397 let offset = addr - range.base; 398 if offset < range.len { 399 return Some((offset, addr, entry)); 400 } 401 } 402 None 403 } 404 405 /// There is no unique ID for device instances. For now we use the Arc pointers to dedup them. 406 /// 407 /// See virtio-gpu for an example of a single device instance with multiple bus entries. 408 /// 409 /// TODO: Add a unique ID to BusDevice and use that instead of pointers. unique_devices(&self) -> Vec<BusDeviceEntry>410 fn unique_devices(&self) -> Vec<BusDeviceEntry> { 411 let mut seen_ptrs = BTreeSet::new(); 412 self.devices 413 .lock() 414 .iter() 415 .map(|(_, bus_entry)| bus_entry.device.clone()) 416 .filter(|dev| match dev { 417 BusDeviceEntry::OuterSync(dev) => seen_ptrs.insert(Arc::as_ptr(dev) as *const u8), 418 BusDeviceEntry::InnerSync(dev) => seen_ptrs.insert(Arc::as_ptr(dev) as *const u8), 419 }) 420 .collect() 421 } 422 423 /// Same as `unique_devices`, but also calculates the "snapshot key" for each device. 424 /// 425 /// The keys are used to associate a particular device with data in a serialized snapshot. The 426 /// keys need to be stable across multiple runs of the same crosvm binary. 427 /// 428 /// It is most convienent to calculate all the snapshot keys at once, because the keys are 429 /// dependant on the order of devices on the bus. unique_devices_with_snapshot_key(&self) -> Vec<(String, BusDeviceEntry)>430 fn unique_devices_with_snapshot_key(&self) -> Vec<(String, BusDeviceEntry)> { 431 let mut next_ids = BTreeMap::<String, usize>::new(); 432 let mut choose_key = |debug_label: String| -> String { 433 let label = debug_label.replace(char::is_whitespace, "-"); 434 let id = next_ids.entry(label.clone()).or_default(); 435 let key = format!("{}-{}", label, id); 436 *id += 1; 437 key 438 }; 439 440 let mut result = Vec::new(); 441 for device_entry in self.unique_devices() { 442 let key = match &device_entry { 443 BusDeviceEntry::OuterSync(d) => choose_key(d.lock().debug_label()), 444 BusDeviceEntry::InnerSync(d) => choose_key(d.debug_label()), 445 }; 446 result.push((key, device_entry)); 447 } 448 result 449 } 450 sleep_devices(&self) -> anyhow::Result<()>451 pub fn sleep_devices(&self) -> anyhow::Result<()> { 452 for device_entry in self.unique_devices() { 453 match device_entry { 454 BusDeviceEntry::OuterSync(dev) => { 455 let mut dev = (*dev).lock(); 456 debug!("Sleep on device: {}", dev.debug_label()); 457 dev.sleep() 458 .with_context(|| format!("failed to sleep {}", dev.debug_label()))?; 459 } 460 BusDeviceEntry::InnerSync(dev) => { 461 debug!("Sleep on device: {}", dev.debug_label()); 462 dev.sleep_sync() 463 .with_context(|| format!("failed to sleep {}", dev.debug_label()))?; 464 } 465 } 466 } 467 Ok(()) 468 } 469 wake_devices(&self) -> anyhow::Result<()>470 pub fn wake_devices(&self) -> anyhow::Result<()> { 471 for device_entry in self.unique_devices() { 472 match device_entry { 473 BusDeviceEntry::OuterSync(dev) => { 474 let mut dev = dev.lock(); 475 debug!("Wake on device: {}", dev.debug_label()); 476 dev.wake() 477 .with_context(|| format!("failed to wake {}", dev.debug_label()))?; 478 } 479 BusDeviceEntry::InnerSync(dev) => { 480 debug!("Wake on device: {}", dev.debug_label()); 481 dev.wake_sync() 482 .with_context(|| format!("failed to wake {}", dev.debug_label()))?; 483 } 484 } 485 } 486 Ok(()) 487 } 488 snapshot_devices( &self, snapshot_writer: &snapshot::SnapshotWriter, ) -> anyhow::Result<()>489 pub fn snapshot_devices( 490 &self, 491 snapshot_writer: &snapshot::SnapshotWriter, 492 ) -> anyhow::Result<()> { 493 for (snapshot_key, device_entry) in self.unique_devices_with_snapshot_key() { 494 match device_entry { 495 BusDeviceEntry::OuterSync(dev) => { 496 let mut dev = dev.lock(); 497 debug!("Snapshot on device: {}", dev.debug_label()); 498 snapshot_writer.write_fragment( 499 &snapshot_key, 500 &(*dev) 501 .snapshot() 502 .with_context(|| format!("failed to snapshot {}", dev.debug_label()))?, 503 )?; 504 } 505 BusDeviceEntry::InnerSync(dev) => { 506 debug!("Snapshot on device: {}", dev.debug_label()); 507 snapshot_writer.write_fragment( 508 &snapshot_key, 509 &dev.snapshot_sync() 510 .with_context(|| format!("failed to snapshot {}", dev.debug_label()))?, 511 )?; 512 } 513 } 514 } 515 Ok(()) 516 } 517 restore_devices( &self, snapshot_reader: &snapshot::SnapshotReader, ) -> anyhow::Result<()>518 pub fn restore_devices( 519 &self, 520 snapshot_reader: &snapshot::SnapshotReader, 521 ) -> anyhow::Result<()> { 522 let mut unused_keys: BTreeSet<String> = 523 snapshot_reader.list_fragments()?.into_iter().collect(); 524 for (snapshot_key, device_entry) in self.unique_devices_with_snapshot_key() { 525 unused_keys.remove(&snapshot_key); 526 match device_entry { 527 BusDeviceEntry::OuterSync(dev) => { 528 let mut dev = dev.lock(); 529 debug!("Restore on device: {}", dev.debug_label()); 530 dev.restore(snapshot_reader.read_fragment(&snapshot_key)?) 531 .with_context(|| { 532 format!("restore failed for device {}", dev.debug_label()) 533 })?; 534 } 535 BusDeviceEntry::InnerSync(dev) => { 536 debug!("Restore on device: {}", dev.debug_label()); 537 dev.restore_sync(snapshot_reader.read_fragment(&snapshot_key)?) 538 .with_context(|| { 539 format!("restore failed for device {}", dev.debug_label()) 540 })?; 541 } 542 } 543 } 544 545 if !unused_keys.is_empty() { 546 error!( 547 "unused restore data in bus, devices might be missing: {:?}", 548 unused_keys 549 ); 550 } 551 552 Ok(()) 553 } 554 555 /// Puts the given device at the given address space. insert(&self, device: Arc<Mutex<dyn BusDevice>>, base: u64, len: u64) -> Result<()>556 pub fn insert(&self, device: Arc<Mutex<dyn BusDevice>>, base: u64, len: u64) -> Result<()> { 557 if len == 0 { 558 return Err(Error::Overlap { 559 base, 560 len, 561 other_base: 0, 562 other_len: 0, 563 }); 564 } 565 566 // Reject all cases where the new device's range overlaps with an existing device. 567 let mut devices = self.devices.lock(); 568 devices.iter().try_for_each(|(range, _dev)| { 569 if range.overlaps(base, len) { 570 Err(Error::Overlap { 571 base, 572 len, 573 other_base: range.base, 574 other_len: range.len, 575 }) 576 } else { 577 Ok(()) 578 } 579 })?; 580 581 #[cfg(feature = "stats")] 582 let name = device.lock().debug_label(); 583 #[cfg(feature = "stats")] 584 let device_id = device.lock().device_id(); 585 if devices 586 .insert( 587 BusRange { base, len }, 588 BusEntry { 589 #[cfg(feature = "stats")] 590 index: self 591 .stats 592 .lock() 593 .next_device_index(name, device_id.into(), base, len), 594 device: BusDeviceEntry::OuterSync(device), 595 }, 596 ) 597 .is_some() 598 { 599 return Err(Error::Overlap { 600 base, 601 len, 602 other_base: base, 603 other_len: len, 604 }); 605 } 606 607 Ok(()) 608 } 609 610 /// Puts the given device that implements BusDeviceSync at the given address space. Devices 611 /// that implement BusDeviceSync manage thread safety internally, and thus can be written to 612 /// by multiple threads simultaneously. insert_sync(&self, device: Arc<dyn BusDeviceSync>, base: u64, len: u64) -> Result<()>613 pub fn insert_sync(&self, device: Arc<dyn BusDeviceSync>, base: u64, len: u64) -> Result<()> { 614 if len == 0 { 615 return Err(Error::Overlap { 616 base, 617 len, 618 other_base: 0, 619 other_len: 0, 620 }); 621 } 622 623 // Reject all cases where the new device's range overlaps with an existing device. 624 let mut devices = self.devices.lock(); 625 devices.iter().try_for_each(|(range, _dev)| { 626 if range.overlaps(base, len) { 627 Err(Error::Overlap { 628 base, 629 len, 630 other_base: range.base, 631 other_len: range.len, 632 }) 633 } else { 634 Ok(()) 635 } 636 })?; 637 638 if devices 639 .insert( 640 BusRange { base, len }, 641 BusEntry { 642 #[cfg(feature = "stats")] 643 index: self.stats.lock().next_device_index( 644 device.debug_label(), 645 device.device_id().into(), 646 base, 647 len, 648 ), 649 device: BusDeviceEntry::InnerSync(device), 650 }, 651 ) 652 .is_some() 653 { 654 return Err(Error::Overlap { 655 base, 656 len, 657 other_base: base, 658 other_len: len, 659 }); 660 } 661 662 Ok(()) 663 } 664 665 /// Remove the given device at the given address space. remove(&self, base: u64, len: u64) -> Result<()>666 pub fn remove(&self, base: u64, len: u64) -> Result<()> { 667 if len == 0 { 668 return Err(Error::Overlap { 669 base, 670 len, 671 other_base: 0, 672 other_len: 0, 673 }); 674 } 675 676 let mut devices = self.devices.lock(); 677 if devices 678 .iter() 679 .any(|(range, _dev)| range.base == base && range.len == len) 680 { 681 let ret = devices.remove(&BusRange { base, len }); 682 if ret.is_some() { 683 Ok(()) 684 } else { 685 Err(Error::Empty) 686 } 687 } else { 688 Err(Error::Empty) 689 } 690 } 691 692 /// Reads data from the device that owns the range containing `addr` and puts it into `data`. 693 /// 694 /// Returns true on success, otherwise `data` is filled with zeroes. read(&self, addr: u64, data: &mut [u8]) -> bool695 pub fn read(&self, addr: u64, data: &mut [u8]) -> bool { 696 #[cfg(feature = "stats")] 697 let start = self.stats.lock().start_stat(); 698 699 // Initialize `data` with all zeroes to ensure consistent results even if device `read()` 700 // implementations don't always fill every byte. 701 data.fill(0); 702 703 let device_index = if let Some((offset, address, entry)) = self.get_device(addr) { 704 let io = BusAccessInfo { 705 address, 706 offset, 707 id: self.access_id, 708 }; 709 710 match &entry.device { 711 BusDeviceEntry::OuterSync(dev) => dev.lock().read(io, data), 712 BusDeviceEntry::InnerSync(dev) => dev.read(io, data), 713 } 714 #[cfg(feature = "stats")] 715 let index = Some(entry.index); 716 #[cfg(not(feature = "stats"))] 717 let index = Some(()); 718 index 719 } else { 720 None 721 }; 722 723 #[cfg(feature = "stats")] 724 if let Some(device_index) = device_index { 725 self.stats 726 .lock() 727 .end_stat(BusOperation::Write, start, device_index); 728 return true; 729 } 730 731 device_index.is_some() 732 } 733 734 /// Writes `data` to the device that owns the range containing `addr`. 735 /// 736 /// Returns true on success, otherwise `data` is untouched. write(&self, addr: u64, data: &[u8]) -> bool737 pub fn write(&self, addr: u64, data: &[u8]) -> bool { 738 #[cfg(feature = "stats")] 739 let start = self.stats.lock().start_stat(); 740 741 let device_index = if let Some((offset, address, entry)) = self.get_device(addr) { 742 let io = BusAccessInfo { 743 address, 744 offset, 745 id: self.access_id, 746 }; 747 748 match &entry.device { 749 BusDeviceEntry::OuterSync(dev) => dev.lock().write(io, data), 750 BusDeviceEntry::InnerSync(dev) => dev.write(io, data), 751 } 752 753 #[cfg(feature = "stats")] 754 let index = Some(entry.index); 755 #[cfg(not(feature = "stats"))] 756 let index = Some(()); 757 index 758 } else { 759 None 760 }; 761 762 #[cfg(feature = "stats")] 763 if let Some(device_index) = device_index { 764 self.stats 765 .lock() 766 .end_stat(BusOperation::Write, start, device_index); 767 } 768 device_index.is_some() 769 } 770 } 771 772 impl Default for Bus { default() -> Self773 fn default() -> Self { 774 Self::new(BusType::Io) 775 } 776 } 777 778 #[cfg(test)] 779 mod tests { 780 use anyhow::Result as AnyhowResult; 781 782 use super::*; 783 use crate::pci::CrosvmDeviceId; 784 use crate::suspendable::Suspendable; 785 use crate::suspendable_tests; 786 787 #[derive(Copy, Clone, Serialize, Deserialize, Eq, PartialEq, Debug)] 788 struct DummyDevice; 789 790 impl BusDevice for DummyDevice { device_id(&self) -> DeviceId791 fn device_id(&self) -> DeviceId { 792 CrosvmDeviceId::Cmos.into() 793 } debug_label(&self) -> String794 fn debug_label(&self) -> String { 795 "dummy device".to_owned() 796 } 797 } 798 799 impl Suspendable for DummyDevice { snapshot(&mut self) -> AnyhowResult<AnySnapshot>800 fn snapshot(&mut self) -> AnyhowResult<AnySnapshot> { 801 AnySnapshot::to_any(self).context("error serializing") 802 } 803 restore(&mut self, data: AnySnapshot) -> AnyhowResult<()>804 fn restore(&mut self, data: AnySnapshot) -> AnyhowResult<()> { 805 *self = AnySnapshot::from_any(data).context("error deserializing")?; 806 Ok(()) 807 } 808 sleep(&mut self) -> AnyhowResult<()>809 fn sleep(&mut self) -> AnyhowResult<()> { 810 Ok(()) 811 } 812 wake(&mut self) -> AnyhowResult<()>813 fn wake(&mut self) -> AnyhowResult<()> { 814 Ok(()) 815 } 816 } 817 818 #[derive(Copy, Clone, Serialize, Deserialize, Eq, PartialEq, Debug)] 819 struct ConstantDevice { 820 uses_full_addr: bool, 821 } 822 823 impl BusDevice for ConstantDevice { device_id(&self) -> DeviceId824 fn device_id(&self) -> DeviceId { 825 CrosvmDeviceId::Cmos.into() 826 } 827 debug_label(&self) -> String828 fn debug_label(&self) -> String { 829 "constant device".to_owned() 830 } 831 read(&mut self, info: BusAccessInfo, data: &mut [u8])832 fn read(&mut self, info: BusAccessInfo, data: &mut [u8]) { 833 let addr = if self.uses_full_addr { 834 info.address 835 } else { 836 info.offset 837 }; 838 for (i, v) in data.iter_mut().enumerate() { 839 *v = (addr as u8) + (i as u8); 840 } 841 } 842 write(&mut self, info: BusAccessInfo, data: &[u8])843 fn write(&mut self, info: BusAccessInfo, data: &[u8]) { 844 let addr = if self.uses_full_addr { 845 info.address 846 } else { 847 info.offset 848 }; 849 for (i, v) in data.iter().enumerate() { 850 assert_eq!(*v, (addr as u8) + (i as u8)) 851 } 852 } 853 } 854 855 impl Suspendable for ConstantDevice { snapshot(&mut self) -> AnyhowResult<AnySnapshot>856 fn snapshot(&mut self) -> AnyhowResult<AnySnapshot> { 857 AnySnapshot::to_any(self).context("error serializing") 858 } 859 restore(&mut self, data: AnySnapshot) -> AnyhowResult<()>860 fn restore(&mut self, data: AnySnapshot) -> AnyhowResult<()> { 861 *self = AnySnapshot::from_any(data).context("error deserializing")?; 862 Ok(()) 863 } 864 sleep(&mut self) -> AnyhowResult<()>865 fn sleep(&mut self) -> AnyhowResult<()> { 866 Ok(()) 867 } 868 wake(&mut self) -> AnyhowResult<()>869 fn wake(&mut self) -> AnyhowResult<()> { 870 Ok(()) 871 } 872 } 873 modify_constant_device(constant: &mut ConstantDevice)874 fn modify_constant_device(constant: &mut ConstantDevice) { 875 constant.uses_full_addr = !constant.uses_full_addr; 876 } 877 878 #[test] bus_insert()879 fn bus_insert() { 880 let bus = Bus::new(BusType::Io); 881 let dummy = Arc::new(Mutex::new(DummyDevice)); 882 assert!(bus.insert(dummy.clone(), 0x10, 0).is_err()); 883 assert!(bus.insert(dummy.clone(), 0x10, 0x10).is_ok()); 884 assert!(bus.insert(dummy.clone(), 0x0f, 0x10).is_err()); 885 assert!(bus.insert(dummy.clone(), 0x10, 0x10).is_err()); 886 assert!(bus.insert(dummy.clone(), 0x10, 0x15).is_err()); 887 assert!(bus.insert(dummy.clone(), 0x12, 0x15).is_err()); 888 assert!(bus.insert(dummy.clone(), 0x12, 0x01).is_err()); 889 assert!(bus.insert(dummy.clone(), 0x0, 0x20).is_err()); 890 assert!(bus.insert(dummy.clone(), 0x20, 0x05).is_ok()); 891 assert!(bus.insert(dummy.clone(), 0x25, 0x05).is_ok()); 892 assert!(bus.insert(dummy, 0x0, 0x10).is_ok()); 893 } 894 895 #[test] bus_insert_full_addr()896 fn bus_insert_full_addr() { 897 let bus = Bus::new(BusType::Io); 898 let dummy = Arc::new(Mutex::new(DummyDevice)); 899 assert!(bus.insert(dummy.clone(), 0x10, 0).is_err()); 900 assert!(bus.insert(dummy.clone(), 0x10, 0x10).is_ok()); 901 assert!(bus.insert(dummy.clone(), 0x0f, 0x10).is_err()); 902 assert!(bus.insert(dummy.clone(), 0x10, 0x10).is_err()); 903 assert!(bus.insert(dummy.clone(), 0x10, 0x15).is_err()); 904 assert!(bus.insert(dummy.clone(), 0x12, 0x15).is_err()); 905 assert!(bus.insert(dummy.clone(), 0x12, 0x01).is_err()); 906 assert!(bus.insert(dummy.clone(), 0x0, 0x20).is_err()); 907 assert!(bus.insert(dummy.clone(), 0x20, 0x05).is_ok()); 908 assert!(bus.insert(dummy.clone(), 0x25, 0x05).is_ok()); 909 assert!(bus.insert(dummy, 0x0, 0x10).is_ok()); 910 } 911 912 #[test] bus_read_write()913 fn bus_read_write() { 914 let bus = Bus::new(BusType::Io); 915 let dummy = Arc::new(Mutex::new(DummyDevice)); 916 assert!(bus.insert(dummy, 0x10, 0x10).is_ok()); 917 assert!(bus.read(0x10, &mut [0, 0, 0, 0])); 918 assert!(bus.write(0x10, &[0, 0, 0, 0])); 919 assert!(bus.read(0x11, &mut [0, 0, 0, 0])); 920 assert!(bus.write(0x11, &[0, 0, 0, 0])); 921 assert!(bus.read(0x16, &mut [0, 0, 0, 0])); 922 assert!(bus.write(0x16, &[0, 0, 0, 0])); 923 assert!(!bus.read(0x20, &mut [0, 0, 0, 0])); 924 assert!(!bus.write(0x20, &[0, 0, 0, 0])); 925 assert!(!bus.read(0x06, &mut [0, 0, 0, 0])); 926 assert!(!bus.write(0x06, &[0, 0, 0, 0])); 927 } 928 929 #[test] bus_read_write_values()930 fn bus_read_write_values() { 931 let bus = Bus::new(BusType::Io); 932 let dummy = Arc::new(Mutex::new(ConstantDevice { 933 uses_full_addr: false, 934 })); 935 assert!(bus.insert(dummy, 0x10, 0x10).is_ok()); 936 937 let mut values = [0, 1, 2, 3]; 938 assert!(bus.read(0x10, &mut values)); 939 assert_eq!(values, [0, 1, 2, 3]); 940 assert!(bus.write(0x10, &values)); 941 assert!(bus.read(0x15, &mut values)); 942 assert_eq!(values, [5, 6, 7, 8]); 943 assert!(bus.write(0x15, &values)); 944 } 945 946 #[test] bus_read_write_full_addr_values()947 fn bus_read_write_full_addr_values() { 948 let bus = Bus::new(BusType::Io); 949 let dummy = Arc::new(Mutex::new(ConstantDevice { 950 uses_full_addr: true, 951 })); 952 assert!(bus.insert(dummy, 0x10, 0x10).is_ok()); 953 954 let mut values = [0u8; 4]; 955 assert!(bus.read(0x10, &mut values)); 956 assert_eq!(values, [0x10, 0x11, 0x12, 0x13]); 957 assert!(bus.write(0x10, &values)); 958 assert!(bus.read(0x15, &mut values)); 959 assert_eq!(values, [0x15, 0x16, 0x17, 0x18]); 960 assert!(bus.write(0x15, &values)); 961 } 962 963 #[test] bus_read_no_device()964 fn bus_read_no_device() { 965 let bus = Bus::new(BusType::Io); 966 967 // read() should return false, since there is no device at address 0x10, but it should 968 // also fill the data with 0s. 969 let mut values = [1, 2, 3, 4]; 970 assert!(!bus.read(0x10, &mut values)); 971 assert_eq!(values, [0, 0, 0, 0]); 972 } 973 974 suspendable_tests!( 975 constant_device_true, 976 ConstantDevice { 977 uses_full_addr: true, 978 }, 979 modify_constant_device 980 ); 981 982 suspendable_tests!( 983 constant_device_false, 984 ConstantDevice { 985 uses_full_addr: false, 986 }, 987 modify_constant_device 988 ); 989 990 #[test] bus_range_contains()991 fn bus_range_contains() { 992 let a = BusRange { 993 base: 0x1000, 994 len: 0x400, 995 }; 996 assert!(a.contains(0x1000)); 997 assert!(a.contains(0x13ff)); 998 assert!(!a.contains(0xfff)); 999 assert!(!a.contains(0x1400)); 1000 assert!(a.contains(0x1200)); 1001 } 1002 1003 #[test] bus_range_overlap()1004 fn bus_range_overlap() { 1005 let a = BusRange { 1006 base: 0x1000, 1007 len: 0x400, 1008 }; 1009 assert!(a.overlaps(0x1000, 0x400)); 1010 assert!(a.overlaps(0xf00, 0x400)); 1011 assert!(a.overlaps(0x1000, 0x01)); 1012 assert!(a.overlaps(0xfff, 0x02)); 1013 assert!(a.overlaps(0x1100, 0x100)); 1014 assert!(a.overlaps(0x13ff, 0x100)); 1015 assert!(!a.overlaps(0x1400, 0x100)); 1016 assert!(!a.overlaps(0xf00, 0x100)); 1017 } 1018 } 1019