1 // Copyright 2018 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 use std::collections::HashMap;
6 use std::collections::HashSet;
7 use std::sync::Arc;
8
9 #[cfg(target_arch = "x86_64")]
10 use acpi_tables::sdt::SDT;
11 use anyhow::bail;
12 use base::error;
13 use base::trace;
14 use base::warn;
15 use base::MemoryMapping;
16 use base::RawDescriptor;
17 use base::SharedMemory;
18 use remain::sorted;
19 use resources::Error as SystemAllocatorFaliure;
20 use resources::SystemAllocator;
21 use snapshot::AnySnapshot;
22 use sync::Mutex;
23 use thiserror::Error;
24 use vm_control::api::VmMemoryClient;
25
26 use super::PciId;
27 use crate::bus::BusDeviceObj;
28 use crate::bus::BusRange;
29 use crate::bus::BusType;
30 use crate::bus::ConfigWriteResult;
31 use crate::pci::pci_configuration;
32 use crate::pci::pci_configuration::PciBarConfiguration;
33 use crate::pci::pci_configuration::COMMAND_REG;
34 use crate::pci::pci_configuration::COMMAND_REG_IO_SPACE_MASK;
35 use crate::pci::pci_configuration::COMMAND_REG_MEMORY_SPACE_MASK;
36 use crate::pci::pci_configuration::NUM_BAR_REGS;
37 use crate::pci::pci_configuration::PCI_ID_REG;
38 use crate::pci::PciAddress;
39 use crate::pci::PciAddressError;
40 use crate::pci::PciBarIndex;
41 use crate::pci::PciInterruptPin;
42 use crate::virtio::ipc_memory_mapper::IpcMemoryMapper;
43 use crate::BusAccessInfo;
44 use crate::BusDevice;
45 use crate::DeviceId;
46 use crate::IrqLevelEvent;
47 use crate::Suspendable;
48 use crate::VirtioPciDevice;
49
50 #[sorted]
51 #[derive(Error, Debug)]
52 pub enum Error {
53 /// Deactivation of ACPI notifications failed
54 #[error("failed to disable ACPI notifications")]
55 AcpiNotifyDeactivationFailed,
56 /// Setup of ACPI notifications failed
57 #[error("failed to enable ACPI notifications")]
58 AcpiNotifySetupFailed,
59 /// Simulating ACPI notifications hardware triggering failed
60 #[error("failed to test ACPI notifications")]
61 AcpiNotifyTestFailed,
62 /// Added pci device's parent bus does not belong to this bus
63 #[error("pci device {0}'s parent bus does not belong to bus {1}")]
64 AddedDeviceBusNotExist(PciAddress, u8),
65 /// Invalid alignment encountered.
66 #[error("Alignment must be a power of 2")]
67 BadAlignment,
68 /// The new bus has already been added to this bus
69 #[error("Added bus {0} already existed on bus {1}")]
70 BusAlreadyExist(u8, u8),
71 /// Target bus not exists on this bus
72 #[error("pci bus {0} does not exist on bus {1}")]
73 BusNotExist(u8, u8),
74 /// Setup of the device capabilities failed.
75 #[error("failed to add capability {0}")]
76 CapabilitiesSetup(pci_configuration::Error),
77 /// Create cras client failed.
78 #[cfg(all(unix, feature = "audio", feature = "audio_cras"))]
79 #[error("failed to create CRAS Client: {0}")]
80 CreateCrasClientFailed(libcras::Error),
81 /// Device is already on this bus
82 #[error("pci device {0} has already been added to bus {1}")]
83 DeviceAlreadyExist(PciAddress, u8),
84 /// Device not exist on this bus
85 #[error("pci device {0} does not located on bus {1}")]
86 DeviceNotExist(PciAddress, u8),
87 /// Fail to clone an event.
88 #[error("failed to clone an event: {0}")]
89 EventCloneFailed(i32),
90 /// Fail to create an event.
91 #[error("failed to create an event: {0}")]
92 EventCreationFailed(i32),
93 /// Fail to signal on an event.
94 #[error("failed to signal an event: {0}")]
95 EventSignalFailed(i32),
96 /// Allocating space for an IO BAR failed.
97 #[error("failed to allocate space for an IO BAR, size={0}: {1}")]
98 IoAllocationFailed(u64, SystemAllocatorFaliure),
99 /// Registering an IO BAR failed.
100 #[error("failed to register an IO BAR, addr={0} err={1}")]
101 IoRegistrationFailed(u64, pci_configuration::Error),
102 /// Setting up MMIO mapping
103 #[error("failed to set up MMIO mapping: {0}")]
104 MmioSetup(anyhow::Error),
105 /// Out-of-space encountered
106 #[error("Out-of-space detected")]
107 OutOfSpace,
108 /// Overflow encountered
109 #[error("base={0} + size={1} overflows")]
110 Overflow(u64, u64),
111 /// The new added bus does not located on this bus
112 #[error("Added bus {0} does not located on bus {1}")]
113 ParentBusNotExist(u8, u8),
114 /// PCI Address parsing failure.
115 #[error("PCI address '{0}' could not be parsed: {1}")]
116 PciAddressParseFailure(String, PciAddressError),
117 /// PCI Address allocation failure.
118 #[error("failed to allocate PCI address")]
119 PciAllocationFailed,
120 /// PCI Bus window allocation failure.
121 #[error("failed to allocate window for PCI bus: {0}")]
122 PciBusWindowAllocationFailure(String),
123 /// Size of zero encountered
124 #[error("Size of zero detected")]
125 SizeZero,
126 }
127
128 pub type Result<T> = std::result::Result<T, Error>;
129
130 /// Pci Bar Range information
131 #[derive(Clone, Debug)]
132 pub struct BarRange {
133 /// pci bar start address
134 pub addr: u64,
135 /// pci bar size
136 pub size: u64,
137 /// pci bar is prefetchable or not, it used to set parent's bridge window
138 pub prefetchable: bool,
139 }
140
141 /// Pci Bus information
142 #[derive(Debug)]
143 pub struct PciBus {
144 // bus number
145 bus_num: u8,
146 // parent bus number
147 parent_bus_num: u8,
148 // devices located on this bus
149 child_devices: HashSet<PciAddress>,
150 // Hash map that stores all direct child buses of this bus.
151 // It maps from child bus number to its pci bus structure.
152 child_buses: HashMap<u8, Arc<Mutex<PciBus>>>,
153 // Is hotplug bus
154 hotplug_bus: bool,
155 }
156
157 impl PciBus {
158 // Creates a new pci bus
new(bus_num: u8, parent_bus_num: u8, hotplug_bus: bool) -> Self159 pub fn new(bus_num: u8, parent_bus_num: u8, hotplug_bus: bool) -> Self {
160 PciBus {
161 bus_num,
162 parent_bus_num,
163 child_devices: HashSet::new(),
164 child_buses: HashMap::new(),
165 hotplug_bus,
166 }
167 }
168
get_bus_num(&self) -> u8169 pub fn get_bus_num(&self) -> u8 {
170 self.bus_num
171 }
172
173 // Find all PCI buses from this PCI bus to a given PCI bus
path_to(&self, bus_num: u8) -> Vec<u8>174 pub fn path_to(&self, bus_num: u8) -> Vec<u8> {
175 if self.bus_num == bus_num {
176 return vec![self.bus_num];
177 }
178
179 for (_, child_bus) in self.child_buses.iter() {
180 let mut path = child_bus.lock().path_to(bus_num);
181 if !path.is_empty() {
182 path.insert(0, self.bus_num);
183 return path;
184 }
185 }
186 Vec::new()
187 }
188
189 // Add a new child device to this pci bus tree.
add_child_device(&mut self, add_device: PciAddress) -> Result<()>190 pub fn add_child_device(&mut self, add_device: PciAddress) -> Result<()> {
191 if self.bus_num == add_device.bus {
192 if !self.child_devices.insert(add_device) {
193 return Err(Error::DeviceAlreadyExist(add_device, self.bus_num));
194 }
195 return Ok(());
196 }
197
198 for child_bus in self.child_buses.values() {
199 match child_bus.lock().add_child_device(add_device) {
200 Ok(()) => return Ok(()),
201 Err(e) => {
202 if let Error::DeviceAlreadyExist(_, _) = e {
203 return Err(e);
204 }
205 }
206 }
207 }
208 Err(Error::AddedDeviceBusNotExist(add_device, self.bus_num))
209 }
210
211 // Remove one child device from this pci bus tree
remove_child_device(&mut self, device: PciAddress) -> Result<()>212 pub fn remove_child_device(&mut self, device: PciAddress) -> Result<()> {
213 if self.child_devices.remove(&device) {
214 return Ok(());
215 }
216 for child_bus in self.child_buses.values() {
217 if child_bus.lock().remove_child_device(device).is_ok() {
218 return Ok(());
219 }
220 }
221 Err(Error::DeviceNotExist(device, self.bus_num))
222 }
223
224 // Add a new child bus to this pci bus tree.
add_child_bus(&mut self, add_bus: Arc<Mutex<PciBus>>) -> Result<()>225 pub fn add_child_bus(&mut self, add_bus: Arc<Mutex<PciBus>>) -> Result<()> {
226 let add_bus_num = add_bus.lock().bus_num;
227 let add_bus_parent = add_bus.lock().parent_bus_num;
228 if self.bus_num == add_bus_parent {
229 if self.child_buses.contains_key(&add_bus_num) {
230 return Err(Error::BusAlreadyExist(self.bus_num, add_bus_num));
231 }
232 self.child_buses.insert(add_bus_num, add_bus);
233 return Ok(());
234 }
235
236 for child_bus in self.child_buses.values() {
237 match child_bus.lock().add_child_bus(add_bus.clone()) {
238 Ok(_) => return Ok(()),
239 Err(e) => {
240 if let Error::BusAlreadyExist(_, _) = e {
241 return Err(e);
242 }
243 }
244 }
245 }
246 Err(Error::ParentBusNotExist(add_bus_num, self.bus_num))
247 }
248
249 // Remove one child bus from this pci bus tree.
remove_child_bus(&mut self, bus_no: u8) -> Result<()>250 pub fn remove_child_bus(&mut self, bus_no: u8) -> Result<()> {
251 if self.child_buses.remove(&bus_no).is_some() {
252 return Ok(());
253 }
254 for (_, child_bus) in self.child_buses.iter() {
255 if child_bus.lock().remove_child_bus(bus_no).is_ok() {
256 return Ok(());
257 }
258 }
259 Err(Error::BusNotExist(bus_no, self.bus_num))
260 }
261
262 // Find all downstream devices under the given bus
find_downstream_devices(&self, bus_no: u8) -> Vec<PciAddress>263 pub fn find_downstream_devices(&self, bus_no: u8) -> Vec<PciAddress> {
264 if self.bus_num == bus_no {
265 return self.get_downstream_devices();
266 }
267 for (_, child_bus) in self.child_buses.iter() {
268 let res = child_bus.lock().find_downstream_devices(bus_no);
269 if !res.is_empty() {
270 return res;
271 }
272 }
273
274 Vec::new()
275 }
276
277 // Get all devices in this pci bus tree by level-order traversal (BFS)
get_downstream_devices(&self) -> Vec<PciAddress>278 pub fn get_downstream_devices(&self) -> Vec<PciAddress> {
279 let mut devices = Vec::new();
280 devices.extend(self.child_devices.clone());
281 for child_bus in self.child_buses.values() {
282 devices.extend(child_bus.lock().get_downstream_devices());
283 }
284 devices
285 }
286
287 // Check if given device is located in the device tree
contains(&self, device: PciAddress) -> bool288 pub fn contains(&self, device: PciAddress) -> bool {
289 if self.child_devices.contains(&device) {
290 return true;
291 }
292
293 for (_, child_bus) in self.child_buses.iter() {
294 if child_bus.lock().contains(device) {
295 return true;
296 }
297 }
298
299 false
300 }
301
302 // Returns the hotplug bus that this device is on.
get_hotplug_bus(&self, device: PciAddress) -> Option<u8>303 pub fn get_hotplug_bus(&self, device: PciAddress) -> Option<u8> {
304 if self.hotplug_bus && self.contains(device) {
305 return Some(self.bus_num);
306 }
307 for (_, child_bus) in self.child_buses.iter() {
308 let hotplug_bus = child_bus.lock().get_hotplug_bus(device);
309 if hotplug_bus.is_some() {
310 return hotplug_bus;
311 }
312 }
313 None
314 }
315 }
316
317 pub enum PreferredIrq {
318 None,
319 Any,
320 Fixed { pin: PciInterruptPin, gsi: u32 },
321 }
322
323 pub trait PciDevice: Send + Suspendable {
324 /// Returns a label suitable for debug output.
debug_label(&self) -> String325 fn debug_label(&self) -> String;
326
327 /// Preferred PCI address for this device, if any.
preferred_address(&self) -> Option<PciAddress>328 fn preferred_address(&self) -> Option<PciAddress> {
329 None
330 }
331
332 /// Allocate and return an unique bus, device and function number for this device.
333 /// May be called multiple times; on subsequent calls, the device should return the same
334 /// address it returned from the first call.
allocate_address(&mut self, resources: &mut SystemAllocator) -> Result<PciAddress>335 fn allocate_address(&mut self, resources: &mut SystemAllocator) -> Result<PciAddress>;
336
337 /// A vector of device-specific file descriptors that must be kept open
338 /// after jailing. Must be called before the process is jailed.
keep_rds(&self) -> Vec<RawDescriptor>339 fn keep_rds(&self) -> Vec<RawDescriptor>;
340
341 /// Preferred IRQ for this device.
342 /// The device may request a specific pin and IRQ number by returning a `Fixed` value.
343 /// If a device does not support INTx# interrupts at all, it should return `None`.
344 /// Otherwise, an appropriate IRQ will be allocated automatically.
345 /// The device's `assign_irq` function will be called with its assigned IRQ either way.
preferred_irq(&self) -> PreferredIrq346 fn preferred_irq(&self) -> PreferredIrq {
347 PreferredIrq::Any
348 }
349
350 /// Assign a legacy PCI IRQ to this device.
351 /// The device may write to `irq_evt` to trigger an interrupt.
352 /// When `irq_resample_evt` is signaled, the device should re-assert `irq_evt` if necessary.
assign_irq(&mut self, _irq_evt: IrqLevelEvent, _pin: PciInterruptPin, _irq_num: u32)353 fn assign_irq(&mut self, _irq_evt: IrqLevelEvent, _pin: PciInterruptPin, _irq_num: u32) {}
354
355 /// Allocates the needed IO BAR space using the `allocate` function which takes a size and
356 /// returns an address. Returns a Vec of BarRange{addr, size, prefetchable}.
allocate_io_bars(&mut self, _resources: &mut SystemAllocator) -> Result<Vec<BarRange>>357 fn allocate_io_bars(&mut self, _resources: &mut SystemAllocator) -> Result<Vec<BarRange>> {
358 Ok(Vec::new())
359 }
360
361 /// Allocates the needed device BAR space. Returns a Vec of BarRange{addr, size, prefetchable}.
362 /// Unlike MMIO BARs (see allocate_io_bars), device BARs are not expected to incur VM exits
363 /// - these BARs represent normal memory.
allocate_device_bars(&mut self, _resources: &mut SystemAllocator) -> Result<Vec<BarRange>>364 fn allocate_device_bars(&mut self, _resources: &mut SystemAllocator) -> Result<Vec<BarRange>> {
365 Ok(Vec::new())
366 }
367
368 /// Returns the configuration of a base address register, if present.
get_bar_configuration(&self, bar_num: usize) -> Option<PciBarConfiguration>369 fn get_bar_configuration(&self, bar_num: usize) -> Option<PciBarConfiguration>;
370
371 /// Register any capabilties specified by the device.
register_device_capabilities(&mut self) -> Result<()>372 fn register_device_capabilities(&mut self) -> Result<()> {
373 Ok(())
374 }
375
376 /// Gets a reference to the API client for sending VmMemoryRequest. Any devices that uses
377 /// ioevents must provide this.
get_vm_memory_client(&self) -> Option<&VmMemoryClient>378 fn get_vm_memory_client(&self) -> Option<&VmMemoryClient> {
379 None
380 }
381
382 /// Reads from a PCI configuration register.
383 /// * `reg_idx` - PCI register index (in units of 4 bytes).
read_config_register(&self, reg_idx: usize) -> u32384 fn read_config_register(&self, reg_idx: usize) -> u32;
385
386 /// Writes to a PCI configuration register.
387 /// * `reg_idx` - PCI register index (in units of 4 bytes).
388 /// * `offset` - byte offset within 4-byte register.
389 /// * `data` - The data to write.
write_config_register(&mut self, reg_idx: usize, offset: u64, data: &[u8])390 fn write_config_register(&mut self, reg_idx: usize, offset: u64, data: &[u8]);
391
392 /// Provides a memory region to back MMIO access to the configuration
393 /// space. If the device can keep the memory region up to date, then it
394 /// should return Ok(true), after which no more calls to read_config_register
395 /// will be made. If support isn't implemented, it should return Ok(false).
396 /// Otherwise, it should return an error (a failure here is not treated as
397 /// a fatal setup error).
398 ///
399 /// The device must set the header type register (0x0E) before returning
400 /// from this function, and must make no further modifications to it
401 /// after returning. This is to allow the caller to manage the multi-
402 /// function device bit without worrying about race conditions.
403 ///
404 /// * `shmem` - The shared memory to use for the configuration space.
405 /// * `base` - The base address of the memory region in shmem.
406 /// * `len` - The length of the memory region.
setup_pci_config_mapping( &mut self, _shmem: &SharedMemory, _base: usize, _len: usize, ) -> Result<bool>407 fn setup_pci_config_mapping(
408 &mut self,
409 _shmem: &SharedMemory,
410 _base: usize,
411 _len: usize,
412 ) -> Result<bool> {
413 Ok(false)
414 }
415
416 /// Reads from a virtual config register.
417 /// * `reg_idx` - virtual config register index (in units of 4 bytes).
read_virtual_config_register(&self, _reg_idx: usize) -> u32418 fn read_virtual_config_register(&self, _reg_idx: usize) -> u32 {
419 0
420 }
421
422 /// Writes to a virtual config register.
423 /// * `reg_idx` - virtual config register index (in units of 4 bytes).
424 /// * `value` - the value to be written.
write_virtual_config_register(&mut self, _reg_idx: usize, _value: u32)425 fn write_virtual_config_register(&mut self, _reg_idx: usize, _value: u32) {}
426
427 /// Reads from a BAR region mapped in to the device.
428 /// * `bar_index` - The index of the PCI BAR.
429 /// * `offset` - The starting offset in bytes inside the BAR.
430 /// * `data` - Filled with the data from `offset`.
read_bar(&mut self, bar_index: PciBarIndex, offset: u64, data: &mut [u8])431 fn read_bar(&mut self, bar_index: PciBarIndex, offset: u64, data: &mut [u8]);
432
433 /// Writes to a BAR region mapped in to the device.
434 /// * `bar_index` - The index of the PCI BAR.
435 /// * `offset` - The starting offset in bytes inside the BAR.
436 /// * `data` - The data to write.
write_bar(&mut self, bar_index: PciBarIndex, offset: u64, data: &[u8])437 fn write_bar(&mut self, bar_index: PciBarIndex, offset: u64, data: &[u8]);
438
439 /// Invoked when the device is sandboxed.
on_device_sandboxed(&mut self)440 fn on_device_sandboxed(&mut self) {}
441
442 #[cfg(target_arch = "x86_64")]
generate_acpi(&mut self, sdts: &mut Vec<SDT>)443 fn generate_acpi(&mut self, sdts: &mut Vec<SDT>) {
444 let _ = sdts;
445 }
446
447 /// Construct customized acpi method, and return the AML code and
448 /// shared memory
generate_acpi_methods(&mut self) -> (Vec<u8>, Option<(u32, MemoryMapping)>)449 fn generate_acpi_methods(&mut self) -> (Vec<u8>, Option<(u32, MemoryMapping)>) {
450 (Vec::new(), None)
451 }
452
set_gpe(&mut self, _resources: &mut SystemAllocator) -> Option<u32>453 fn set_gpe(&mut self, _resources: &mut SystemAllocator) -> Option<u32> {
454 None
455 }
456
457 /// Invoked when the device is destroyed
destroy_device(&mut self)458 fn destroy_device(&mut self) {}
459
460 /// Get the removed children devices under pci bridge
get_removed_children_devices(&self) -> Vec<PciAddress>461 fn get_removed_children_devices(&self) -> Vec<PciAddress> {
462 Vec::new()
463 }
464
465 /// Get the pci bus generated by this pci device
get_new_pci_bus(&self) -> Option<Arc<Mutex<PciBus>>>466 fn get_new_pci_bus(&self) -> Option<Arc<Mutex<PciBus>>> {
467 None
468 }
469
470 /// if device is a pci brdige, configure pci bridge window
configure_bridge_window( &mut self, _resources: &mut SystemAllocator, _bar_ranges: &[BarRange], ) -> Result<Vec<BarRange>>471 fn configure_bridge_window(
472 &mut self,
473 _resources: &mut SystemAllocator,
474 _bar_ranges: &[BarRange],
475 ) -> Result<Vec<BarRange>> {
476 Ok(Vec::new())
477 }
478
479 /// if device is a pci bridge, configure subordinate bus number
set_subordinate_bus(&mut self, _bus_no: u8)480 fn set_subordinate_bus(&mut self, _bus_no: u8) {}
481
482 /// Indicates whether the device supports IOMMU
supports_iommu(&self) -> bool483 fn supports_iommu(&self) -> bool {
484 false
485 }
486
487 /// Sets the IOMMU for the device if `supports_iommu()`
set_iommu(&mut self, _iommu: IpcMemoryMapper) -> anyhow::Result<()>488 fn set_iommu(&mut self, _iommu: IpcMemoryMapper) -> anyhow::Result<()> {
489 bail!("Iommu not supported.");
490 }
491
492 // Used for bootorder
as_virtio_pci_device(&self) -> Option<&VirtioPciDevice>493 fn as_virtio_pci_device(&self) -> Option<&VirtioPciDevice> {
494 None
495 }
496 }
497
update_ranges( old_enabled: bool, new_enabled: bool, bus_type_filter: BusType, old_ranges: &[(BusRange, BusType)], new_ranges: &[(BusRange, BusType)], ) -> (Vec<BusRange>, Vec<BusRange>)498 fn update_ranges(
499 old_enabled: bool,
500 new_enabled: bool,
501 bus_type_filter: BusType,
502 old_ranges: &[(BusRange, BusType)],
503 new_ranges: &[(BusRange, BusType)],
504 ) -> (Vec<BusRange>, Vec<BusRange>) {
505 let mut remove_ranges = Vec::new();
506 let mut add_ranges = Vec::new();
507
508 let old_ranges_filtered = old_ranges
509 .iter()
510 .filter(|(_range, bus_type)| *bus_type == bus_type_filter)
511 .map(|(range, _bus_type)| *range);
512 let new_ranges_filtered = new_ranges
513 .iter()
514 .filter(|(_range, bus_type)| *bus_type == bus_type_filter)
515 .map(|(range, _bus_type)| *range);
516
517 if old_enabled && !new_enabled {
518 // Bus type was enabled and is now disabled; remove all old ranges.
519 remove_ranges.extend(old_ranges_filtered);
520 } else if !old_enabled && new_enabled {
521 // Bus type was disabled and is now enabled; add all new ranges.
522 add_ranges.extend(new_ranges_filtered);
523 } else if old_enabled && new_enabled {
524 // Bus type was enabled before and is still enabled; diff old and new ranges.
525 for (old_range, new_range) in old_ranges_filtered.zip(new_ranges_filtered) {
526 if old_range.base != new_range.base {
527 remove_ranges.push(old_range);
528 add_ranges.push(new_range);
529 }
530 }
531 }
532
533 (remove_ranges, add_ranges)
534 }
535
536 // Debug-only helper function to convert a slice of bytes into a u32.
537 // This can be lossy - only use it for logging!
trace_data(data: &[u8], offset: u64) -> u32538 fn trace_data(data: &[u8], offset: u64) -> u32 {
539 let mut data4 = [0u8; 4];
540 for (d, s) in data4.iter_mut().skip(offset as usize).zip(data.iter()) {
541 *d = *s;
542 }
543 u32::from_le_bytes(data4)
544 }
545
546 /// Find the BAR containing an access specified by `address` and `size`.
547 ///
548 /// If found, returns the BAR index and offset in bytes within that BAR corresponding to `address`.
549 ///
550 /// The BAR must fully contain the access region; partial overlaps will return `None`. Zero-sized
551 /// accesses should not normally happen, but in case one does, this function will return `None`.
552 ///
553 /// This function only finds memory BARs, not I/O BARs. If a device with a BAR in I/O address space
554 /// is ever added, address space information will need to be added to `BusDevice::read()` and
555 /// `BusDevice::write()` and passed along to this function.
find_bar_and_offset( device: &impl PciDevice, address: u64, size: usize, ) -> Option<(PciBarIndex, u64)>556 fn find_bar_and_offset(
557 device: &impl PciDevice,
558 address: u64,
559 size: usize,
560 ) -> Option<(PciBarIndex, u64)> {
561 if size == 0 {
562 return None;
563 }
564
565 for bar_index in 0..NUM_BAR_REGS {
566 if let Some(bar_info) = device.get_bar_configuration(bar_index) {
567 if !bar_info.is_memory() {
568 continue;
569 }
570
571 // If access address >= BAR address, calculate the offset of the access in bytes from
572 // the start of the BAR. If underflow occurs, the access begins before this BAR, so it
573 // cannot be fully contained in the BAR; skip to the next BAR.
574 let Some(offset) = address.checked_sub(bar_info.address()) else {
575 continue;
576 };
577
578 // Calculate the largest valid offset given the BAR size and access size. If underflow
579 // occurs, the access size is larger than the BAR size, so the access is definitely not
580 // fully contained in the BAR; skip to the next BAR.
581 let Some(max_offset) = bar_info.size().checked_sub(size as u64) else {
582 continue;
583 };
584
585 // If offset <= max_offset, then the access is entirely contained within the BAR.
586 if offset <= max_offset {
587 return Some((bar_index, offset));
588 }
589 }
590 }
591
592 None
593 }
594
595 impl<T: PciDevice> BusDevice for T {
debug_label(&self) -> String596 fn debug_label(&self) -> String {
597 PciDevice::debug_label(self)
598 }
599
device_id(&self) -> DeviceId600 fn device_id(&self) -> DeviceId {
601 // Use the PCI ID for PCI devices, which contains the PCI vendor ID and the PCI device ID
602 let pci_id: PciId = PciDevice::read_config_register(self, PCI_ID_REG).into();
603 pci_id.into()
604 }
605
read(&mut self, info: BusAccessInfo, data: &mut [u8])606 fn read(&mut self, info: BusAccessInfo, data: &mut [u8]) {
607 if let Some((bar_index, offset)) = find_bar_and_offset(self, info.address, data.len()) {
608 self.read_bar(bar_index, offset, data);
609 } else {
610 error!("PciDevice::read({:#x}) did not match a BAR", info.address);
611 }
612 }
613
write(&mut self, info: BusAccessInfo, data: &[u8])614 fn write(&mut self, info: BusAccessInfo, data: &[u8]) {
615 if let Some((bar_index, offset)) = find_bar_and_offset(self, info.address, data.len()) {
616 self.write_bar(bar_index, offset, data);
617 } else {
618 error!("PciDevice::write({:#x}) did not match a BAR", info.address);
619 }
620 }
621
config_register_write( &mut self, reg_idx: usize, offset: u64, data: &[u8], ) -> ConfigWriteResult622 fn config_register_write(
623 &mut self,
624 reg_idx: usize,
625 offset: u64,
626 data: &[u8],
627 ) -> ConfigWriteResult {
628 if offset as usize + data.len() > 4 {
629 return Default::default();
630 }
631
632 trace!(
633 "reg_idx {:02X} data {:08X}",
634 reg_idx,
635 trace_data(data, offset)
636 );
637
638 let old_command_reg = self.read_config_register(COMMAND_REG);
639 let old_ranges =
640 if old_command_reg & (COMMAND_REG_MEMORY_SPACE_MASK | COMMAND_REG_IO_SPACE_MASK) != 0 {
641 self.get_ranges()
642 } else {
643 Vec::new()
644 };
645
646 self.write_config_register(reg_idx, offset, data);
647
648 let new_command_reg = self.read_config_register(COMMAND_REG);
649 let new_ranges =
650 if new_command_reg & (COMMAND_REG_MEMORY_SPACE_MASK | COMMAND_REG_IO_SPACE_MASK) != 0 {
651 self.get_ranges()
652 } else {
653 Vec::new()
654 };
655
656 let (mmio_remove, mmio_add) = update_ranges(
657 old_command_reg & COMMAND_REG_MEMORY_SPACE_MASK != 0,
658 new_command_reg & COMMAND_REG_MEMORY_SPACE_MASK != 0,
659 BusType::Mmio,
660 &old_ranges,
661 &new_ranges,
662 );
663
664 let (io_remove, io_add) = update_ranges(
665 old_command_reg & COMMAND_REG_IO_SPACE_MASK != 0,
666 new_command_reg & COMMAND_REG_IO_SPACE_MASK != 0,
667 BusType::Io,
668 &old_ranges,
669 &new_ranges,
670 );
671
672 ConfigWriteResult {
673 mmio_remove,
674 mmio_add,
675 io_remove,
676 io_add,
677 removed_pci_devices: self.get_removed_children_devices(),
678 }
679 }
680
config_register_read(&self, reg_idx: usize) -> u32681 fn config_register_read(&self, reg_idx: usize) -> u32 {
682 self.read_config_register(reg_idx)
683 }
684
init_pci_config_mapping(&mut self, shmem: &SharedMemory, base: usize, len: usize) -> bool685 fn init_pci_config_mapping(&mut self, shmem: &SharedMemory, base: usize, len: usize) -> bool {
686 match self.setup_pci_config_mapping(shmem, base, len) {
687 Ok(res) => res,
688 Err(err) => {
689 warn!("Failed to create PCI mapping: {:#}", err);
690 false
691 }
692 }
693 }
694
virtual_config_register_write(&mut self, reg_idx: usize, value: u32)695 fn virtual_config_register_write(&mut self, reg_idx: usize, value: u32) {
696 self.write_virtual_config_register(reg_idx, value);
697 }
698
virtual_config_register_read(&self, reg_idx: usize) -> u32699 fn virtual_config_register_read(&self, reg_idx: usize) -> u32 {
700 self.read_virtual_config_register(reg_idx)
701 }
702
on_sandboxed(&mut self)703 fn on_sandboxed(&mut self) {
704 self.on_device_sandboxed();
705 }
706
get_ranges(&self) -> Vec<(BusRange, BusType)>707 fn get_ranges(&self) -> Vec<(BusRange, BusType)> {
708 let mut ranges = Vec::new();
709 for bar_num in 0..NUM_BAR_REGS {
710 if let Some(bar) = self.get_bar_configuration(bar_num) {
711 let bus_type = if bar.is_memory() {
712 BusType::Mmio
713 } else {
714 BusType::Io
715 };
716 ranges.push((
717 BusRange {
718 base: bar.address(),
719 len: bar.size(),
720 },
721 bus_type,
722 ));
723 }
724 }
725 ranges
726 }
727
728 // Invoked when the device is destroyed
destroy_device(&mut self)729 fn destroy_device(&mut self) {
730 self.destroy_device()
731 }
732
is_bridge(&self) -> Option<u8>733 fn is_bridge(&self) -> Option<u8> {
734 self.get_new_pci_bus().map(|bus| bus.lock().get_bus_num())
735 }
736 }
737
738 impl<T: PciDevice + ?Sized> PciDevice for Box<T> {
739 /// Returns a label suitable for debug output.
debug_label(&self) -> String740 fn debug_label(&self) -> String {
741 (**self).debug_label()
742 }
preferred_address(&self) -> Option<PciAddress>743 fn preferred_address(&self) -> Option<PciAddress> {
744 (**self).preferred_address()
745 }
allocate_address(&mut self, resources: &mut SystemAllocator) -> Result<PciAddress>746 fn allocate_address(&mut self, resources: &mut SystemAllocator) -> Result<PciAddress> {
747 (**self).allocate_address(resources)
748 }
keep_rds(&self) -> Vec<RawDescriptor>749 fn keep_rds(&self) -> Vec<RawDescriptor> {
750 (**self).keep_rds()
751 }
preferred_irq(&self) -> PreferredIrq752 fn preferred_irq(&self) -> PreferredIrq {
753 (**self).preferred_irq()
754 }
assign_irq(&mut self, irq_evt: IrqLevelEvent, pin: PciInterruptPin, irq_num: u32)755 fn assign_irq(&mut self, irq_evt: IrqLevelEvent, pin: PciInterruptPin, irq_num: u32) {
756 (**self).assign_irq(irq_evt, pin, irq_num)
757 }
allocate_io_bars(&mut self, resources: &mut SystemAllocator) -> Result<Vec<BarRange>>758 fn allocate_io_bars(&mut self, resources: &mut SystemAllocator) -> Result<Vec<BarRange>> {
759 (**self).allocate_io_bars(resources)
760 }
allocate_device_bars(&mut self, resources: &mut SystemAllocator) -> Result<Vec<BarRange>>761 fn allocate_device_bars(&mut self, resources: &mut SystemAllocator) -> Result<Vec<BarRange>> {
762 (**self).allocate_device_bars(resources)
763 }
get_bar_configuration(&self, bar_num: usize) -> Option<PciBarConfiguration>764 fn get_bar_configuration(&self, bar_num: usize) -> Option<PciBarConfiguration> {
765 (**self).get_bar_configuration(bar_num)
766 }
register_device_capabilities(&mut self) -> Result<()>767 fn register_device_capabilities(&mut self) -> Result<()> {
768 (**self).register_device_capabilities()
769 }
read_virtual_config_register(&self, reg_idx: usize) -> u32770 fn read_virtual_config_register(&self, reg_idx: usize) -> u32 {
771 (**self).read_virtual_config_register(reg_idx)
772 }
write_virtual_config_register(&mut self, reg_idx: usize, value: u32)773 fn write_virtual_config_register(&mut self, reg_idx: usize, value: u32) {
774 (**self).write_virtual_config_register(reg_idx, value)
775 }
get_vm_memory_client(&self) -> Option<&VmMemoryClient>776 fn get_vm_memory_client(&self) -> Option<&VmMemoryClient> {
777 (**self).get_vm_memory_client()
778 }
read_config_register(&self, reg_idx: usize) -> u32779 fn read_config_register(&self, reg_idx: usize) -> u32 {
780 (**self).read_config_register(reg_idx)
781 }
write_config_register(&mut self, reg_idx: usize, offset: u64, data: &[u8])782 fn write_config_register(&mut self, reg_idx: usize, offset: u64, data: &[u8]) {
783 (**self).write_config_register(reg_idx, offset, data)
784 }
setup_pci_config_mapping( &mut self, shmem: &SharedMemory, base: usize, len: usize, ) -> Result<bool>785 fn setup_pci_config_mapping(
786 &mut self,
787 shmem: &SharedMemory,
788 base: usize,
789 len: usize,
790 ) -> Result<bool> {
791 (**self).setup_pci_config_mapping(shmem, base, len)
792 }
read_bar(&mut self, bar_index: PciBarIndex, offset: u64, data: &mut [u8])793 fn read_bar(&mut self, bar_index: PciBarIndex, offset: u64, data: &mut [u8]) {
794 (**self).read_bar(bar_index, offset, data)
795 }
write_bar(&mut self, bar_index: PciBarIndex, offset: u64, data: &[u8])796 fn write_bar(&mut self, bar_index: PciBarIndex, offset: u64, data: &[u8]) {
797 (**self).write_bar(bar_index, offset, data)
798 }
799 /// Invoked when the device is sandboxed.
on_device_sandboxed(&mut self)800 fn on_device_sandboxed(&mut self) {
801 (**self).on_device_sandboxed()
802 }
803
804 #[cfg(target_arch = "x86_64")]
generate_acpi(&mut self, sdts: &mut Vec<SDT>)805 fn generate_acpi(&mut self, sdts: &mut Vec<SDT>) {
806 (**self).generate_acpi(sdts)
807 }
808
generate_acpi_methods(&mut self) -> (Vec<u8>, Option<(u32, MemoryMapping)>)809 fn generate_acpi_methods(&mut self) -> (Vec<u8>, Option<(u32, MemoryMapping)>) {
810 (**self).generate_acpi_methods()
811 }
812
set_gpe(&mut self, resources: &mut SystemAllocator) -> Option<u32>813 fn set_gpe(&mut self, resources: &mut SystemAllocator) -> Option<u32> {
814 (**self).set_gpe(resources)
815 }
816
destroy_device(&mut self)817 fn destroy_device(&mut self) {
818 (**self).destroy_device();
819 }
get_new_pci_bus(&self) -> Option<Arc<Mutex<PciBus>>>820 fn get_new_pci_bus(&self) -> Option<Arc<Mutex<PciBus>>> {
821 (**self).get_new_pci_bus()
822 }
get_removed_children_devices(&self) -> Vec<PciAddress>823 fn get_removed_children_devices(&self) -> Vec<PciAddress> {
824 (**self).get_removed_children_devices()
825 }
826
configure_bridge_window( &mut self, resources: &mut SystemAllocator, bar_ranges: &[BarRange], ) -> Result<Vec<BarRange>>827 fn configure_bridge_window(
828 &mut self,
829 resources: &mut SystemAllocator,
830 bar_ranges: &[BarRange],
831 ) -> Result<Vec<BarRange>> {
832 (**self).configure_bridge_window(resources, bar_ranges)
833 }
834 }
835
836 impl<T: PciDevice + ?Sized> Suspendable for Box<T> {
snapshot(&mut self) -> anyhow::Result<AnySnapshot>837 fn snapshot(&mut self) -> anyhow::Result<AnySnapshot> {
838 (**self).snapshot()
839 }
840
restore(&mut self, data: AnySnapshot) -> anyhow::Result<()>841 fn restore(&mut self, data: AnySnapshot) -> anyhow::Result<()> {
842 (**self).restore(data)
843 }
844
sleep(&mut self) -> anyhow::Result<()>845 fn sleep(&mut self) -> anyhow::Result<()> {
846 (**self).sleep()
847 }
848
wake(&mut self) -> anyhow::Result<()>849 fn wake(&mut self) -> anyhow::Result<()> {
850 (**self).wake()
851 }
852 }
853
854 impl<T: 'static + PciDevice> BusDeviceObj for T {
as_pci_device(&self) -> Option<&dyn PciDevice>855 fn as_pci_device(&self) -> Option<&dyn PciDevice> {
856 Some(self)
857 }
as_pci_device_mut(&mut self) -> Option<&mut dyn PciDevice>858 fn as_pci_device_mut(&mut self) -> Option<&mut dyn PciDevice> {
859 Some(self)
860 }
into_pci_device(self: Box<Self>) -> Option<Box<dyn PciDevice>>861 fn into_pci_device(self: Box<Self>) -> Option<Box<dyn PciDevice>> {
862 Some(self)
863 }
864 }
865
866 #[cfg(test)]
867 mod tests {
868 use pci_configuration::PciBarPrefetchable;
869 use pci_configuration::PciBarRegionType;
870 use pci_configuration::PciClassCode;
871 use pci_configuration::PciConfiguration;
872 use pci_configuration::PciHeaderType;
873 use pci_configuration::PciMultimediaSubclass;
874
875 use super::*;
876 use crate::pci::pci_configuration::BAR0_REG;
877
878 const BAR0_SIZE: u64 = 0x1000;
879 const BAR2_SIZE: u64 = 0x20;
880 const BAR0_ADDR: u64 = 0xc0000000;
881 const BAR2_ADDR: u64 = 0x800;
882
883 struct TestDev {
884 pub config_regs: PciConfiguration,
885 }
886
887 impl PciDevice for TestDev {
debug_label(&self) -> String888 fn debug_label(&self) -> String {
889 "test".to_owned()
890 }
891
keep_rds(&self) -> Vec<RawDescriptor>892 fn keep_rds(&self) -> Vec<RawDescriptor> {
893 Vec::new()
894 }
895
read_config_register(&self, reg_idx: usize) -> u32896 fn read_config_register(&self, reg_idx: usize) -> u32 {
897 self.config_regs.read_reg(reg_idx)
898 }
899
write_config_register(&mut self, reg_idx: usize, offset: u64, data: &[u8])900 fn write_config_register(&mut self, reg_idx: usize, offset: u64, data: &[u8]) {
901 self.config_regs.write_reg(reg_idx, offset, data);
902 }
903
read_bar(&mut self, _bar_index: PciBarIndex, _offset: u64, _data: &mut [u8])904 fn read_bar(&mut self, _bar_index: PciBarIndex, _offset: u64, _data: &mut [u8]) {}
905
write_bar(&mut self, _bar_index: PciBarIndex, _offset: u64, _data: &[u8])906 fn write_bar(&mut self, _bar_index: PciBarIndex, _offset: u64, _data: &[u8]) {}
907
allocate_address(&mut self, _resources: &mut SystemAllocator) -> Result<PciAddress>908 fn allocate_address(&mut self, _resources: &mut SystemAllocator) -> Result<PciAddress> {
909 Err(Error::PciAllocationFailed)
910 }
911
get_bar_configuration(&self, bar_num: usize) -> Option<PciBarConfiguration>912 fn get_bar_configuration(&self, bar_num: usize) -> Option<PciBarConfiguration> {
913 self.config_regs.get_bar_configuration(bar_num)
914 }
915 }
916
917 impl Suspendable for TestDev {}
918
919 #[test]
config_write_result()920 fn config_write_result() {
921 let mut test_dev = TestDev {
922 config_regs: PciConfiguration::new(
923 0x1234,
924 0xABCD,
925 PciClassCode::MultimediaController,
926 &PciMultimediaSubclass::AudioDevice,
927 None,
928 PciHeaderType::Device,
929 0x5678,
930 0xEF01,
931 0,
932 ),
933 };
934
935 let _ = test_dev.config_regs.add_pci_bar(
936 PciBarConfiguration::new(
937 0,
938 BAR0_SIZE,
939 PciBarRegionType::Memory64BitRegion,
940 PciBarPrefetchable::Prefetchable,
941 )
942 .set_address(BAR0_ADDR),
943 );
944 let _ = test_dev.config_regs.add_pci_bar(
945 PciBarConfiguration::new(
946 2,
947 BAR2_SIZE,
948 PciBarRegionType::IoRegion,
949 PciBarPrefetchable::NotPrefetchable,
950 )
951 .set_address(BAR2_ADDR),
952 );
953 let bar0_range = BusRange {
954 base: BAR0_ADDR,
955 len: BAR0_SIZE,
956 };
957 let bar2_range = BusRange {
958 base: BAR2_ADDR,
959 len: BAR2_SIZE,
960 };
961
962 // Initialize command register to an all-zeroes value.
963 test_dev.config_register_write(COMMAND_REG, 0, &0u32.to_le_bytes());
964
965 // Enable IO space access (bit 0 of command register).
966 assert_eq!(
967 test_dev.config_register_write(COMMAND_REG, 0, &1u32.to_le_bytes()),
968 ConfigWriteResult {
969 mmio_remove: Vec::new(),
970 mmio_add: Vec::new(),
971 io_remove: Vec::new(),
972 io_add: vec![bar2_range],
973 removed_pci_devices: Vec::new(),
974 }
975 );
976
977 // Enable memory space access (bit 1 of command register).
978 assert_eq!(
979 test_dev.config_register_write(COMMAND_REG, 0, &3u32.to_le_bytes()),
980 ConfigWriteResult {
981 mmio_remove: Vec::new(),
982 mmio_add: vec![bar0_range],
983 io_remove: Vec::new(),
984 io_add: Vec::new(),
985 removed_pci_devices: Vec::new(),
986 }
987 );
988
989 // Rewrite the same IO + mem value again (result should be no change).
990 assert_eq!(
991 test_dev.config_register_write(COMMAND_REG, 0, &3u32.to_le_bytes()),
992 ConfigWriteResult {
993 mmio_remove: Vec::new(),
994 mmio_add: Vec::new(),
995 io_remove: Vec::new(),
996 io_add: Vec::new(),
997 removed_pci_devices: Vec::new(),
998 }
999 );
1000
1001 // Disable IO space access, leaving mem enabled.
1002 assert_eq!(
1003 test_dev.config_register_write(COMMAND_REG, 0, &2u32.to_le_bytes()),
1004 ConfigWriteResult {
1005 mmio_remove: Vec::new(),
1006 mmio_add: Vec::new(),
1007 io_remove: vec![bar2_range],
1008 io_add: Vec::new(),
1009 removed_pci_devices: Vec::new(),
1010 }
1011 );
1012
1013 // Disable mem space access.
1014 assert_eq!(
1015 test_dev.config_register_write(COMMAND_REG, 0, &0u32.to_le_bytes()),
1016 ConfigWriteResult {
1017 mmio_remove: vec![bar0_range],
1018 mmio_add: Vec::new(),
1019 io_remove: Vec::new(),
1020 io_add: Vec::new(),
1021 removed_pci_devices: Vec::new(),
1022 }
1023 );
1024
1025 assert_eq!(test_dev.get_ranges(), Vec::new());
1026
1027 // Re-enable mem and IO space.
1028 assert_eq!(
1029 test_dev.config_register_write(COMMAND_REG, 0, &3u32.to_le_bytes()),
1030 ConfigWriteResult {
1031 mmio_remove: Vec::new(),
1032 mmio_add: vec![bar0_range],
1033 io_remove: Vec::new(),
1034 io_add: vec![bar2_range],
1035 removed_pci_devices: Vec::new(),
1036 }
1037 );
1038
1039 // Change Bar0's address
1040 assert_eq!(
1041 test_dev.config_register_write(BAR0_REG, 0, &0xD0000000u32.to_le_bytes()),
1042 ConfigWriteResult {
1043 mmio_remove: vec!(bar0_range),
1044 mmio_add: vec![BusRange {
1045 base: 0xD0000000,
1046 len: BAR0_SIZE
1047 }],
1048 io_remove: Vec::new(),
1049 io_add: Vec::new(),
1050 removed_pci_devices: Vec::new(),
1051 }
1052 );
1053 }
1054
1055 #[test]
find_bar()1056 fn find_bar() {
1057 let mut dev = TestDev {
1058 config_regs: PciConfiguration::new(
1059 0x1234,
1060 0xABCD,
1061 PciClassCode::MultimediaController,
1062 &PciMultimediaSubclass::AudioDevice,
1063 None,
1064 PciHeaderType::Device,
1065 0x5678,
1066 0xEF01,
1067 0,
1068 ),
1069 };
1070
1071 let _ = dev.config_regs.add_pci_bar(
1072 PciBarConfiguration::new(
1073 0,
1074 BAR0_SIZE,
1075 PciBarRegionType::Memory64BitRegion,
1076 PciBarPrefetchable::Prefetchable,
1077 )
1078 .set_address(BAR0_ADDR),
1079 );
1080 let _ = dev.config_regs.add_pci_bar(
1081 PciBarConfiguration::new(
1082 2,
1083 BAR2_SIZE,
1084 PciBarRegionType::IoRegion,
1085 PciBarPrefetchable::NotPrefetchable,
1086 )
1087 .set_address(BAR2_ADDR),
1088 );
1089
1090 // No matching BAR
1091 assert_eq!(find_bar_and_offset(&dev, 0, 4), None);
1092 assert_eq!(find_bar_and_offset(&dev, 0xbfffffff, 4), None);
1093 assert_eq!(find_bar_and_offset(&dev, 0xc0000000, 0), None);
1094 assert_eq!(find_bar_and_offset(&dev, 0xc0000000, 0x1001), None);
1095 assert_eq!(find_bar_and_offset(&dev, 0xffff_ffff_ffff_ffff, 1), None);
1096 assert_eq!(find_bar_and_offset(&dev, 0xffff_ffff_ffff_ffff, 4), None);
1097
1098 // BAR0 (64-bit memory BAR at 0xc0000000, size 0x1000)
1099 assert_eq!(find_bar_and_offset(&dev, 0xc0000000, 4), Some((0, 0)));
1100 assert_eq!(find_bar_and_offset(&dev, 0xc0000001, 4), Some((0, 1)));
1101 assert_eq!(find_bar_and_offset(&dev, 0xc0000ffc, 4), Some((0, 0xffc)));
1102 assert_eq!(find_bar_and_offset(&dev, 0xc0000ffd, 4), None);
1103 assert_eq!(find_bar_and_offset(&dev, 0xc0000ffe, 4), None);
1104 assert_eq!(find_bar_and_offset(&dev, 0xc0000fff, 4), None);
1105 assert_eq!(find_bar_and_offset(&dev, 0xc0000fff, 1), Some((0, 0xfff)));
1106 assert_eq!(find_bar_and_offset(&dev, 0xc0001000, 1), None);
1107 assert_eq!(find_bar_and_offset(&dev, 0xc0000000, 0xfff), Some((0, 0)));
1108 assert_eq!(find_bar_and_offset(&dev, 0xc0000000, 0x1000), Some((0, 0)));
1109
1110 // BAR2 (I/O BAR)
1111 assert_eq!(find_bar_and_offset(&dev, 0x800, 1), None);
1112 }
1113 }
1114