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