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