devices/pci/
pci_device.rs

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
5use std::collections::HashMap;
6use std::collections::HashSet;
7use std::sync::Arc;
8
9#[cfg(target_arch = "x86_64")]
10use acpi_tables::sdt::SDT;
11use anyhow::bail;
12use base::error;
13use base::trace;
14use base::warn;
15use base::MemoryMapping;
16use base::RawDescriptor;
17use base::SharedMemory;
18use remain::sorted;
19use resources::Error as SystemAllocatorFaliure;
20use resources::SystemAllocator;
21use snapshot::AnySnapshot;
22use sync::Mutex;
23use thiserror::Error;
24use vm_control::api::VmMemoryClient;
25
26use super::PciId;
27use crate::bus::BusDeviceObj;
28use crate::bus::BusRange;
29use crate::bus::BusType;
30use crate::bus::ConfigWriteResult;
31use crate::pci::pci_configuration;
32use crate::pci::pci_configuration::PciBarConfiguration;
33use crate::pci::pci_configuration::COMMAND_REG;
34use crate::pci::pci_configuration::COMMAND_REG_IO_SPACE_MASK;
35use crate::pci::pci_configuration::COMMAND_REG_MEMORY_SPACE_MASK;
36use crate::pci::pci_configuration::NUM_BAR_REGS;
37use crate::pci::pci_configuration::PCI_ID_REG;
38use crate::pci::PciAddress;
39use crate::pci::PciAddressError;
40use crate::pci::PciBarIndex;
41use crate::pci::PciInterruptPin;
42use crate::virtio::ipc_memory_mapper::IpcMemoryMapper;
43use crate::BusAccessInfo;
44use crate::BusDevice;
45use crate::DeviceId;
46use crate::IrqLevelEvent;
47use crate::Suspendable;
48use crate::VirtioPciDevice;
49
50#[sorted]
51#[derive(Error, Debug)]
52pub 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
128pub type Result<T> = std::result::Result<T, Error>;
129
130/// Pci Bar Range information
131#[derive(Clone, Debug)]
132pub 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)]
143pub 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
157impl PciBus {
158    // Creates a new pci bus
159    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
169    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
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.
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
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.
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.
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
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)
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
288    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.
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
317pub enum PreferredIrq {
318    None,
319    Any,
320    Fixed { pin: PciInterruptPin, gsi: u32 },
321}
322
323pub trait PciDevice: Send + Suspendable {
324    /// Returns a label suitable for debug output.
325    fn debug_label(&self) -> String;
326
327    /// Preferred PCI address for this device, if any.
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.
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.
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.
346    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.
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}.
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.
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.
369    fn get_bar_configuration(&self, bar_num: usize) -> Option<PciBarConfiguration>;
370
371    /// Register any capabilties specified by the device.
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.
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).
384    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.
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.
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).
418    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.
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`.
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.
437    fn write_bar(&mut self, bar_index: PciBarIndex, offset: u64, data: &[u8]);
438
439    /// Invoked when the device is sandboxed.
440    fn on_device_sandboxed(&mut self) {}
441
442    #[cfg(target_arch = "x86_64")]
443    fn generate_acpi(&mut self, sdts: &mut Vec<SDT>) -> anyhow::Result<()> {
444        let _ = sdts;
445        Ok(())
446    }
447
448    /// Construct customized acpi method, and return the AML code and
449    /// shared memory
450    fn generate_acpi_methods(&mut self) -> (Vec<u8>, Option<(u32, MemoryMapping)>) {
451        (Vec::new(), None)
452    }
453
454    fn set_gpe(&mut self, _resources: &mut SystemAllocator) -> Option<u32> {
455        None
456    }
457
458    /// Invoked when the device is destroyed
459    fn destroy_device(&mut self) {}
460
461    /// Get the removed children devices under pci bridge
462    fn get_removed_children_devices(&self) -> Vec<PciAddress> {
463        Vec::new()
464    }
465
466    /// Get the pci bus generated by this pci device
467    fn get_new_pci_bus(&self) -> Option<Arc<Mutex<PciBus>>> {
468        None
469    }
470
471    /// if device is a pci brdige, configure pci bridge window
472    fn configure_bridge_window(
473        &mut self,
474        _resources: &mut SystemAllocator,
475        _bar_ranges: &[BarRange],
476    ) -> Result<Vec<BarRange>> {
477        Ok(Vec::new())
478    }
479
480    /// if device is a pci bridge, configure subordinate bus number
481    fn set_subordinate_bus(&mut self, _bus_no: u8) {}
482
483    /// Indicates whether the device supports IOMMU
484    fn supports_iommu(&self) -> bool {
485        false
486    }
487
488    /// Sets the IOMMU for the device if `supports_iommu()`
489    fn set_iommu(&mut self, _iommu: IpcMemoryMapper) -> anyhow::Result<()> {
490        bail!("Iommu not supported.");
491    }
492
493    // Used for bootorder
494    fn as_virtio_pci_device(&self) -> Option<&VirtioPciDevice> {
495        None
496    }
497}
498
499fn update_ranges(
500    old_enabled: bool,
501    new_enabled: bool,
502    bus_type_filter: BusType,
503    old_ranges: &[(BusRange, BusType)],
504    new_ranges: &[(BusRange, BusType)],
505) -> (Vec<BusRange>, Vec<BusRange>) {
506    let mut remove_ranges = Vec::new();
507    let mut add_ranges = Vec::new();
508
509    let old_ranges_filtered = old_ranges
510        .iter()
511        .filter(|(_range, bus_type)| *bus_type == bus_type_filter)
512        .map(|(range, _bus_type)| *range);
513    let new_ranges_filtered = new_ranges
514        .iter()
515        .filter(|(_range, bus_type)| *bus_type == bus_type_filter)
516        .map(|(range, _bus_type)| *range);
517
518    if old_enabled && !new_enabled {
519        // Bus type was enabled and is now disabled; remove all old ranges.
520        remove_ranges.extend(old_ranges_filtered);
521    } else if !old_enabled && new_enabled {
522        // Bus type was disabled and is now enabled; add all new ranges.
523        add_ranges.extend(new_ranges_filtered);
524    } else if old_enabled && new_enabled {
525        // Bus type was enabled before and is still enabled; diff old and new ranges.
526        for (old_range, new_range) in old_ranges_filtered.zip(new_ranges_filtered) {
527            if old_range.base != new_range.base {
528                remove_ranges.push(old_range);
529                add_ranges.push(new_range);
530            }
531        }
532    }
533
534    (remove_ranges, add_ranges)
535}
536
537// Debug-only helper function to convert a slice of bytes into a u32.
538// This can be lossy - only use it for logging!
539fn trace_data(data: &[u8], offset: u64) -> u32 {
540    let mut data4 = [0u8; 4];
541    for (d, s) in data4.iter_mut().skip(offset as usize).zip(data.iter()) {
542        *d = *s;
543    }
544    u32::from_le_bytes(data4)
545}
546
547/// Find the BAR containing an access specified by `address` and `size`.
548///
549/// If found, returns the BAR index and offset in bytes within that BAR corresponding to `address`.
550///
551/// The BAR must fully contain the access region; partial overlaps will return `None`. Zero-sized
552/// accesses should not normally happen, but in case one does, this function will return `None`.
553///
554/// This function only finds memory BARs, not I/O BARs. If a device with a BAR in I/O address space
555/// is ever added, address space information will need to be added to `BusDevice::read()` and
556/// `BusDevice::write()` and passed along to this function.
557fn find_bar_and_offset(
558    device: &impl PciDevice,
559    address: u64,
560    size: usize,
561) -> Option<(PciBarIndex, u64)> {
562    if size == 0 {
563        return None;
564    }
565
566    for bar_index in 0..NUM_BAR_REGS {
567        if let Some(bar_info) = device.get_bar_configuration(bar_index) {
568            if !bar_info.is_memory() {
569                continue;
570            }
571
572            // If access address >= BAR address, calculate the offset of the access in bytes from
573            // the start of the BAR. If underflow occurs, the access begins before this BAR, so it
574            // cannot be fully contained in the BAR; skip to the next BAR.
575            let Some(offset) = address.checked_sub(bar_info.address()) else {
576                continue;
577            };
578
579            // Calculate the largest valid offset given the BAR size and access size. If underflow
580            // occurs, the access size is larger than the BAR size, so the access is definitely not
581            // fully contained in the BAR; skip to the next BAR.
582            let Some(max_offset) = bar_info.size().checked_sub(size as u64) else {
583                continue;
584            };
585
586            // If offset <= max_offset, then the access is entirely contained within the BAR.
587            if offset <= max_offset {
588                return Some((bar_index, offset));
589            }
590        }
591    }
592
593    None
594}
595
596impl<T: PciDevice> BusDevice for T {
597    fn debug_label(&self) -> String {
598        PciDevice::debug_label(self)
599    }
600
601    fn device_id(&self) -> DeviceId {
602        // Use the PCI ID for PCI devices, which contains the PCI vendor ID and the PCI device ID
603        let pci_id: PciId = PciDevice::read_config_register(self, PCI_ID_REG).into();
604        pci_id.into()
605    }
606
607    fn read(&mut self, info: BusAccessInfo, data: &mut [u8]) {
608        if let Some((bar_index, offset)) = find_bar_and_offset(self, info.address, data.len()) {
609            self.read_bar(bar_index, offset, data);
610        } else {
611            error!("PciDevice::read({:#x}) did not match a BAR", info.address);
612        }
613    }
614
615    fn write(&mut self, info: BusAccessInfo, data: &[u8]) {
616        if let Some((bar_index, offset)) = find_bar_and_offset(self, info.address, data.len()) {
617            self.write_bar(bar_index, offset, data);
618        } else {
619            error!("PciDevice::write({:#x}) did not match a BAR", info.address);
620        }
621    }
622
623    fn config_register_write(
624        &mut self,
625        reg_idx: usize,
626        offset: u64,
627        data: &[u8],
628    ) -> ConfigWriteResult {
629        if offset as usize + data.len() > 4 {
630            return Default::default();
631        }
632
633        trace!(
634            "reg_idx {:02X} data {:08X}",
635            reg_idx,
636            trace_data(data, offset)
637        );
638
639        let old_command_reg = self.read_config_register(COMMAND_REG);
640        let old_ranges =
641            if old_command_reg & (COMMAND_REG_MEMORY_SPACE_MASK | COMMAND_REG_IO_SPACE_MASK) != 0 {
642                self.get_ranges()
643            } else {
644                Vec::new()
645            };
646
647        self.write_config_register(reg_idx, offset, data);
648
649        let new_command_reg = self.read_config_register(COMMAND_REG);
650        let new_ranges =
651            if new_command_reg & (COMMAND_REG_MEMORY_SPACE_MASK | COMMAND_REG_IO_SPACE_MASK) != 0 {
652                self.get_ranges()
653            } else {
654                Vec::new()
655            };
656
657        let (mmio_remove, mmio_add) = update_ranges(
658            old_command_reg & COMMAND_REG_MEMORY_SPACE_MASK != 0,
659            new_command_reg & COMMAND_REG_MEMORY_SPACE_MASK != 0,
660            BusType::Mmio,
661            &old_ranges,
662            &new_ranges,
663        );
664
665        let (io_remove, io_add) = update_ranges(
666            old_command_reg & COMMAND_REG_IO_SPACE_MASK != 0,
667            new_command_reg & COMMAND_REG_IO_SPACE_MASK != 0,
668            BusType::Io,
669            &old_ranges,
670            &new_ranges,
671        );
672
673        ConfigWriteResult {
674            mmio_remove,
675            mmio_add,
676            io_remove,
677            io_add,
678            removed_pci_devices: self.get_removed_children_devices(),
679        }
680    }
681
682    fn config_register_read(&self, reg_idx: usize) -> u32 {
683        self.read_config_register(reg_idx)
684    }
685
686    fn init_pci_config_mapping(&mut self, shmem: &SharedMemory, base: usize, len: usize) -> bool {
687        match self.setup_pci_config_mapping(shmem, base, len) {
688            Ok(res) => res,
689            Err(err) => {
690                warn!("Failed to create PCI mapping: {:#}", err);
691                false
692            }
693        }
694    }
695
696    fn virtual_config_register_write(&mut self, reg_idx: usize, value: u32) {
697        self.write_virtual_config_register(reg_idx, value);
698    }
699
700    fn virtual_config_register_read(&self, reg_idx: usize) -> u32 {
701        self.read_virtual_config_register(reg_idx)
702    }
703
704    fn on_sandboxed(&mut self) {
705        self.on_device_sandboxed();
706    }
707
708    fn get_ranges(&self) -> Vec<(BusRange, BusType)> {
709        let mut ranges = Vec::new();
710        for bar_num in 0..NUM_BAR_REGS {
711            if let Some(bar) = self.get_bar_configuration(bar_num) {
712                let bus_type = if bar.is_memory() {
713                    BusType::Mmio
714                } else {
715                    BusType::Io
716                };
717                ranges.push((
718                    BusRange {
719                        base: bar.address(),
720                        len: bar.size(),
721                    },
722                    bus_type,
723                ));
724            }
725        }
726        ranges
727    }
728
729    // Invoked when the device is destroyed
730    fn destroy_device(&mut self) {
731        self.destroy_device()
732    }
733
734    fn is_bridge(&self) -> Option<u8> {
735        self.get_new_pci_bus().map(|bus| bus.lock().get_bus_num())
736    }
737}
738
739impl<T: PciDevice + ?Sized> PciDevice for Box<T> {
740    /// Returns a label suitable for debug output.
741    fn debug_label(&self) -> String {
742        (**self).debug_label()
743    }
744    fn preferred_address(&self) -> Option<PciAddress> {
745        (**self).preferred_address()
746    }
747    fn allocate_address(&mut self, resources: &mut SystemAllocator) -> Result<PciAddress> {
748        (**self).allocate_address(resources)
749    }
750    fn keep_rds(&self) -> Vec<RawDescriptor> {
751        (**self).keep_rds()
752    }
753    fn preferred_irq(&self) -> PreferredIrq {
754        (**self).preferred_irq()
755    }
756    fn assign_irq(&mut self, irq_evt: IrqLevelEvent, pin: PciInterruptPin, irq_num: u32) {
757        (**self).assign_irq(irq_evt, pin, irq_num)
758    }
759    fn allocate_io_bars(&mut self, resources: &mut SystemAllocator) -> Result<Vec<BarRange>> {
760        (**self).allocate_io_bars(resources)
761    }
762    fn allocate_device_bars(&mut self, resources: &mut SystemAllocator) -> Result<Vec<BarRange>> {
763        (**self).allocate_device_bars(resources)
764    }
765    fn get_bar_configuration(&self, bar_num: usize) -> Option<PciBarConfiguration> {
766        (**self).get_bar_configuration(bar_num)
767    }
768    fn register_device_capabilities(&mut self) -> Result<()> {
769        (**self).register_device_capabilities()
770    }
771    fn read_virtual_config_register(&self, reg_idx: usize) -> u32 {
772        (**self).read_virtual_config_register(reg_idx)
773    }
774    fn write_virtual_config_register(&mut self, reg_idx: usize, value: u32) {
775        (**self).write_virtual_config_register(reg_idx, value)
776    }
777    fn get_vm_memory_client(&self) -> Option<&VmMemoryClient> {
778        (**self).get_vm_memory_client()
779    }
780    fn read_config_register(&self, reg_idx: usize) -> u32 {
781        (**self).read_config_register(reg_idx)
782    }
783    fn write_config_register(&mut self, reg_idx: usize, offset: u64, data: &[u8]) {
784        (**self).write_config_register(reg_idx, offset, data)
785    }
786    fn setup_pci_config_mapping(
787        &mut self,
788        shmem: &SharedMemory,
789        base: usize,
790        len: usize,
791    ) -> Result<bool> {
792        (**self).setup_pci_config_mapping(shmem, base, len)
793    }
794    fn read_bar(&mut self, bar_index: PciBarIndex, offset: u64, data: &mut [u8]) {
795        (**self).read_bar(bar_index, offset, data)
796    }
797    fn write_bar(&mut self, bar_index: PciBarIndex, offset: u64, data: &[u8]) {
798        (**self).write_bar(bar_index, offset, data)
799    }
800    /// Invoked when the device is sandboxed.
801    fn on_device_sandboxed(&mut self) {
802        (**self).on_device_sandboxed()
803    }
804
805    #[cfg(target_arch = "x86_64")]
806    fn generate_acpi(&mut self, sdts: &mut Vec<SDT>) -> anyhow::Result<()> {
807        (**self).generate_acpi(sdts)
808    }
809
810    fn generate_acpi_methods(&mut self) -> (Vec<u8>, Option<(u32, MemoryMapping)>) {
811        (**self).generate_acpi_methods()
812    }
813
814    fn set_gpe(&mut self, resources: &mut SystemAllocator) -> Option<u32> {
815        (**self).set_gpe(resources)
816    }
817
818    fn destroy_device(&mut self) {
819        (**self).destroy_device();
820    }
821    fn get_new_pci_bus(&self) -> Option<Arc<Mutex<PciBus>>> {
822        (**self).get_new_pci_bus()
823    }
824    fn get_removed_children_devices(&self) -> Vec<PciAddress> {
825        (**self).get_removed_children_devices()
826    }
827
828    fn configure_bridge_window(
829        &mut self,
830        resources: &mut SystemAllocator,
831        bar_ranges: &[BarRange],
832    ) -> Result<Vec<BarRange>> {
833        (**self).configure_bridge_window(resources, bar_ranges)
834    }
835}
836
837impl<T: PciDevice + ?Sized> Suspendable for Box<T> {
838    fn snapshot(&mut self) -> anyhow::Result<AnySnapshot> {
839        (**self).snapshot()
840    }
841
842    fn restore(&mut self, data: AnySnapshot) -> anyhow::Result<()> {
843        (**self).restore(data)
844    }
845
846    fn sleep(&mut self) -> anyhow::Result<()> {
847        (**self).sleep()
848    }
849
850    fn wake(&mut self) -> anyhow::Result<()> {
851        (**self).wake()
852    }
853}
854
855impl<T: 'static + PciDevice> BusDeviceObj for T {
856    fn as_pci_device(&self) -> Option<&dyn PciDevice> {
857        Some(self)
858    }
859    fn as_pci_device_mut(&mut self) -> Option<&mut dyn PciDevice> {
860        Some(self)
861    }
862    fn into_pci_device(self: Box<Self>) -> Option<Box<dyn PciDevice>> {
863        Some(self)
864    }
865}
866
867#[cfg(test)]
868mod tests {
869    use pci_configuration::PciBarPrefetchable;
870    use pci_configuration::PciBarRegionType;
871    use pci_configuration::PciClassCode;
872    use pci_configuration::PciConfiguration;
873    use pci_configuration::PciHeaderType;
874    use pci_configuration::PciMultimediaSubclass;
875
876    use super::*;
877    use crate::pci::pci_configuration::BAR0_REG;
878
879    const BAR0_SIZE: u64 = 0x1000;
880    const BAR2_SIZE: u64 = 0x20;
881    const BAR0_ADDR: u64 = 0xc0000000;
882    const BAR2_ADDR: u64 = 0x800;
883
884    struct TestDev {
885        pub config_regs: PciConfiguration,
886    }
887
888    impl PciDevice for TestDev {
889        fn debug_label(&self) -> String {
890            "test".to_owned()
891        }
892
893        fn keep_rds(&self) -> Vec<RawDescriptor> {
894            Vec::new()
895        }
896
897        fn read_config_register(&self, reg_idx: usize) -> u32 {
898            self.config_regs.read_reg(reg_idx)
899        }
900
901        fn write_config_register(&mut self, reg_idx: usize, offset: u64, data: &[u8]) {
902            self.config_regs.write_reg(reg_idx, offset, data);
903        }
904
905        fn read_bar(&mut self, _bar_index: PciBarIndex, _offset: u64, _data: &mut [u8]) {}
906
907        fn write_bar(&mut self, _bar_index: PciBarIndex, _offset: u64, _data: &[u8]) {}
908
909        fn allocate_address(&mut self, _resources: &mut SystemAllocator) -> Result<PciAddress> {
910            Err(Error::PciAllocationFailed)
911        }
912
913        fn get_bar_configuration(&self, bar_num: usize) -> Option<PciBarConfiguration> {
914            self.config_regs.get_bar_configuration(bar_num)
915        }
916    }
917
918    impl Suspendable for TestDev {}
919
920    #[test]
921    fn config_write_result() {
922        let mut test_dev = TestDev {
923            config_regs: PciConfiguration::new(
924                0x1234,
925                0xABCD,
926                PciClassCode::MultimediaController,
927                &PciMultimediaSubclass::AudioDevice,
928                None,
929                PciHeaderType::Device,
930                0x5678,
931                0xEF01,
932                0,
933            ),
934        };
935
936        let _ = test_dev.config_regs.add_pci_bar(
937            PciBarConfiguration::new(
938                0,
939                BAR0_SIZE,
940                PciBarRegionType::Memory64BitRegion,
941                PciBarPrefetchable::Prefetchable,
942            )
943            .set_address(BAR0_ADDR),
944        );
945        let _ = test_dev.config_regs.add_pci_bar(
946            PciBarConfiguration::new(
947                2,
948                BAR2_SIZE,
949                PciBarRegionType::IoRegion,
950                PciBarPrefetchable::NotPrefetchable,
951            )
952            .set_address(BAR2_ADDR),
953        );
954        let bar0_range = BusRange {
955            base: BAR0_ADDR,
956            len: BAR0_SIZE,
957        };
958        let bar2_range = BusRange {
959            base: BAR2_ADDR,
960            len: BAR2_SIZE,
961        };
962
963        // Initialize command register to an all-zeroes value.
964        test_dev.config_register_write(COMMAND_REG, 0, &0u32.to_le_bytes());
965
966        // Enable IO space access (bit 0 of command register).
967        assert_eq!(
968            test_dev.config_register_write(COMMAND_REG, 0, &1u32.to_le_bytes()),
969            ConfigWriteResult {
970                mmio_remove: Vec::new(),
971                mmio_add: Vec::new(),
972                io_remove: Vec::new(),
973                io_add: vec![bar2_range],
974                removed_pci_devices: Vec::new(),
975            }
976        );
977
978        // Enable memory space access (bit 1 of command register).
979        assert_eq!(
980            test_dev.config_register_write(COMMAND_REG, 0, &3u32.to_le_bytes()),
981            ConfigWriteResult {
982                mmio_remove: Vec::new(),
983                mmio_add: vec![bar0_range],
984                io_remove: Vec::new(),
985                io_add: Vec::new(),
986                removed_pci_devices: Vec::new(),
987            }
988        );
989
990        // Rewrite the same IO + mem value again (result should be no change).
991        assert_eq!(
992            test_dev.config_register_write(COMMAND_REG, 0, &3u32.to_le_bytes()),
993            ConfigWriteResult {
994                mmio_remove: Vec::new(),
995                mmio_add: Vec::new(),
996                io_remove: Vec::new(),
997                io_add: Vec::new(),
998                removed_pci_devices: Vec::new(),
999            }
1000        );
1001
1002        // Disable IO space access, leaving mem enabled.
1003        assert_eq!(
1004            test_dev.config_register_write(COMMAND_REG, 0, &2u32.to_le_bytes()),
1005            ConfigWriteResult {
1006                mmio_remove: Vec::new(),
1007                mmio_add: Vec::new(),
1008                io_remove: vec![bar2_range],
1009                io_add: Vec::new(),
1010                removed_pci_devices: Vec::new(),
1011            }
1012        );
1013
1014        // Disable mem space access.
1015        assert_eq!(
1016            test_dev.config_register_write(COMMAND_REG, 0, &0u32.to_le_bytes()),
1017            ConfigWriteResult {
1018                mmio_remove: vec![bar0_range],
1019                mmio_add: Vec::new(),
1020                io_remove: Vec::new(),
1021                io_add: Vec::new(),
1022                removed_pci_devices: Vec::new(),
1023            }
1024        );
1025
1026        assert_eq!(test_dev.get_ranges(), Vec::new());
1027
1028        // Re-enable mem and IO space.
1029        assert_eq!(
1030            test_dev.config_register_write(COMMAND_REG, 0, &3u32.to_le_bytes()),
1031            ConfigWriteResult {
1032                mmio_remove: Vec::new(),
1033                mmio_add: vec![bar0_range],
1034                io_remove: Vec::new(),
1035                io_add: vec![bar2_range],
1036                removed_pci_devices: Vec::new(),
1037            }
1038        );
1039
1040        // Change Bar0's address
1041        assert_eq!(
1042            test_dev.config_register_write(BAR0_REG, 0, &0xD0000000u32.to_le_bytes()),
1043            ConfigWriteResult {
1044                mmio_remove: vec!(bar0_range),
1045                mmio_add: vec![BusRange {
1046                    base: 0xD0000000,
1047                    len: BAR0_SIZE
1048                }],
1049                io_remove: Vec::new(),
1050                io_add: Vec::new(),
1051                removed_pci_devices: Vec::new(),
1052            }
1053        );
1054    }
1055
1056    #[test]
1057    fn find_bar() {
1058        let mut dev = TestDev {
1059            config_regs: PciConfiguration::new(
1060                0x1234,
1061                0xABCD,
1062                PciClassCode::MultimediaController,
1063                &PciMultimediaSubclass::AudioDevice,
1064                None,
1065                PciHeaderType::Device,
1066                0x5678,
1067                0xEF01,
1068                0,
1069            ),
1070        };
1071
1072        let _ = dev.config_regs.add_pci_bar(
1073            PciBarConfiguration::new(
1074                0,
1075                BAR0_SIZE,
1076                PciBarRegionType::Memory64BitRegion,
1077                PciBarPrefetchable::Prefetchable,
1078            )
1079            .set_address(BAR0_ADDR),
1080        );
1081        let _ = dev.config_regs.add_pci_bar(
1082            PciBarConfiguration::new(
1083                2,
1084                BAR2_SIZE,
1085                PciBarRegionType::IoRegion,
1086                PciBarPrefetchable::NotPrefetchable,
1087            )
1088            .set_address(BAR2_ADDR),
1089        );
1090
1091        // No matching BAR
1092        assert_eq!(find_bar_and_offset(&dev, 0, 4), None);
1093        assert_eq!(find_bar_and_offset(&dev, 0xbfffffff, 4), None);
1094        assert_eq!(find_bar_and_offset(&dev, 0xc0000000, 0), None);
1095        assert_eq!(find_bar_and_offset(&dev, 0xc0000000, 0x1001), None);
1096        assert_eq!(find_bar_and_offset(&dev, 0xffff_ffff_ffff_ffff, 1), None);
1097        assert_eq!(find_bar_and_offset(&dev, 0xffff_ffff_ffff_ffff, 4), None);
1098
1099        // BAR0 (64-bit memory BAR at 0xc0000000, size 0x1000)
1100        assert_eq!(find_bar_and_offset(&dev, 0xc0000000, 4), Some((0, 0)));
1101        assert_eq!(find_bar_and_offset(&dev, 0xc0000001, 4), Some((0, 1)));
1102        assert_eq!(find_bar_and_offset(&dev, 0xc0000ffc, 4), Some((0, 0xffc)));
1103        assert_eq!(find_bar_and_offset(&dev, 0xc0000ffd, 4), None);
1104        assert_eq!(find_bar_and_offset(&dev, 0xc0000ffe, 4), None);
1105        assert_eq!(find_bar_and_offset(&dev, 0xc0000fff, 4), None);
1106        assert_eq!(find_bar_and_offset(&dev, 0xc0000fff, 1), Some((0, 0xfff)));
1107        assert_eq!(find_bar_and_offset(&dev, 0xc0001000, 1), None);
1108        assert_eq!(find_bar_and_offset(&dev, 0xc0000000, 0xfff), Some((0, 0)));
1109        assert_eq!(find_bar_and_offset(&dev, 0xc0000000, 0x1000), Some((0, 0)));
1110
1111        // BAR2 (I/O BAR)
1112        assert_eq!(find_bar_and_offset(&dev, 0x800, 1), None);
1113    }
1114}