vmm: Store VFIO device's name and its PCI b/d/f

Add a new list storing the device names across the entire codebase. VFIO
devices are added to the list whenever a new one is created. By default,
each VFIO device is given a name "vfioX" where X is the first available
integer.

Along with this new list of names, another list is created, grouping PCI
device's name with its associated b/d/f. This will be useful to keep
track of the created devices so that we can implement unplug
functionality.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
This commit is contained in:
Sebastien Boeuf
2020-03-06 11:34:24 +01:00
committed by Rob Bradford
parent 13a61c4784
commit 0f99d3f7cc
+49 -3
View File
@@ -36,6 +36,8 @@ use qcow::{self, ImageType, QcowFile};
use std::collections::HashMap; use std::collections::HashMap;
use std::fs::{File, OpenOptions}; use std::fs::{File, OpenOptions};
use std::io::{self, sink, stdout}; use std::io::{self, sink, stdout};
#[cfg(feature = "pci_support")]
use std::num::Wrapping;
use std::os::unix::fs::OpenOptionsExt; use std::os::unix::fs::OpenOptionsExt;
use std::path::PathBuf; use std::path::PathBuf;
use std::result; use std::result;
@@ -64,6 +66,9 @@ use vmm_sys_util::eventfd::EventFd;
#[cfg(feature = "mmio_support")] #[cfg(feature = "mmio_support")]
const MMIO_LEN: u64 = 0x1000; const MMIO_LEN: u64 = 0x1000;
#[cfg(feature = "pci_support")]
const VFIO_DEVICE_NAME_PREFIX: &str = "vfio";
/// Errors associated with device manager /// Errors associated with device manager
#[derive(Debug)] #[derive(Debug)]
pub enum DeviceManagerError { pub enum DeviceManagerError {
@@ -212,6 +217,10 @@ pub enum DeviceManagerError {
/// Missing PCI bus. /// Missing PCI bus.
NoPciBus, NoPciBus,
/// Could not find an available VFIO device name.
#[cfg(feature = "pci_support")]
NoAvailableVfioDeviceName,
} }
pub type DeviceManagerResult<T> = result::Result<T, DeviceManagerError>; pub type DeviceManagerResult<T> = result::Result<T, DeviceManagerError>;
@@ -462,6 +471,14 @@ pub struct DeviceManager {
// Bitmap of PCI devices to hotunplug. // Bitmap of PCI devices to hotunplug.
#[cfg(feature = "pci_support")] #[cfg(feature = "pci_support")]
pci_devices_down: u32, pci_devices_down: u32,
// Hashmap of device's name to their corresponding PCI b/d/f.
#[cfg(feature = "pci_support")]
pci_id_list: HashMap<String, u32>,
// Counter to keep track of the consumed device IDs.
#[cfg(feature = "pci_support")]
device_id_cnt: Wrapping<usize>,
} }
impl DeviceManager { impl DeviceManager {
@@ -561,6 +578,10 @@ impl DeviceManager {
pci_devices_up: 0, pci_devices_up: 0,
#[cfg(feature = "pci_support")] #[cfg(feature = "pci_support")]
pci_devices_down: 0, pci_devices_down: 0,
#[cfg(feature = "pci_support")]
pci_id_list: HashMap::new(),
#[cfg(feature = "pci_support")]
device_id_cnt: Wrapping(0),
}; };
device_manager device_manager
@@ -1393,6 +1414,28 @@ impl DeviceManager {
.map_err(DeviceManagerError::CreateKvmDevice) .map_err(DeviceManagerError::CreateKvmDevice)
} }
#[cfg(feature = "pci_support")]
fn next_device_name(&mut self, prefix: &str) -> DeviceManagerResult<String> {
let start_id = self.device_id_cnt;
loop {
// Generate the temporary name.
let name = format!("{}{}", prefix, self.device_id_cnt);
// Increment the counter.
self.device_id_cnt += Wrapping(1);
// Check if the name is already in use.
if !self.pci_id_list.contains_key(&name) {
return Ok(name);
}
if self.device_id_cnt == start_id {
// We went through a full loop and there's nothing else we can
// do.
break;
}
}
Err(DeviceManagerError::NoAvailableVfioDeviceName)
}
#[cfg(feature = "pci_support")] #[cfg(feature = "pci_support")]
fn add_vfio_device( fn add_vfio_device(
&mut self, &mut self,
@@ -1406,7 +1449,7 @@ impl DeviceManager {
// do multifunction. Also, because we only support one PCI // do multifunction. Also, because we only support one PCI
// bus, the bus 0, we don't need to add anything to the // bus, the bus 0, we don't need to add anything to the
// global device ID. // global device ID.
let device_id = pci.next_device_id() << 3; let pci_device_bdf = pci.next_device_id() << 3;
let memory = self.memory_manager.lock().unwrap().guest_memory(); let memory = self.memory_manager.lock().unwrap().guest_memory();
let vfio_device = VfioDevice::new( let vfio_device = VfioDevice::new(
@@ -1425,7 +1468,7 @@ impl DeviceManager {
iommu iommu
.lock() .lock()
.unwrap() .unwrap()
.add_external_mapping(device_id, vfio_mapping); .add_external_mapping(pci_device_bdf, vfio_mapping);
} }
} }
@@ -1462,7 +1505,10 @@ impl DeviceManager {
) )
.map_err(DeviceManagerError::AddPciDevice)?; .map_err(DeviceManagerError::AddPciDevice)?;
Ok(device_id) let vfio_name = self.next_device_name(VFIO_DEVICE_NAME_PREFIX)?;
self.pci_id_list.insert(vfio_name, pci_device_bdf);
Ok(pci_device_bdf)
} }
#[cfg(feature = "pci_support")] #[cfg(feature = "pci_support")]