xref: /aosp_15_r20/external/crosvm/devices/src/pci/pci_device.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
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