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