devices: vfio: prepare for vIOMMU support: multiple VFIO containers
In preparation for virtio IOMMU support, implement global variables
IOMMU_CONTAINERS and NO_IOMMU_CONTAINER to hold the VFIO containers
for VFIO devices with or without IOMMu enabled respectively.
Also implement vfio_get_container()help create VFIO container based
on the more complicated policies.
- all VFIO devices without attaching to virtio IOMMU devices share
one VFIO container.
- for IOMMU enabled devices, one VFIO container manages all devices
under one VFIO group.
- we don't support multiple IOMMU groups set to one VFIO container.
Currently don't see an user case for this.
BUG=b:181736020
TEST=unit tests.
Change-Id: I44d792cbc8ca9696c1da54c571aad1b94c7f665d
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/2976054
Tested-by: kokoro <noreply+kokoro@google.com>
Reviewed-by: Daniel Verkamp <dverkamp@chromium.org>
Reviewed-by: David Stevens <stevensd@chromium.org>
Commit-Queue: David Stevens <stevensd@chromium.org>
diff --git a/src/linux.rs b/src/linux.rs
index 06004ca..974b4d6 100644
--- a/src/linux.rs
+++ b/src/linux.rs
@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-use std::cell::RefCell;
use std::cmp::Reverse;
use std::convert::TryFrom;
#[cfg(feature = "gpu")]
@@ -33,6 +32,7 @@
use base::net::{UnixSeqpacket, UnixSeqpacketListener, UnlinkUnixSeqpacketListener};
use base::*;
+use devices::vfio::{VfioCommonSetup, VfioCommonTrait};
#[cfg(feature = "gpu")]
use devices::virtio::gpu::{DEFAULT_DISPLAY_HEIGHT, DEFAULT_DISPLAY_WIDTH};
use devices::virtio::vhost::user::{
@@ -45,8 +45,8 @@
#[cfg(feature = "audio")]
use devices::Ac97Dev;
use devices::{
- self, IrqChip, IrqEventIndex, KvmKernelIrqChip, PciDevice, VcpuRunState, VfioContainer,
- VfioDevice, VfioPciDevice, VirtioPciDevice,
+ self, IrqChip, IrqEventIndex, KvmKernelIrqChip, PciDevice, VcpuRunState, VfioDevice,
+ VfioPciDevice, VirtioPciDevice,
};
#[cfg(feature = "usb")]
use devices::{HostBackendDeviceProvider, XhciController};
@@ -97,7 +97,6 @@
BalloonDeviceNew(virtio::BalloonError),
BlockDeviceNew(base::Error),
BlockSignal(base::signal::Error),
- BorrowVfioContainer,
BuildVm(<Arch as LinuxArch>::Error),
ChownTpmStorage(base::Error),
CloneEvent(base::Error),
@@ -225,7 +224,6 @@
BalloonDeviceNew(e) => write!(f, "failed to create balloon: {}", e),
BlockDeviceNew(e) => write!(f, "failed to create block device: {}", e),
BlockSignal(e) => write!(f, "failed to block signal: {}", e),
- BorrowVfioContainer => write!(f, "failed to borrow global vfio container"),
BuildVm(e) => write!(f, "The architecture failed to build the vm: {}", e),
ChownTpmStorage(e) => write!(f, "failed to chown tpm storage: {}", e),
CloneEvent(e) => write!(f, "failed to clone event: {}", e),
@@ -1730,7 +1728,6 @@
Ok(devs)
}
-thread_local!(static VFIO_CONTAINER: RefCell<Option<Arc<Mutex<VfioContainer>>>> = RefCell::new(None));
fn create_vfio_device(
cfg: &Config,
vm: &impl Vm,
@@ -1740,21 +1737,7 @@
kvm_vfio_file: &SafeDescriptor,
) -> DeviceResult<(Box<VfioPciDevice>, Option<Minijail>)> {
let vfio_container =
- VFIO_CONTAINER.with::<_, DeviceResult<Arc<Mutex<VfioContainer>>>>(|v| {
- if v.borrow().is_some() {
- if let Some(container) = &(*v.borrow()) {
- Ok(container.clone())
- } else {
- Err(Error::BorrowVfioContainer)
- }
- } else {
- let container = Arc::new(Mutex::new(
- VfioContainer::new().map_err(Error::CreateVfioDevice)?,
- ));
- *v.borrow_mut() = Some(container.clone());
- Ok(container)
- }
- })?;
+ VfioCommonSetup::vfio_get_container(vfio_path, false).map_err(Error::CreateVfioDevice)?;
// create MSI, MSI-X, and Mem request sockets for each vfio device
let (vfio_host_tube_msi, vfio_device_tube_msi) = Tube::pair().map_err(Error::CreateTube)?;