mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2024-10-02 11:35:46 +00:00
vmm: Remove mmio and pci differentiation
Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
This commit is contained in:
parent
d2741fdc84
commit
af3c6c34c3
@ -49,10 +49,8 @@ serde_json = "1.0.59"
|
|||||||
net_util = { path = "net_util" }
|
net_util = { path = "net_util" }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["acpi", "pci", "cmos", "kvm"]
|
default = ["acpi", "cmos", "kvm"]
|
||||||
acpi = ["vmm/acpi"]
|
acpi = ["vmm/acpi"]
|
||||||
pci = ["vmm/pci_support"]
|
|
||||||
mmio = ["vmm/mmio_support"]
|
|
||||||
cmos = ["vmm/cmos"]
|
cmos = ["vmm/cmos"]
|
||||||
fwdebug = ["vmm/fwdebug"]
|
fwdebug = ["vmm/fwdebug"]
|
||||||
kvm = ["vmm/kvm"]
|
kvm = ["vmm/kvm"]
|
||||||
|
@ -7,8 +7,6 @@ edition = "2018"
|
|||||||
[features]
|
[features]
|
||||||
default = []
|
default = []
|
||||||
acpi = ["acpi_tables","devices/acpi", "arch/acpi"]
|
acpi = ["acpi_tables","devices/acpi", "arch/acpi"]
|
||||||
pci_support = ["pci", "vfio-ioctls", "virtio-devices/pci_support"]
|
|
||||||
mmio_support = ["virtio-devices/mmio_support"]
|
|
||||||
cmos = ["devices/cmos"]
|
cmos = ["devices/cmos"]
|
||||||
fwdebug = ["devices/fwdebug"]
|
fwdebug = ["devices/fwdebug"]
|
||||||
kvm = ["hypervisor/kvm"]
|
kvm = ["hypervisor/kvm"]
|
||||||
@ -31,15 +29,15 @@ log = "0.4.11"
|
|||||||
micro_http = { git = "https://github.com/firecracker-microvm/micro-http", branch = "master" }
|
micro_http = { git = "https://github.com/firecracker-microvm/micro-http", branch = "master" }
|
||||||
net_util = { path = "../net_util" }
|
net_util = { path = "../net_util" }
|
||||||
option_parser = { path = "../option_parser" }
|
option_parser = { path = "../option_parser" }
|
||||||
pci = {path = "../pci", optional = true}
|
pci = { path = "../pci" }
|
||||||
qcow = { path = "../qcow" }
|
qcow = { path = "../qcow" }
|
||||||
seccomp = { git = "https://github.com/firecracker-microvm/firecracker", tag = "v0.22.0" }
|
seccomp = { git = "https://github.com/firecracker-microvm/firecracker", tag = "v0.22.0" }
|
||||||
serde = {version = ">=1.0.27", features = ["rc"] }
|
serde = {version = ">=1.0.27", features = ["rc"] }
|
||||||
serde_derive = ">=1.0.27"
|
serde_derive = ">=1.0.27"
|
||||||
serde_json = ">=1.0.9"
|
serde_json = ">=1.0.9"
|
||||||
url = "2.1.1"
|
url = "2.1.1"
|
||||||
vfio-ioctls = { git = "https://github.com/cloud-hypervisor/vfio-ioctls", branch = "ch", optional = true }
|
vfio-ioctls = { git = "https://github.com/cloud-hypervisor/vfio-ioctls", branch = "ch" }
|
||||||
virtio-devices = {path = "../virtio-devices"}
|
virtio-devices = { path = "../virtio-devices", features = ["pci_support"]}
|
||||||
vm-allocator = { path = "../vm-allocator" }
|
vm-allocator = { path = "../vm-allocator" }
|
||||||
vm-device = { path = "../vm-device" }
|
vm-device = { path = "../vm-device" }
|
||||||
vm-memory = { version = "0.3.0", features = ["backend-mmap", "backend-atomic"] }
|
vm-memory = { version = "0.3.0", features = ["backend-mmap", "backend-atomic"] }
|
||||||
|
@ -1449,15 +1449,6 @@ impl VmConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if cfg!(not(feature = "pci_support")) {
|
|
||||||
if self.iommu {
|
|
||||||
return Err(ValidationError::IommuUnsupported);
|
|
||||||
}
|
|
||||||
if self.devices.is_some() {
|
|
||||||
return Err(ValidationError::VfioUnsupported);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(t) = &self.cpus.topology {
|
if let Some(t) = &self.cpus.topology {
|
||||||
if t.threads_per_core == 0
|
if t.threads_per_core == 0
|
||||||
|| t.cores_per_die == 0
|
|| t.cores_per_die == 0
|
||||||
|
@ -10,7 +10,6 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
use crate::config::ConsoleOutputMode;
|
use crate::config::ConsoleOutputMode;
|
||||||
#[cfg(feature = "pci_support")]
|
|
||||||
use crate::config::DeviceConfig;
|
use crate::config::DeviceConfig;
|
||||||
use crate::config::{DiskConfig, FsConfig, NetConfig, PmemConfig, VmConfig, VsockConfig};
|
use crate::config::{DiskConfig, FsConfig, NetConfig, PmemConfig, VmConfig, VsockConfig};
|
||||||
use crate::device_tree::{DeviceNode, DeviceTree};
|
use crate::device_tree::{DeviceNode, DeviceTree};
|
||||||
@ -20,7 +19,6 @@ use crate::interrupt::LegacyUserspaceInterruptManager;
|
|||||||
use crate::memory_manager::{Error as MemoryManagerError, MemoryManager};
|
use crate::memory_manager::{Error as MemoryManagerError, MemoryManager};
|
||||||
#[cfg(feature = "acpi")]
|
#[cfg(feature = "acpi")]
|
||||||
use crate::vm::NumaNodes;
|
use crate::vm::NumaNodes;
|
||||||
#[cfg(feature = "pci_support")]
|
|
||||||
use crate::PciDeviceInfo;
|
use crate::PciDeviceInfo;
|
||||||
use crate::{device_node, DEVICE_MANAGER_SNAPSHOT_ID};
|
use crate::{device_node, DEVICE_MANAGER_SNAPSHOT_ID};
|
||||||
#[cfg(feature = "acpi")]
|
#[cfg(feature = "acpi")]
|
||||||
@ -47,39 +45,33 @@ use devices::{
|
|||||||
};
|
};
|
||||||
use hypervisor::kvm_ioctls;
|
use hypervisor::kvm_ioctls;
|
||||||
use hypervisor::kvm_ioctls::*;
|
use hypervisor::kvm_ioctls::*;
|
||||||
#[cfg(feature = "mmio_support")]
|
|
||||||
use hypervisor::vm::DataMatch;
|
|
||||||
#[cfg(target_arch = "aarch64")]
|
#[cfg(target_arch = "aarch64")]
|
||||||
use hypervisor::CpuState;
|
use hypervisor::CpuState;
|
||||||
use libc::TIOCGWINSZ;
|
use libc::TIOCGWINSZ;
|
||||||
use libc::{MAP_NORESERVE, MAP_PRIVATE, MAP_SHARED, O_TMPFILE, PROT_READ, PROT_WRITE};
|
use libc::{MAP_NORESERVE, MAP_PRIVATE, MAP_SHARED, O_TMPFILE, PROT_READ, PROT_WRITE};
|
||||||
#[cfg(feature = "pci_support")]
|
|
||||||
use pci::{
|
use pci::{
|
||||||
DeviceRelocation, PciBarRegionType, PciBus, PciConfigIo, PciConfigMmio, PciDevice, PciRoot,
|
DeviceRelocation, PciBarRegionType, PciBus, PciConfigIo, PciConfigMmio, PciDevice, PciRoot,
|
||||||
VfioPciDevice,
|
VfioPciDevice,
|
||||||
};
|
};
|
||||||
use qcow::{self, ImageType, QcowFile};
|
use qcow::{self, ImageType, QcowFile};
|
||||||
use seccomp::SeccompAction;
|
use seccomp::SeccompAction;
|
||||||
#[cfg(feature = "pci_support")]
|
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::fs::{File, OpenOptions};
|
use std::fs::{File, OpenOptions};
|
||||||
use std::io::{self, sink, stdout, Seek, SeekFrom};
|
use std::io::{self, sink, stdout, Seek, SeekFrom};
|
||||||
use std::num::Wrapping;
|
use std::num::Wrapping;
|
||||||
use std::os::unix::fs::OpenOptionsExt;
|
use std::os::unix::fs::OpenOptionsExt;
|
||||||
#[cfg(all(feature = "pci_support", feature = "kvm"))]
|
#[cfg(feature = "kvm")]
|
||||||
use std::os::unix::io::FromRawFd;
|
use std::os::unix::io::FromRawFd;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::result;
|
use std::result;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use tempfile::NamedTempFile;
|
use tempfile::NamedTempFile;
|
||||||
#[cfg(all(feature = "pci_support", feature = "kvm"))]
|
#[cfg(feature = "kvm")]
|
||||||
use vfio_ioctls::{VfioContainer, VfioDevice, VfioDmaMapping};
|
use vfio_ioctls::{VfioContainer, VfioDevice, VfioDmaMapping};
|
||||||
#[cfg(feature = "pci_support")]
|
|
||||||
use virtio_devices::transport::VirtioPciDevice;
|
use virtio_devices::transport::VirtioPciDevice;
|
||||||
use virtio_devices::transport::VirtioTransport;
|
use virtio_devices::transport::VirtioTransport;
|
||||||
use virtio_devices::vhost_user::VhostUserConfig;
|
use virtio_devices::vhost_user::VhostUserConfig;
|
||||||
#[cfg(feature = "pci_support")]
|
|
||||||
use virtio_devices::{DmaRemapping, IommuMapping};
|
use virtio_devices::{DmaRemapping, IommuMapping};
|
||||||
use virtio_devices::{VirtioSharedMemory, VirtioSharedMemoryList};
|
use virtio_devices::{VirtioSharedMemory, VirtioSharedMemoryList};
|
||||||
use vm_allocator::SystemAllocator;
|
use vm_allocator::SystemAllocator;
|
||||||
@ -95,14 +87,13 @@ use vm_migration::{
|
|||||||
Migratable, MigratableError, Pausable, Snapshot, SnapshotDataSection, Snapshottable,
|
Migratable, MigratableError, Pausable, Snapshot, SnapshotDataSection, Snapshottable,
|
||||||
Transportable,
|
Transportable,
|
||||||
};
|
};
|
||||||
#[cfg(feature = "pci_support")]
|
|
||||||
use vm_virtio::{VirtioDeviceType, VirtioIommuRemapping};
|
use vm_virtio::{VirtioDeviceType, VirtioIommuRemapping};
|
||||||
use vmm_sys_util::eventfd::EventFd;
|
use vmm_sys_util::eventfd::EventFd;
|
||||||
|
|
||||||
#[cfg(any(feature = "mmio_support", target_arch = "aarch64"))]
|
#[cfg(target_arch = "aarch64")]
|
||||||
const MMIO_LEN: u64 = 0x1000;
|
const MMIO_LEN: u64 = 0x1000;
|
||||||
|
|
||||||
#[cfg(all(feature = "pci_support", feature = "kvm"))]
|
#[cfg(feature = "kvm")]
|
||||||
const VFIO_DEVICE_NAME_PREFIX: &str = "_vfio";
|
const VFIO_DEVICE_NAME_PREFIX: &str = "_vfio";
|
||||||
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
@ -120,12 +111,8 @@ const PMEM_DEVICE_NAME_PREFIX: &str = "_pmem";
|
|||||||
const RNG_DEVICE_NAME: &str = "_rng";
|
const RNG_DEVICE_NAME: &str = "_rng";
|
||||||
const VSOCK_DEVICE_NAME_PREFIX: &str = "_vsock";
|
const VSOCK_DEVICE_NAME_PREFIX: &str = "_vsock";
|
||||||
|
|
||||||
#[cfg(feature = "pci_support")]
|
|
||||||
const IOMMU_DEVICE_NAME: &str = "_iommu";
|
const IOMMU_DEVICE_NAME: &str = "_iommu";
|
||||||
|
|
||||||
#[cfg(feature = "mmio_support")]
|
|
||||||
const VIRTIO_MMIO_DEVICE_NAME_PREFIX: &str = "_virtio-mmio";
|
|
||||||
#[cfg(feature = "pci_support")]
|
|
||||||
const VIRTIO_PCI_DEVICE_NAME_PREFIX: &str = "_virtio-pci";
|
const VIRTIO_PCI_DEVICE_NAME_PREFIX: &str = "_virtio-pci";
|
||||||
|
|
||||||
/// Errors associated with device manager
|
/// Errors associated with device manager
|
||||||
@ -195,11 +182,9 @@ pub enum DeviceManagerError {
|
|||||||
Irq(kvm_ioctls::Error),
|
Irq(kvm_ioctls::Error),
|
||||||
|
|
||||||
/// Cannot allocate PCI BARs
|
/// Cannot allocate PCI BARs
|
||||||
#[cfg(feature = "pci_support")]
|
|
||||||
AllocateBars(pci::PciDeviceError),
|
AllocateBars(pci::PciDeviceError),
|
||||||
|
|
||||||
/// Could not free the BARs associated with a PCI device.
|
/// Could not free the BARs associated with a PCI device.
|
||||||
#[cfg(feature = "pci_support")]
|
|
||||||
FreePciBars(pci::PciDeviceError),
|
FreePciBars(pci::PciDeviceError),
|
||||||
|
|
||||||
/// Cannot register ioevent.
|
/// Cannot register ioevent.
|
||||||
@ -212,7 +197,6 @@ pub enum DeviceManagerError {
|
|||||||
VirtioDevice(vmm_sys_util::errno::Error),
|
VirtioDevice(vmm_sys_util::errno::Error),
|
||||||
|
|
||||||
/// Cannot add PCI device
|
/// Cannot add PCI device
|
||||||
#[cfg(feature = "pci_support")]
|
|
||||||
AddPciDevice(pci::PciRootError),
|
AddPciDevice(pci::PciRootError),
|
||||||
|
|
||||||
/// Cannot open persistent memory file
|
/// Cannot open persistent memory file
|
||||||
@ -234,15 +218,12 @@ pub enum DeviceManagerError {
|
|||||||
ConsoleOutputFileOpen(io::Error),
|
ConsoleOutputFileOpen(io::Error),
|
||||||
|
|
||||||
/// Cannot create a VFIO device
|
/// Cannot create a VFIO device
|
||||||
#[cfg(feature = "pci_support")]
|
|
||||||
VfioCreate(vfio_ioctls::VfioError),
|
VfioCreate(vfio_ioctls::VfioError),
|
||||||
|
|
||||||
/// Cannot create a VFIO PCI device
|
/// Cannot create a VFIO PCI device
|
||||||
#[cfg(feature = "pci_support")]
|
|
||||||
VfioPciCreate(pci::VfioPciError),
|
VfioPciCreate(pci::VfioPciError),
|
||||||
|
|
||||||
/// Failed to map VFIO MMIO region.
|
/// Failed to map VFIO MMIO region.
|
||||||
#[cfg(feature = "pci_support")]
|
|
||||||
VfioMapRegion(pci::VfioPciError),
|
VfioMapRegion(pci::VfioPciError),
|
||||||
|
|
||||||
/// Failed to create the passthrough device.
|
/// Failed to create the passthrough device.
|
||||||
@ -297,7 +278,6 @@ pub enum DeviceManagerError {
|
|||||||
MissingPciDevice,
|
MissingPciDevice,
|
||||||
|
|
||||||
/// Failed removing a PCI device from the PCI bus.
|
/// Failed removing a PCI device from the PCI bus.
|
||||||
#[cfg(feature = "pci_support")]
|
|
||||||
RemoveDeviceFromPciBus(pci::PciRootError),
|
RemoveDeviceFromPciBus(pci::PciRootError),
|
||||||
|
|
||||||
/// Failed removing a bus device from the IO bus.
|
/// Failed removing a bus device from the IO bus.
|
||||||
@ -307,27 +287,21 @@ pub enum DeviceManagerError {
|
|||||||
RemoveDeviceFromMmioBus(vm_device::BusError),
|
RemoveDeviceFromMmioBus(vm_device::BusError),
|
||||||
|
|
||||||
/// Failed to find the device corresponding to a specific PCI b/d/f.
|
/// Failed to find the device corresponding to a specific PCI b/d/f.
|
||||||
#[cfg(feature = "pci_support")]
|
|
||||||
UnknownPciBdf(u32),
|
UnknownPciBdf(u32),
|
||||||
|
|
||||||
/// Not allowed to remove this type of device from the VM.
|
/// Not allowed to remove this type of device from the VM.
|
||||||
#[cfg(feature = "pci_support")]
|
|
||||||
RemovalNotAllowed(vm_virtio::VirtioDeviceType),
|
RemovalNotAllowed(vm_virtio::VirtioDeviceType),
|
||||||
|
|
||||||
/// Failed to find device corresponding to the given identifier.
|
/// Failed to find device corresponding to the given identifier.
|
||||||
#[cfg(feature = "pci_support")]
|
|
||||||
UnknownDeviceId(String),
|
UnknownDeviceId(String),
|
||||||
|
|
||||||
/// Failed to find an available PCI device ID.
|
/// Failed to find an available PCI device ID.
|
||||||
#[cfg(feature = "pci_support")]
|
|
||||||
NextPciDeviceId(pci::PciRootError),
|
NextPciDeviceId(pci::PciRootError),
|
||||||
|
|
||||||
/// Could not reserve the PCI device ID.
|
/// Could not reserve the PCI device ID.
|
||||||
#[cfg(feature = "pci_support")]
|
|
||||||
GetPciDeviceId(pci::PciRootError),
|
GetPciDeviceId(pci::PciRootError),
|
||||||
|
|
||||||
/// Could not give the PCI device ID back.
|
/// Could not give the PCI device ID back.
|
||||||
#[cfg(feature = "pci_support")]
|
|
||||||
PutPciDeviceId(pci::PciRootError),
|
PutPciDeviceId(pci::PciRootError),
|
||||||
|
|
||||||
/// Incorrect device ID as it is already used by another device.
|
/// Incorrect device ID as it is already used by another device.
|
||||||
@ -349,7 +323,6 @@ pub enum DeviceManagerError {
|
|||||||
VirtioMemRangeAllocation,
|
VirtioMemRangeAllocation,
|
||||||
|
|
||||||
/// Failed updating guest memory for VFIO PCI device.
|
/// Failed updating guest memory for VFIO PCI device.
|
||||||
#[cfg(feature = "pci_support")]
|
|
||||||
UpdateMemoryForVfioPciDevice(pci::VfioPciError),
|
UpdateMemoryForVfioPciDevice(pci::VfioPciError),
|
||||||
|
|
||||||
/// Trying to use a directory for pmem but no size specified
|
/// Trying to use a directory for pmem but no size specified
|
||||||
@ -377,7 +350,6 @@ pub enum DeviceManagerError {
|
|||||||
MissingVirtioFsResources,
|
MissingVirtioFsResources,
|
||||||
|
|
||||||
/// Missing PCI b/d/f from the DeviceNode.
|
/// Missing PCI b/d/f from the DeviceNode.
|
||||||
#[cfg(feature = "pci_support")]
|
|
||||||
MissingDeviceNodePciBdf,
|
MissingDeviceNodePciBdf,
|
||||||
|
|
||||||
/// No support for device passthrough
|
/// No support for device passthrough
|
||||||
@ -465,11 +437,9 @@ struct AddressManager {
|
|||||||
io_bus: Arc<Bus>,
|
io_bus: Arc<Bus>,
|
||||||
mmio_bus: Arc<Bus>,
|
mmio_bus: Arc<Bus>,
|
||||||
vm: Arc<dyn hypervisor::Vm>,
|
vm: Arc<dyn hypervisor::Vm>,
|
||||||
#[cfg(feature = "pci_support")]
|
|
||||||
device_tree: Arc<Mutex<DeviceTree>>,
|
device_tree: Arc<Mutex<DeviceTree>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "pci_support")]
|
|
||||||
impl DeviceRelocation for AddressManager {
|
impl DeviceRelocation for AddressManager {
|
||||||
fn move_bar(
|
fn move_bar(
|
||||||
&self,
|
&self,
|
||||||
@ -763,7 +733,6 @@ pub struct DeviceManager {
|
|||||||
device_id_cnt: Wrapping<usize>,
|
device_id_cnt: Wrapping<usize>,
|
||||||
|
|
||||||
// Keep a reference to the PCI bus
|
// Keep a reference to the PCI bus
|
||||||
#[cfg(feature = "pci_support")]
|
|
||||||
pci_bus: Option<Arc<Mutex<PciBus>>>,
|
pci_bus: Option<Arc<Mutex<PciBus>>>,
|
||||||
|
|
||||||
#[cfg_attr(target_arch = "aarch64", allow(dead_code))]
|
#[cfg_attr(target_arch = "aarch64", allow(dead_code))]
|
||||||
@ -771,27 +740,21 @@ pub struct DeviceManager {
|
|||||||
msi_interrupt_manager: Arc<dyn InterruptManager<GroupConfig = MsiIrqGroupConfig>>,
|
msi_interrupt_manager: Arc<dyn InterruptManager<GroupConfig = MsiIrqGroupConfig>>,
|
||||||
|
|
||||||
// Passthrough device handle
|
// Passthrough device handle
|
||||||
#[cfg(feature = "pci_support")]
|
|
||||||
passthrough_device: Option<Arc<dyn hypervisor::Device>>,
|
passthrough_device: Option<Arc<dyn hypervisor::Device>>,
|
||||||
|
|
||||||
// Paravirtualized IOMMU
|
// Paravirtualized IOMMU
|
||||||
#[cfg(feature = "pci_support")]
|
|
||||||
iommu_device: Option<Arc<Mutex<virtio_devices::Iommu>>>,
|
iommu_device: Option<Arc<Mutex<virtio_devices::Iommu>>>,
|
||||||
|
|
||||||
// Bitmap of PCI devices to hotplug.
|
// Bitmap of PCI devices to hotplug.
|
||||||
#[cfg(feature = "pci_support")]
|
|
||||||
pci_devices_up: u32,
|
pci_devices_up: u32,
|
||||||
|
|
||||||
// Bitmap of PCI devices to hotunplug.
|
// Bitmap of PCI devices to hotunplug.
|
||||||
#[cfg(feature = "pci_support")]
|
|
||||||
pci_devices_down: u32,
|
pci_devices_down: u32,
|
||||||
|
|
||||||
// Hashmap of device's name to their corresponding PCI b/d/f.
|
// Hashmap of device's name to their corresponding PCI b/d/f.
|
||||||
#[cfg(feature = "pci_support")]
|
|
||||||
pci_id_list: HashMap<String, u32>,
|
pci_id_list: HashMap<String, u32>,
|
||||||
|
|
||||||
// Hashmap of PCI b/d/f to their corresponding Arc<Mutex<dyn PciDevice>>.
|
// Hashmap of PCI b/d/f to their corresponding Arc<Mutex<dyn PciDevice>>.
|
||||||
#[cfg(feature = "pci_support")]
|
|
||||||
pci_devices: HashMap<u32, Arc<dyn Any + Send + Sync>>,
|
pci_devices: HashMap<u32, Arc<dyn Any + Send + Sync>>,
|
||||||
|
|
||||||
// Tree of devices, representing the dependencies between devices.
|
// Tree of devices, representing the dependencies between devices.
|
||||||
@ -837,7 +800,6 @@ impl DeviceManager {
|
|||||||
io_bus: Arc::new(Bus::new()),
|
io_bus: Arc::new(Bus::new()),
|
||||||
mmio_bus: Arc::new(Bus::new()),
|
mmio_bus: Arc::new(Bus::new()),
|
||||||
vm: vm.clone(),
|
vm: vm.clone(),
|
||||||
#[cfg(feature = "pci_support")]
|
|
||||||
device_tree: Arc::clone(&device_tree),
|
device_tree: Arc::clone(&device_tree),
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -869,20 +831,13 @@ impl DeviceManager {
|
|||||||
vmm_path,
|
vmm_path,
|
||||||
vhost_user_backends: Vec::new(),
|
vhost_user_backends: Vec::new(),
|
||||||
device_id_cnt: Wrapping(0),
|
device_id_cnt: Wrapping(0),
|
||||||
#[cfg(feature = "pci_support")]
|
|
||||||
pci_bus: None,
|
pci_bus: None,
|
||||||
msi_interrupt_manager,
|
msi_interrupt_manager,
|
||||||
#[cfg(feature = "pci_support")]
|
|
||||||
passthrough_device: None,
|
passthrough_device: None,
|
||||||
#[cfg(feature = "pci_support")]
|
|
||||||
iommu_device: None,
|
iommu_device: None,
|
||||||
#[cfg(feature = "pci_support")]
|
|
||||||
pci_devices_up: 0,
|
pci_devices_up: 0,
|
||||||
#[cfg(feature = "pci_support")]
|
|
||||||
pci_devices_down: 0,
|
pci_devices_down: 0,
|
||||||
#[cfg(feature = "pci_support")]
|
|
||||||
pci_id_list: HashMap::new(),
|
pci_id_list: HashMap::new(),
|
||||||
#[cfg(feature = "pci_support")]
|
|
||||||
pci_devices: HashMap::new(),
|
pci_devices: HashMap::new(),
|
||||||
device_tree,
|
device_tree,
|
||||||
#[cfg(feature = "acpi")]
|
#[cfg(feature = "acpi")]
|
||||||
@ -975,14 +930,9 @@ impl DeviceManager {
|
|||||||
|
|
||||||
self.console = self.add_console_device(&legacy_interrupt_manager, &mut virtio_devices)?;
|
self.console = self.add_console_device(&legacy_interrupt_manager, &mut virtio_devices)?;
|
||||||
|
|
||||||
#[cfg(any(feature = "pci_support", feature = "mmio_support"))]
|
|
||||||
virtio_devices.append(&mut self.make_virtio_devices()?);
|
virtio_devices.append(&mut self.make_virtio_devices()?);
|
||||||
|
|
||||||
if cfg!(feature = "pci_support") {
|
self.add_pci_devices(virtio_devices.clone())?;
|
||||||
self.add_pci_devices(virtio_devices.clone())?;
|
|
||||||
} else if cfg!(feature = "mmio_support") {
|
|
||||||
self.add_mmio_devices(virtio_devices.clone(), &legacy_interrupt_manager)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
self.virtio_devices = virtio_devices;
|
self.virtio_devices = virtio_devices;
|
||||||
|
|
||||||
@ -1014,123 +964,98 @@ impl DeviceManager {
|
|||||||
&mut self,
|
&mut self,
|
||||||
virtio_devices: Vec<(VirtioDeviceArc, bool, String)>,
|
virtio_devices: Vec<(VirtioDeviceArc, bool, String)>,
|
||||||
) -> DeviceManagerResult<()> {
|
) -> DeviceManagerResult<()> {
|
||||||
#[cfg(feature = "pci_support")]
|
let pci_root = PciRoot::new(None);
|
||||||
{
|
let mut pci_bus = PciBus::new(
|
||||||
let pci_root = PciRoot::new(None);
|
pci_root,
|
||||||
let mut pci_bus = PciBus::new(
|
Arc::clone(&self.address_manager) as Arc<dyn DeviceRelocation>,
|
||||||
pci_root,
|
);
|
||||||
Arc::clone(&self.address_manager) as Arc<dyn DeviceRelocation>,
|
|
||||||
);
|
|
||||||
|
|
||||||
let iommu_id = String::from(IOMMU_DEVICE_NAME);
|
let iommu_id = String::from(IOMMU_DEVICE_NAME);
|
||||||
|
|
||||||
let (iommu_device, iommu_mapping) = if self.config.lock().unwrap().iommu {
|
let (iommu_device, iommu_mapping) = if self.config.lock().unwrap().iommu {
|
||||||
let (device, mapping) =
|
let (device, mapping) =
|
||||||
virtio_devices::Iommu::new(iommu_id.clone(), self.seccomp_action.clone())
|
virtio_devices::Iommu::new(iommu_id.clone(), self.seccomp_action.clone())
|
||||||
.map_err(DeviceManagerError::CreateVirtioIommu)?;
|
.map_err(DeviceManagerError::CreateVirtioIommu)?;
|
||||||
let device = Arc::new(Mutex::new(device));
|
let device = Arc::new(Mutex::new(device));
|
||||||
self.iommu_device = Some(Arc::clone(&device));
|
self.iommu_device = Some(Arc::clone(&device));
|
||||||
|
|
||||||
// Fill the device tree with a new node. In case of restore, we
|
// Fill the device tree with a new node. In case of restore, we
|
||||||
// know there is nothing to do, so we can simply override the
|
// know there is nothing to do, so we can simply override the
|
||||||
// existing entry.
|
// existing entry.
|
||||||
self.device_tree
|
self.device_tree
|
||||||
.lock()
|
.lock()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.insert(iommu_id.clone(), device_node!(iommu_id, device));
|
.insert(iommu_id.clone(), device_node!(iommu_id, device));
|
||||||
|
|
||||||
(Some(device), Some(mapping))
|
(Some(device), Some(mapping))
|
||||||
|
} else {
|
||||||
|
(None, None)
|
||||||
|
};
|
||||||
|
|
||||||
|
let interrupt_manager = Arc::clone(&self.msi_interrupt_manager);
|
||||||
|
|
||||||
|
let mut iommu_attached_devices = Vec::new();
|
||||||
|
|
||||||
|
for (device, iommu_attached, id) in virtio_devices {
|
||||||
|
let mapping: &Option<Arc<IommuMapping>> = if iommu_attached {
|
||||||
|
&iommu_mapping
|
||||||
} else {
|
} else {
|
||||||
(None, None)
|
&None
|
||||||
};
|
};
|
||||||
|
|
||||||
let interrupt_manager = Arc::clone(&self.msi_interrupt_manager);
|
let dev_id =
|
||||||
|
self.add_virtio_pci_device(device, &mut pci_bus, mapping, &interrupt_manager, id)?;
|
||||||
|
|
||||||
let mut iommu_attached_devices = Vec::new();
|
if iommu_attached {
|
||||||
|
iommu_attached_devices.push(dev_id);
|
||||||
for (device, iommu_attached, id) in virtio_devices {
|
|
||||||
let mapping: &Option<Arc<IommuMapping>> = if iommu_attached {
|
|
||||||
&iommu_mapping
|
|
||||||
} else {
|
|
||||||
&None
|
|
||||||
};
|
|
||||||
|
|
||||||
let dev_id = self.add_virtio_pci_device(
|
|
||||||
device,
|
|
||||||
&mut pci_bus,
|
|
||||||
mapping,
|
|
||||||
&interrupt_manager,
|
|
||||||
id,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
if iommu_attached {
|
|
||||||
iommu_attached_devices.push(dev_id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut vfio_iommu_device_ids =
|
|
||||||
self.add_vfio_devices(&mut pci_bus, &interrupt_manager)?;
|
|
||||||
|
|
||||||
iommu_attached_devices.append(&mut vfio_iommu_device_ids);
|
|
||||||
|
|
||||||
if let Some(iommu_device) = iommu_device {
|
|
||||||
iommu_device
|
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.attach_pci_devices(0, iommu_attached_devices);
|
|
||||||
|
|
||||||
// Because we determined the virtio-iommu b/d/f, we have to
|
|
||||||
// add the device to the PCI topology now. Otherwise, the
|
|
||||||
// b/d/f won't match the virtio-iommu device as expected.
|
|
||||||
self.add_virtio_pci_device(
|
|
||||||
iommu_device,
|
|
||||||
&mut pci_bus,
|
|
||||||
&None,
|
|
||||||
&interrupt_manager,
|
|
||||||
iommu_id,
|
|
||||||
)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
let pci_bus = Arc::new(Mutex::new(pci_bus));
|
|
||||||
let pci_config_io = Arc::new(Mutex::new(PciConfigIo::new(Arc::clone(&pci_bus))));
|
|
||||||
self.bus_devices
|
|
||||||
.push(Arc::clone(&pci_config_io) as Arc<Mutex<dyn BusDevice>>);
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
|
||||||
self.address_manager
|
|
||||||
.io_bus
|
|
||||||
.insert(pci_config_io, 0xcf8, 0x8)
|
|
||||||
.map_err(DeviceManagerError::BusError)?;
|
|
||||||
let pci_config_mmio = Arc::new(Mutex::new(PciConfigMmio::new(Arc::clone(&pci_bus))));
|
|
||||||
self.bus_devices
|
|
||||||
.push(Arc::clone(&pci_config_mmio) as Arc<Mutex<dyn BusDevice>>);
|
|
||||||
self.address_manager
|
|
||||||
.mmio_bus
|
|
||||||
.insert(
|
|
||||||
pci_config_mmio,
|
|
||||||
arch::layout::PCI_MMCONFIG_START.0,
|
|
||||||
arch::layout::PCI_MMCONFIG_SIZE,
|
|
||||||
)
|
|
||||||
.map_err(DeviceManagerError::BusError)?;
|
|
||||||
|
|
||||||
self.pci_bus = Some(pci_bus);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(unused_variables, unused_mut)]
|
|
||||||
fn add_mmio_devices(
|
|
||||||
&mut self,
|
|
||||||
virtio_devices: Vec<(VirtioDeviceArc, bool, String)>,
|
|
||||||
interrupt_manager: &Arc<dyn InterruptManager<GroupConfig = LegacyIrqGroupConfig>>,
|
|
||||||
) -> DeviceManagerResult<()> {
|
|
||||||
#[cfg(feature = "mmio_support")]
|
|
||||||
{
|
|
||||||
for (device, _, id) in virtio_devices {
|
|
||||||
self.add_virtio_mmio_device(id, device, interrupt_manager)?;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut vfio_iommu_device_ids = self.add_vfio_devices(&mut pci_bus, &interrupt_manager)?;
|
||||||
|
|
||||||
|
iommu_attached_devices.append(&mut vfio_iommu_device_ids);
|
||||||
|
|
||||||
|
if let Some(iommu_device) = iommu_device {
|
||||||
|
iommu_device
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.attach_pci_devices(0, iommu_attached_devices);
|
||||||
|
|
||||||
|
// Because we determined the virtio-iommu b/d/f, we have to
|
||||||
|
// add the device to the PCI topology now. Otherwise, the
|
||||||
|
// b/d/f won't match the virtio-iommu device as expected.
|
||||||
|
self.add_virtio_pci_device(
|
||||||
|
iommu_device,
|
||||||
|
&mut pci_bus,
|
||||||
|
&None,
|
||||||
|
&interrupt_manager,
|
||||||
|
iommu_id,
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let pci_bus = Arc::new(Mutex::new(pci_bus));
|
||||||
|
let pci_config_io = Arc::new(Mutex::new(PciConfigIo::new(Arc::clone(&pci_bus))));
|
||||||
|
self.bus_devices
|
||||||
|
.push(Arc::clone(&pci_config_io) as Arc<Mutex<dyn BusDevice>>);
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
|
self.address_manager
|
||||||
|
.io_bus
|
||||||
|
.insert(pci_config_io, 0xcf8, 0x8)
|
||||||
|
.map_err(DeviceManagerError::BusError)?;
|
||||||
|
let pci_config_mmio = Arc::new(Mutex::new(PciConfigMmio::new(Arc::clone(&pci_bus))));
|
||||||
|
self.bus_devices
|
||||||
|
.push(Arc::clone(&pci_config_mmio) as Arc<Mutex<dyn BusDevice>>);
|
||||||
|
self.address_manager
|
||||||
|
.mmio_bus
|
||||||
|
.insert(
|
||||||
|
pci_config_mmio,
|
||||||
|
arch::layout::PCI_MMCONFIG_START.0,
|
||||||
|
arch::layout::PCI_MMCONFIG_SIZE,
|
||||||
|
)
|
||||||
|
.map_err(DeviceManagerError::BusError)?;
|
||||||
|
|
||||||
|
self.pci_bus = Some(pci_bus);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2543,17 +2468,6 @@ impl DeviceManager {
|
|||||||
Ok(devices)
|
Ok(devices)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "pci_support"))]
|
|
||||||
fn next_device_name(&mut self, prefix: &str) -> DeviceManagerResult<String> {
|
|
||||||
// Generate the temporary name.
|
|
||||||
let name = format!("{}{}", prefix, self.device_id_cnt);
|
|
||||||
// Increment the counter.
|
|
||||||
self.device_id_cnt += Wrapping(1);
|
|
||||||
|
|
||||||
Ok(name)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "pci_support")]
|
|
||||||
fn next_device_name(&mut self, prefix: &str) -> DeviceManagerResult<String> {
|
fn next_device_name(&mut self, prefix: &str) -> DeviceManagerResult<String> {
|
||||||
let start_id = self.device_id_cnt;
|
let start_id = self.device_id_cnt;
|
||||||
loop {
|
loop {
|
||||||
@ -2575,7 +2489,6 @@ impl DeviceManager {
|
|||||||
Err(DeviceManagerError::NoAvailableDeviceName)
|
Err(DeviceManagerError::NoAvailableDeviceName)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "pci_support")]
|
|
||||||
#[cfg_attr(not(feature = "kvm"), allow(unused_variables))]
|
#[cfg_attr(not(feature = "kvm"), allow(unused_variables))]
|
||||||
fn add_passthrough_device(
|
fn add_passthrough_device(
|
||||||
&mut self,
|
&mut self,
|
||||||
@ -2590,7 +2503,7 @@ impl DeviceManager {
|
|||||||
Err(DeviceManagerError::NoDevicePassthroughSupport)
|
Err(DeviceManagerError::NoDevicePassthroughSupport)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(all(feature = "pci_support", feature = "kvm"))]
|
#[cfg(feature = "kvm")]
|
||||||
fn add_vfio_device(
|
fn add_vfio_device(
|
||||||
&mut self,
|
&mut self,
|
||||||
pci: &mut PciBus,
|
pci: &mut PciBus,
|
||||||
@ -2700,7 +2613,6 @@ impl DeviceManager {
|
|||||||
Ok((pci_device_bdf, vfio_name))
|
Ok((pci_device_bdf, vfio_name))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "pci_support")]
|
|
||||||
fn add_pci_device(
|
fn add_pci_device(
|
||||||
&mut self,
|
&mut self,
|
||||||
pci_bus: &mut PciBus,
|
pci_bus: &mut PciBus,
|
||||||
@ -2740,7 +2652,6 @@ impl DeviceManager {
|
|||||||
Ok(bars)
|
Ok(bars)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "pci_support")]
|
|
||||||
fn add_vfio_devices(
|
fn add_vfio_devices(
|
||||||
&mut self,
|
&mut self,
|
||||||
pci: &mut PciBus,
|
pci: &mut PciBus,
|
||||||
@ -2775,7 +2686,6 @@ impl DeviceManager {
|
|||||||
Ok(iommu_attached_device_ids)
|
Ok(iommu_attached_device_ids)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "pci_support")]
|
|
||||||
fn add_virtio_pci_device(
|
fn add_virtio_pci_device(
|
||||||
&mut self,
|
&mut self,
|
||||||
virtio_device: VirtioDeviceArc,
|
virtio_device: VirtioDeviceArc,
|
||||||
@ -2914,160 +2824,6 @@ impl DeviceManager {
|
|||||||
Ok(pci_device_bdf)
|
Ok(pci_device_bdf)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "mmio_support")]
|
|
||||||
fn add_virtio_mmio_device(
|
|
||||||
&mut self,
|
|
||||||
virtio_device_id: String,
|
|
||||||
virtio_device: VirtioDeviceArc,
|
|
||||||
interrupt_manager: &Arc<dyn InterruptManager<GroupConfig = LegacyIrqGroupConfig>>,
|
|
||||||
) -> DeviceManagerResult<()> {
|
|
||||||
let id = format!("{}-{}", VIRTIO_MMIO_DEVICE_NAME_PREFIX, virtio_device_id);
|
|
||||||
|
|
||||||
// Create the new virtio-mmio node that will be added later to the
|
|
||||||
// device tree.
|
|
||||||
let mut node = device_node!(id);
|
|
||||||
node.children = vec![virtio_device_id.clone()];
|
|
||||||
|
|
||||||
// Look for the id in the device tree. If it can be found, that means
|
|
||||||
// the device is being restored, otherwise it's created from scratch.
|
|
||||||
let (mmio_range, mmio_irq) = if let Some(node) = self.device_tree.lock().unwrap().get(&id) {
|
|
||||||
debug!("Restoring virtio-mmio {} resources", id);
|
|
||||||
|
|
||||||
let mut mmio_range: Option<(u64, u64)> = None;
|
|
||||||
let mut mmio_irq: Option<u32> = None;
|
|
||||||
for resource in node.resources.iter() {
|
|
||||||
match resource {
|
|
||||||
Resource::MmioAddressRange { base, size } => {
|
|
||||||
if mmio_range.is_some() {
|
|
||||||
return Err(DeviceManagerError::ResourceAlreadyExists);
|
|
||||||
}
|
|
||||||
|
|
||||||
mmio_range = Some((*base, *size));
|
|
||||||
}
|
|
||||||
Resource::LegacyIrq(irq) => {
|
|
||||||
if mmio_irq.is_some() {
|
|
||||||
return Err(DeviceManagerError::ResourceAlreadyExists);
|
|
||||||
}
|
|
||||||
|
|
||||||
mmio_irq = Some(*irq);
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
error!("Unexpected resource {:?} for {}", resource, id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if mmio_range.is_none() || mmio_irq.is_none() {
|
|
||||||
return Err(DeviceManagerError::MissingVirtioMmioResources);
|
|
||||||
}
|
|
||||||
|
|
||||||
(mmio_range, mmio_irq)
|
|
||||||
} else {
|
|
||||||
(None, None)
|
|
||||||
};
|
|
||||||
|
|
||||||
// Update the existing virtio node by setting the parent.
|
|
||||||
if let Some(node) = self.device_tree.lock().unwrap().get_mut(&virtio_device_id) {
|
|
||||||
node.parent = Some(id.clone());
|
|
||||||
} else {
|
|
||||||
return Err(DeviceManagerError::MissingNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
let (mmio_base, mmio_size) = if let Some((base, size)) = mmio_range {
|
|
||||||
self.address_manager
|
|
||||||
.allocator
|
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.allocate_mmio_addresses(Some(GuestAddress(base)), size, Some(size))
|
|
||||||
.ok_or(DeviceManagerError::MmioRangeAllocation)?;
|
|
||||||
|
|
||||||
(base, size)
|
|
||||||
} else {
|
|
||||||
let size = MMIO_LEN;
|
|
||||||
let base = self
|
|
||||||
.address_manager
|
|
||||||
.allocator
|
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.allocate_mmio_addresses(None, size, Some(size))
|
|
||||||
.ok_or(DeviceManagerError::MmioRangeAllocation)?;
|
|
||||||
|
|
||||||
(base.raw_value(), size)
|
|
||||||
};
|
|
||||||
|
|
||||||
let irq_num = if let Some(irq) = mmio_irq {
|
|
||||||
irq
|
|
||||||
} else {
|
|
||||||
self.address_manager
|
|
||||||
.allocator
|
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.allocate_irq()
|
|
||||||
.ok_or(DeviceManagerError::AllocateIrq)?
|
|
||||||
};
|
|
||||||
|
|
||||||
#[cfg(target_arch = "aarch64")]
|
|
||||||
{
|
|
||||||
let device_type = virtio_device.lock().unwrap().device_type();
|
|
||||||
self.id_to_dev_info.insert(
|
|
||||||
(DeviceType::Virtio(device_type), virtio_device_id),
|
|
||||||
MMIODeviceInfo {
|
|
||||||
addr: mmio_base,
|
|
||||||
len: mmio_size,
|
|
||||||
irq: irq_num,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
let memory = self.memory_manager.lock().unwrap().guest_memory();
|
|
||||||
let mut mmio_device =
|
|
||||||
virtio_devices::transport::MmioDevice::new(id.clone(), memory, virtio_device)
|
|
||||||
.map_err(DeviceManagerError::VirtioDevice)?;
|
|
||||||
|
|
||||||
for (i, (event, addr)) in mmio_device.ioeventfds(mmio_base).iter().enumerate() {
|
|
||||||
let io_addr = IoEventAddress::Mmio(*addr);
|
|
||||||
self.address_manager
|
|
||||||
.vm
|
|
||||||
.register_ioevent(event, &io_addr, Some(DataMatch::DataMatch32(i as u32)))
|
|
||||||
.map_err(|e| DeviceManagerError::RegisterIoevent(e.into()))?;
|
|
||||||
}
|
|
||||||
|
|
||||||
let interrupt_group = interrupt_manager
|
|
||||||
.create_group(LegacyIrqGroupConfig {
|
|
||||||
irq: irq_num as InterruptIndex,
|
|
||||||
})
|
|
||||||
.map_err(DeviceManagerError::CreateInterruptGroup)?;
|
|
||||||
|
|
||||||
mmio_device.assign_interrupt(interrupt_group);
|
|
||||||
|
|
||||||
let mmio_device_arc = Arc::new(Mutex::new(mmio_device));
|
|
||||||
self.bus_devices
|
|
||||||
.push(Arc::clone(&mmio_device_arc) as Arc<Mutex<dyn BusDevice>>);
|
|
||||||
self.address_manager
|
|
||||||
.mmio_bus
|
|
||||||
.insert(mmio_device_arc.clone(), mmio_base, MMIO_LEN)
|
|
||||||
.map_err(DeviceManagerError::BusError)?;
|
|
||||||
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
|
||||||
self.cmdline_additions.push(format!(
|
|
||||||
"virtio_mmio.device={}K@0x{:08x}:{}",
|
|
||||||
mmio_size / 1024,
|
|
||||||
mmio_base,
|
|
||||||
irq_num
|
|
||||||
));
|
|
||||||
|
|
||||||
// Update the device tree with correct resource information.
|
|
||||||
node.resources.push(Resource::MmioAddressRange {
|
|
||||||
base: mmio_base,
|
|
||||||
size: mmio_size,
|
|
||||||
});
|
|
||||||
node.resources.push(Resource::LegacyIrq(irq_num));
|
|
||||||
node.migratable = Some(Arc::clone(&mmio_device_arc) as Arc<Mutex<dyn Migratable>>);
|
|
||||||
self.device_tree.lock().unwrap().insert(id, node);
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
pub fn io_bus(&self) -> &Arc<Bus> {
|
pub fn io_bus(&self) -> &Arc<Bus> {
|
||||||
&self.address_manager.io_bus
|
&self.address_manager.io_bus
|
||||||
@ -3108,18 +2864,13 @@ impl DeviceManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Take care of updating the memory for VFIO PCI devices.
|
// Take care of updating the memory for VFIO PCI devices.
|
||||||
#[cfg(feature = "pci_support")]
|
for (_, any_device) in self.pci_devices.iter() {
|
||||||
{
|
if let Ok(vfio_pci_device) = Arc::clone(any_device).downcast::<Mutex<VfioPciDevice>>() {
|
||||||
for (_, any_device) in self.pci_devices.iter() {
|
vfio_pci_device
|
||||||
if let Ok(vfio_pci_device) =
|
.lock()
|
||||||
Arc::clone(any_device).downcast::<Mutex<VfioPciDevice>>()
|
.unwrap()
|
||||||
{
|
.update_memory(_new_region)
|
||||||
vfio_pci_device
|
.map_err(DeviceManagerError::UpdateMemoryForVfioPciDevice)?;
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.update_memory(_new_region)
|
|
||||||
.map_err(DeviceManagerError::UpdateMemoryForVfioPciDevice)?;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3143,7 +2894,6 @@ impl DeviceManager {
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "pci_support")]
|
|
||||||
pub fn add_device(
|
pub fn add_device(
|
||||||
&mut self,
|
&mut self,
|
||||||
device_cfg: &mut DeviceConfig,
|
device_cfg: &mut DeviceConfig,
|
||||||
@ -3179,7 +2929,6 @@ impl DeviceManager {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "pci_support")]
|
|
||||||
pub fn remove_device(&mut self, id: String) -> DeviceManagerResult<()> {
|
pub fn remove_device(&mut self, id: String) -> DeviceManagerResult<()> {
|
||||||
if let Some(pci_device_bdf) = self.pci_id_list.get(&id) {
|
if let Some(pci_device_bdf) = self.pci_id_list.get(&id) {
|
||||||
if let Some(any_device) = self.pci_devices.get(&pci_device_bdf) {
|
if let Some(any_device) = self.pci_devices.get(&pci_device_bdf) {
|
||||||
@ -3225,7 +2974,6 @@ impl DeviceManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "pci_support")]
|
|
||||||
pub fn eject_device(&mut self, device_id: u8) -> DeviceManagerResult<()> {
|
pub fn eject_device(&mut self, device_id: u8) -> DeviceManagerResult<()> {
|
||||||
// Retrieve the PCI bus.
|
// Retrieve the PCI bus.
|
||||||
let pci = if let Some(pci_bus) = &self.pci_bus {
|
let pci = if let Some(pci_bus) = &self.pci_bus {
|
||||||
@ -3337,7 +3085,6 @@ impl DeviceManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "pci_support")]
|
|
||||||
fn hotplug_virtio_pci_device(
|
fn hotplug_virtio_pci_device(
|
||||||
&mut self,
|
&mut self,
|
||||||
device: VirtioDeviceArc,
|
device: VirtioDeviceArc,
|
||||||
@ -3376,31 +3123,26 @@ impl DeviceManager {
|
|||||||
Ok(PciDeviceInfo { id, bdf: device_id })
|
Ok(PciDeviceInfo { id, bdf: device_id })
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "pci_support")]
|
|
||||||
pub fn add_disk(&mut self, disk_cfg: &mut DiskConfig) -> DeviceManagerResult<PciDeviceInfo> {
|
pub fn add_disk(&mut self, disk_cfg: &mut DiskConfig) -> DeviceManagerResult<PciDeviceInfo> {
|
||||||
let (device, iommu_attached, id) = self.make_virtio_block_device(disk_cfg)?;
|
let (device, iommu_attached, id) = self.make_virtio_block_device(disk_cfg)?;
|
||||||
self.hotplug_virtio_pci_device(device, iommu_attached, id)
|
self.hotplug_virtio_pci_device(device, iommu_attached, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "pci_support")]
|
|
||||||
pub fn add_fs(&mut self, fs_cfg: &mut FsConfig) -> DeviceManagerResult<PciDeviceInfo> {
|
pub fn add_fs(&mut self, fs_cfg: &mut FsConfig) -> DeviceManagerResult<PciDeviceInfo> {
|
||||||
let (device, iommu_attached, id) = self.make_virtio_fs_device(fs_cfg)?;
|
let (device, iommu_attached, id) = self.make_virtio_fs_device(fs_cfg)?;
|
||||||
self.hotplug_virtio_pci_device(device, iommu_attached, id)
|
self.hotplug_virtio_pci_device(device, iommu_attached, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "pci_support")]
|
|
||||||
pub fn add_pmem(&mut self, pmem_cfg: &mut PmemConfig) -> DeviceManagerResult<PciDeviceInfo> {
|
pub fn add_pmem(&mut self, pmem_cfg: &mut PmemConfig) -> DeviceManagerResult<PciDeviceInfo> {
|
||||||
let (device, iommu_attached, id) = self.make_virtio_pmem_device(pmem_cfg)?;
|
let (device, iommu_attached, id) = self.make_virtio_pmem_device(pmem_cfg)?;
|
||||||
self.hotplug_virtio_pci_device(device, iommu_attached, id)
|
self.hotplug_virtio_pci_device(device, iommu_attached, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "pci_support")]
|
|
||||||
pub fn add_net(&mut self, net_cfg: &mut NetConfig) -> DeviceManagerResult<PciDeviceInfo> {
|
pub fn add_net(&mut self, net_cfg: &mut NetConfig) -> DeviceManagerResult<PciDeviceInfo> {
|
||||||
let (device, iommu_attached, id) = self.make_virtio_net_device(net_cfg)?;
|
let (device, iommu_attached, id) = self.make_virtio_net_device(net_cfg)?;
|
||||||
self.hotplug_virtio_pci_device(device, iommu_attached, id)
|
self.hotplug_virtio_pci_device(device, iommu_attached, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "pci_support")]
|
|
||||||
pub fn add_vsock(&mut self, vsock_cfg: &mut VsockConfig) -> DeviceManagerResult<PciDeviceInfo> {
|
pub fn add_vsock(&mut self, vsock_cfg: &mut VsockConfig) -> DeviceManagerResult<PciDeviceInfo> {
|
||||||
let (device, iommu_attached, id) = self.make_virtio_vsock_device(vsock_cfg)?;
|
let (device, iommu_attached, id) = self.make_virtio_vsock_device(vsock_cfg)?;
|
||||||
self.hotplug_virtio_pci_device(device, iommu_attached, id)
|
self.hotplug_virtio_pci_device(device, iommu_attached, id)
|
||||||
@ -3792,23 +3534,16 @@ impl Snapshottable for DeviceManager {
|
|||||||
impl Transportable for DeviceManager {}
|
impl Transportable for DeviceManager {}
|
||||||
impl Migratable for DeviceManager {}
|
impl Migratable for DeviceManager {}
|
||||||
|
|
||||||
#[cfg(feature = "pci_support")]
|
|
||||||
const PCIU_FIELD_OFFSET: u64 = 0;
|
const PCIU_FIELD_OFFSET: u64 = 0;
|
||||||
#[cfg(feature = "pci_support")]
|
|
||||||
const PCID_FIELD_OFFSET: u64 = 4;
|
const PCID_FIELD_OFFSET: u64 = 4;
|
||||||
#[cfg(feature = "pci_support")]
|
|
||||||
const B0EJ_FIELD_OFFSET: u64 = 8;
|
const B0EJ_FIELD_OFFSET: u64 = 8;
|
||||||
|
|
||||||
#[cfg(feature = "pci_support")]
|
|
||||||
const PCIU_FIELD_SIZE: usize = 4;
|
const PCIU_FIELD_SIZE: usize = 4;
|
||||||
#[cfg(feature = "pci_support")]
|
|
||||||
const PCID_FIELD_SIZE: usize = 4;
|
const PCID_FIELD_SIZE: usize = 4;
|
||||||
#[cfg(feature = "pci_support")]
|
|
||||||
const B0EJ_FIELD_SIZE: usize = 4;
|
const B0EJ_FIELD_SIZE: usize = 4;
|
||||||
|
|
||||||
impl BusDevice for DeviceManager {
|
impl BusDevice for DeviceManager {
|
||||||
fn read(&mut self, base: u64, offset: u64, data: &mut [u8]) {
|
fn read(&mut self, base: u64, offset: u64, data: &mut [u8]) {
|
||||||
#[cfg(feature = "pci_support")]
|
|
||||||
match offset {
|
match offset {
|
||||||
PCIU_FIELD_OFFSET => {
|
PCIU_FIELD_OFFSET => {
|
||||||
assert!(data.len() == PCIU_FIELD_SIZE);
|
assert!(data.len() == PCIU_FIELD_SIZE);
|
||||||
@ -3835,7 +3570,6 @@ impl BusDevice for DeviceManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn write(&mut self, base: u64, offset: u64, data: &[u8]) {
|
fn write(&mut self, base: u64, offset: u64, data: &[u8]) {
|
||||||
#[cfg(feature = "pci_support")]
|
|
||||||
match offset {
|
match offset {
|
||||||
B0EJ_FIELD_OFFSET => {
|
B0EJ_FIELD_OFFSET => {
|
||||||
assert!(data.len() == B0EJ_FIELD_SIZE);
|
assert!(data.len() == B0EJ_FIELD_SIZE);
|
||||||
|
@ -15,7 +15,6 @@ pub struct DeviceNode {
|
|||||||
pub children: Vec<String>,
|
pub children: Vec<String>,
|
||||||
#[serde(skip)]
|
#[serde(skip)]
|
||||||
pub migratable: Option<Arc<Mutex<dyn Migratable>>>,
|
pub migratable: Option<Arc<Mutex<dyn Migratable>>>,
|
||||||
#[cfg(feature = "pci_support")]
|
|
||||||
pub pci_bdf: Option<u32>,
|
pub pci_bdf: Option<u32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -27,7 +26,6 @@ impl DeviceNode {
|
|||||||
parent: None,
|
parent: None,
|
||||||
children: Vec::new(),
|
children: Vec::new(),
|
||||||
migratable,
|
migratable,
|
||||||
#[cfg(feature = "pci_support")]
|
|
||||||
pci_bdf: None,
|
pci_bdf: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
164
vmm/src/vm.rs
164
vmm/src/vm.rs
@ -19,7 +19,6 @@ extern crate libc;
|
|||||||
extern crate linux_loader;
|
extern crate linux_loader;
|
||||||
extern crate net_util;
|
extern crate net_util;
|
||||||
extern crate signal_hook;
|
extern crate signal_hook;
|
||||||
#[cfg(feature = "pci_support")]
|
|
||||||
extern crate vm_allocator;
|
extern crate vm_allocator;
|
||||||
extern crate vm_memory;
|
extern crate vm_memory;
|
||||||
|
|
||||||
@ -945,30 +944,26 @@ impl Vm {
|
|||||||
.get_device_info()
|
.get_device_info()
|
||||||
.clone();
|
.clone();
|
||||||
|
|
||||||
let pci_space: Option<(u64, u64)> = if cfg!(feature = "pci_support") {
|
let pci_space_start: GuestAddress = self
|
||||||
let pci_space_start: GuestAddress = self
|
.memory_manager
|
||||||
.memory_manager
|
.lock()
|
||||||
.lock()
|
.as_ref()
|
||||||
.as_ref()
|
.unwrap()
|
||||||
.unwrap()
|
.start_of_device_area();
|
||||||
.start_of_device_area();
|
|
||||||
|
|
||||||
let pci_space_end: GuestAddress = self
|
let pci_space_end: GuestAddress = self
|
||||||
.memory_manager
|
.memory_manager
|
||||||
.lock()
|
.lock()
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.end_of_device_area();
|
.end_of_device_area();
|
||||||
|
|
||||||
let pci_space_size = pci_space_end
|
let pci_space_size = pci_space_end
|
||||||
.checked_offset_from(pci_space_start)
|
.checked_offset_from(pci_space_start)
|
||||||
.ok_or(Error::MemOverflow)?
|
.ok_or(Error::MemOverflow)?
|
||||||
+ 1;
|
+ 1;
|
||||||
|
|
||||||
Some((pci_space_start.0, pci_space_size))
|
let pci_space = Some((pci_space_start.0, pci_space_size));
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
// Call `configure_system` and pass the GIC devices out, so that
|
// Call `configure_system` and pass the GIC devices out, so that
|
||||||
// we can register the GIC device to the device manager.
|
// we can register the GIC device to the device manager.
|
||||||
@ -1158,12 +1153,6 @@ impl Vm {
|
|||||||
Err(Error::ResizeZone)
|
Err(Error::ResizeZone)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "pci_support"))]
|
|
||||||
pub fn add_device(&mut self, mut _device_cfg: DeviceConfig) -> Result<PciDeviceInfo> {
|
|
||||||
Err(Error::NoPciSupport)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "pci_support")]
|
|
||||||
pub fn add_device(&mut self, mut _device_cfg: DeviceConfig) -> Result<PciDeviceInfo> {
|
pub fn add_device(&mut self, mut _device_cfg: DeviceConfig) -> Result<PciDeviceInfo> {
|
||||||
let pci_device_info = self
|
let pci_device_info = self
|
||||||
.device_manager
|
.device_manager
|
||||||
@ -1193,66 +1182,51 @@ impl Vm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn remove_device(&mut self, _id: String) -> Result<()> {
|
pub fn remove_device(&mut self, _id: String) -> Result<()> {
|
||||||
if cfg!(feature = "pci_support") {
|
self.device_manager
|
||||||
#[cfg(feature = "pci_support")]
|
.lock()
|
||||||
{
|
.unwrap()
|
||||||
self.device_manager
|
.remove_device(_id.clone())
|
||||||
.lock()
|
.map_err(Error::DeviceManager)?;
|
||||||
.unwrap()
|
|
||||||
.remove_device(_id.clone())
|
|
||||||
.map_err(Error::DeviceManager)?;
|
|
||||||
|
|
||||||
// Update VmConfig by removing the device. This is important to
|
// Update VmConfig by removing the device. This is important to
|
||||||
// ensure the device would not be created in case of a reboot.
|
// ensure the device would not be created in case of a reboot.
|
||||||
{
|
let mut config = self.config.lock().unwrap();
|
||||||
let mut config = self.config.lock().unwrap();
|
|
||||||
|
|
||||||
// Remove if VFIO device
|
// Remove if VFIO device
|
||||||
if let Some(devices) = config.devices.as_mut() {
|
if let Some(devices) = config.devices.as_mut() {
|
||||||
devices.retain(|dev| dev.id.as_ref() != Some(&_id));
|
devices.retain(|dev| dev.id.as_ref() != Some(&_id));
|
||||||
}
|
|
||||||
|
|
||||||
// Remove if disk device
|
|
||||||
if let Some(disks) = config.disks.as_mut() {
|
|
||||||
disks.retain(|dev| dev.id.as_ref() != Some(&_id));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove if net device
|
|
||||||
if let Some(net) = config.net.as_mut() {
|
|
||||||
net.retain(|dev| dev.id.as_ref() != Some(&_id));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove if pmem device
|
|
||||||
if let Some(pmem) = config.pmem.as_mut() {
|
|
||||||
pmem.retain(|dev| dev.id.as_ref() != Some(&_id));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove if vsock device
|
|
||||||
if let Some(vsock) = config.vsock.as_ref() {
|
|
||||||
if vsock.id.as_ref() == Some(&_id) {
|
|
||||||
config.vsock = None;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.device_manager
|
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.notify_hotplug(HotPlugNotificationFlags::PCI_DEVICES_CHANGED)
|
|
||||||
.map_err(Error::DeviceManager)?;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
} else {
|
|
||||||
Err(Error::NoPciSupport)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remove if disk device
|
||||||
|
if let Some(disks) = config.disks.as_mut() {
|
||||||
|
disks.retain(|dev| dev.id.as_ref() != Some(&_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove if net device
|
||||||
|
if let Some(net) = config.net.as_mut() {
|
||||||
|
net.retain(|dev| dev.id.as_ref() != Some(&_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove if pmem device
|
||||||
|
if let Some(pmem) = config.pmem.as_mut() {
|
||||||
|
pmem.retain(|dev| dev.id.as_ref() != Some(&_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove if vsock device
|
||||||
|
if let Some(vsock) = config.vsock.as_ref() {
|
||||||
|
if vsock.id.as_ref() == Some(&_id) {
|
||||||
|
config.vsock = None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.device_manager
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.notify_hotplug(HotPlugNotificationFlags::PCI_DEVICES_CHANGED)
|
||||||
|
.map_err(Error::DeviceManager)?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "pci_support"))]
|
|
||||||
pub fn add_disk(&mut self, mut _disk_cfg: DiskConfig) -> Result<PciDeviceInfo> {
|
|
||||||
Err(Error::NoPciSupport)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "pci_support")]
|
|
||||||
pub fn add_disk(&mut self, mut _disk_cfg: DiskConfig) -> Result<PciDeviceInfo> {
|
pub fn add_disk(&mut self, mut _disk_cfg: DiskConfig) -> Result<PciDeviceInfo> {
|
||||||
let pci_device_info = self
|
let pci_device_info = self
|
||||||
.device_manager
|
.device_manager
|
||||||
@ -1281,12 +1255,6 @@ impl Vm {
|
|||||||
Ok(pci_device_info)
|
Ok(pci_device_info)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "pci_support"))]
|
|
||||||
pub fn add_fs(&mut self, mut _fs_cfg: FsConfig) -> Result<PciDeviceInfo> {
|
|
||||||
Err(Error::NoPciSupport)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "pci_support")]
|
|
||||||
pub fn add_fs(&mut self, mut _fs_cfg: FsConfig) -> Result<PciDeviceInfo> {
|
pub fn add_fs(&mut self, mut _fs_cfg: FsConfig) -> Result<PciDeviceInfo> {
|
||||||
let pci_device_info = self
|
let pci_device_info = self
|
||||||
.device_manager
|
.device_manager
|
||||||
@ -1315,12 +1283,6 @@ impl Vm {
|
|||||||
Ok(pci_device_info)
|
Ok(pci_device_info)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "pci_support"))]
|
|
||||||
pub fn add_pmem(&mut self, mut _pmem_cfg: PmemConfig) -> Result<PciDeviceInfo> {
|
|
||||||
Err(Error::NoPciSupport)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "pci_support")]
|
|
||||||
pub fn add_pmem(&mut self, mut _pmem_cfg: PmemConfig) -> Result<PciDeviceInfo> {
|
pub fn add_pmem(&mut self, mut _pmem_cfg: PmemConfig) -> Result<PciDeviceInfo> {
|
||||||
let pci_device_info = self
|
let pci_device_info = self
|
||||||
.device_manager
|
.device_manager
|
||||||
@ -1349,12 +1311,6 @@ impl Vm {
|
|||||||
Ok(pci_device_info)
|
Ok(pci_device_info)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "pci_support"))]
|
|
||||||
pub fn add_net(&mut self, mut _net_cfg: NetConfig) -> Result<PciDeviceInfo> {
|
|
||||||
Err(Error::NoPciSupport)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "pci_support")]
|
|
||||||
pub fn add_net(&mut self, mut _net_cfg: NetConfig) -> Result<PciDeviceInfo> {
|
pub fn add_net(&mut self, mut _net_cfg: NetConfig) -> Result<PciDeviceInfo> {
|
||||||
let pci_device_info = self
|
let pci_device_info = self
|
||||||
.device_manager
|
.device_manager
|
||||||
@ -1383,12 +1339,6 @@ impl Vm {
|
|||||||
Ok(pci_device_info)
|
Ok(pci_device_info)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "pci_support"))]
|
|
||||||
pub fn add_vsock(&mut self, mut _vsock_cfg: VsockConfig) -> Result<PciDeviceInfo> {
|
|
||||||
Err(Error::NoPciSupport)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "pci_support")]
|
|
||||||
pub fn add_vsock(&mut self, mut _vsock_cfg: VsockConfig) -> Result<PciDeviceInfo> {
|
pub fn add_vsock(&mut self, mut _vsock_cfg: VsockConfig) -> Result<PciDeviceInfo> {
|
||||||
if self.config.lock().unwrap().vsock.is_some() {
|
if self.config.lock().unwrap().vsock.is_some() {
|
||||||
return Err(Error::TooManyVsockDevices);
|
return Err(Error::TooManyVsockDevices);
|
||||||
|
Loading…
Reference in New Issue
Block a user