Linux: Make vfio kvm file as global

One vm may have one vfio kvm file only, it could be created at vm
setup or runtime through vfio-pci hotplug, make it as global to
satisfy these two cases.

When vfio pci device is removed throgh hotplug out, the vfio group
will be removed frome vfio kvm file also, so move it into vfio.rs,
so it is could be referenced at vfio group's destroy. And
vfio group's destroy is called from vcpu thread, while vfio kvm file
is created in main thread, so use OnceCall instead of thread_local.

BUG=b:185084350
TEST=Boot a vm with or without passthrough device

Change-Id: I780c43a0ac0265f1e6f62578e134d09cbefc3e2f
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/3062741
Reviewed-by: Daniel Verkamp <dverkamp@chromium.org>
Tested-by: kokoro <noreply+kokoro@google.com>
Commit-Queue: Daniel Verkamp <dverkamp@chromium.org>
diff --git a/src/linux.rs b/src/linux.rs
index 9c587cf..32f06d9 100644
--- a/src/linux.rs
+++ b/src/linux.rs
@@ -50,7 +50,7 @@
 #[cfg(feature = "usb")]
 use devices::{HostBackendDeviceProvider, XhciController};
 use hypervisor::kvm::{Kvm, KvmVcpu, KvmVm};
-use hypervisor::{DeviceKind, HypervisorCap, Vcpu, VcpuExit, VcpuRunHandle, Vm, VmCap};
+use hypervisor::{HypervisorCap, Vcpu, VcpuExit, VcpuRunHandle, Vm, VmCap};
 use minijail::{self, Minijail};
 use net_util::{MacAddress, Tap};
 use resources::{Alloc, MmioType, SystemAllocator};
@@ -1473,7 +1473,6 @@
     resources: &mut SystemAllocator,
     control_tubes: &mut Vec<TaggedControlTube>,
     vfio_path: &Path,
-    kvm_vfio_file: &SafeDescriptor,
     endpoints: &mut BTreeMap<u32, Arc<Mutex<VfioContainer>>>,
     iommu_enabled: bool,
 ) -> DeviceResult<(Box<VfioPciDevice>, Option<Minijail>)> {
@@ -1490,14 +1489,8 @@
     let (vfio_host_tube_mem, vfio_device_tube_mem) = Tube::pair().map_err(Error::CreateTube)?;
     control_tubes.push(TaggedControlTube::VmMemory(vfio_host_tube_mem));
 
-    let vfio_device = VfioDevice::new(
-        vfio_path,
-        vm.get_memory(),
-        &kvm_vfio_file,
-        vfio_container.clone(),
-        iommu_enabled,
-    )
-    .map_err(Error::CreateVfioDevice)?;
+    let vfio_device = VfioDevice::new(vfio_path, vm, vfio_container.clone(), iommu_enabled)
+        .map_err(Error::CreateVfioDevice)?;
     let mut vfio_pci_device = Box::new(VfioPciDevice::new(
         vfio_device,
         vfio_device_tube_msi,
@@ -1577,10 +1570,6 @@
     }
 
     if !cfg.vfio.is_empty() {
-        let kvm_vfio_file = vm
-            .create_device(DeviceKind::Vfio)
-            .map_err(Error::CreateVfioKvmDevice)?;
-
         let mut iommu_attached_endpoints: BTreeMap<u32, Arc<Mutex<VfioContainer>>> =
             BTreeMap::new();
 
@@ -1591,7 +1580,6 @@
                 resources,
                 control_tubes,
                 vfio_path.as_path(),
-                &kvm_vfio_file,
                 &mut iommu_attached_endpoints,
                 *enable_iommu,
             )?;