mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
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:
committed by
Rob Bradford
parent
13a61c4784
commit
0f99d3f7cc
@@ -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")]
|
||||||
|
|||||||
Reference in New Issue
Block a user