mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2025-01-21 20:15:21 +00:00
vmm, pci: Implement virtio-mem support for vfio-user
Implement the infrastructure that lets a virtio-mem device map the guest memory into the device. This is necessary since with virtio-mem zones memory can be added or removed and the vfio-user device must be informed. Fixes: #3025 Signed-off-by: Rob Bradford <robert.bradford@intel.com>
This commit is contained in:
parent
e9d67dc405
commit
43365ade2e
@ -26,7 +26,7 @@ pub use self::device::{
|
||||
pub use self::msi::{msi_num_enabled_vectors, MsiCap, MsiConfig};
|
||||
pub use self::msix::{MsixCap, MsixConfig, MsixTableEntry, MSIX_TABLE_ENTRY_SIZE};
|
||||
pub use self::vfio::{VfioPciDevice, VfioPciError};
|
||||
pub use self::vfio_user::{VfioUserPciDevice, VfioUserPciDeviceError};
|
||||
pub use self::vfio_user::{VfioUserDmaMapping, VfioUserPciDevice, VfioUserPciDeviceError};
|
||||
|
||||
/// PCI has four interrupt pins A->D.
|
||||
#[derive(Copy, Clone)]
|
||||
|
@ -19,10 +19,14 @@ use vfio_bindings::bindings::vfio::*;
|
||||
use vfio_ioctls::VfioIrq;
|
||||
use vfio_user::{Client, Error as VfioUserError};
|
||||
use vm_allocator::SystemAllocator;
|
||||
use vm_device::dma_mapping::ExternalDmaMapping;
|
||||
use vm_device::interrupt::{InterruptManager, InterruptSourceGroup, MsiIrqGroupConfig};
|
||||
use vm_device::BusDevice;
|
||||
use vm_memory::bitmap::AtomicBitmap;
|
||||
use vm_memory::{Address, GuestAddress, GuestMemoryRegion, GuestRegionMmap, GuestUsize};
|
||||
use vm_memory::{
|
||||
Address, GuestAddress, GuestAddressSpace, GuestMemory, GuestMemoryRegion, GuestRegionMmap,
|
||||
GuestUsize,
|
||||
};
|
||||
use vmm_sys_util::eventfd::EventFd;
|
||||
|
||||
pub struct VfioUserPciDevice {
|
||||
@ -483,3 +487,57 @@ impl Drop for VfioUserPciDevice {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct VfioUserDmaMapping<M: GuestAddressSpace> {
|
||||
client: Arc<Mutex<Client>>,
|
||||
memory: Arc<M>,
|
||||
}
|
||||
|
||||
impl<M: GuestAddressSpace> VfioUserDmaMapping<M> {
|
||||
pub fn new(client: Arc<Mutex<Client>>, memory: Arc<M>) -> Self {
|
||||
Self { client, memory }
|
||||
}
|
||||
}
|
||||
|
||||
impl<M: GuestAddressSpace + Sync + Send> ExternalDmaMapping for VfioUserDmaMapping<M> {
|
||||
fn map(&self, iova: u64, gpa: u64, size: u64) -> std::result::Result<(), std::io::Error> {
|
||||
let mem = self.memory.memory();
|
||||
let guest_addr = GuestAddress(gpa);
|
||||
let region = mem.find_region(guest_addr);
|
||||
|
||||
if let Some(region) = region {
|
||||
let file_offset = region.file_offset().unwrap();
|
||||
let offset = (GuestAddress(gpa).checked_offset_from(region.start_addr())).unwrap()
|
||||
+ file_offset.start();
|
||||
|
||||
self.client
|
||||
.lock()
|
||||
.unwrap()
|
||||
.dma_map(offset, iova, size, file_offset.file().as_raw_fd())
|
||||
.map_err(|e| {
|
||||
std::io::Error::new(
|
||||
std::io::ErrorKind::Other,
|
||||
format!("Error mapping region: {}", e),
|
||||
)
|
||||
})
|
||||
} else {
|
||||
return Err(std::io::Error::new(
|
||||
std::io::ErrorKind::Other,
|
||||
format!("Region not found for 0x{:x}", gpa),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
fn unmap(&self, iova: u64, size: u64) -> std::result::Result<(), std::io::Error> {
|
||||
self.client
|
||||
.lock()
|
||||
.unwrap()
|
||||
.dma_unmap(iova, size)
|
||||
.map_err(|e| {
|
||||
std::io::Error::new(
|
||||
std::io::ErrorKind::Other,
|
||||
format!("Error unmapping region: {}", e),
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -123,6 +123,8 @@ fn virtio_mem_thread_rules() -> Vec<(i64, Vec<SeccompRule>)> {
|
||||
vec![
|
||||
(libc::SYS_fallocate, vec![]),
|
||||
(libc::SYS_ioctl, create_virtio_mem_ioctl_seccomp_rule()),
|
||||
(libc::SYS_recvfrom, vec![]),
|
||||
(libc::SYS_sendmsg, vec![]),
|
||||
]
|
||||
}
|
||||
|
||||
|
@ -69,7 +69,7 @@ use libc::{
|
||||
};
|
||||
use pci::{
|
||||
DeviceRelocation, PciBarRegionType, PciBus, PciConfigMmio, PciDevice, PciRoot, VfioPciDevice,
|
||||
VfioUserPciDevice, VfioUserPciDeviceError,
|
||||
VfioUserDmaMapping, VfioUserPciDevice, VfioUserPciDeviceError,
|
||||
};
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
use pci::{PciConfigIo, PCI_CONFIG_IO_PORT, PCI_CONFIG_IO_PORT_SIZE};
|
||||
@ -3115,7 +3115,7 @@ impl DeviceManager {
|
||||
|
||||
let mut vfio_user_pci_device = VfioUserPciDevice::new(
|
||||
&self.address_manager.vm,
|
||||
client,
|
||||
client.clone(),
|
||||
&self.msi_interrupt_manager,
|
||||
legacy_interrupt_group,
|
||||
)
|
||||
@ -3127,6 +3127,19 @@ impl DeviceManager {
|
||||
})
|
||||
.map_err(DeviceManagerError::VfioUserMapRegion)?;
|
||||
|
||||
let memory = self.memory_manager.lock().unwrap().guest_memory();
|
||||
let vfio_user_mapping = Arc::new(VfioUserDmaMapping::new(client, Arc::new(memory)));
|
||||
for virtio_mem_device in self.virtio_mem_devices.iter() {
|
||||
virtio_mem_device
|
||||
.lock()
|
||||
.unwrap()
|
||||
.add_dma_mapping_handler(
|
||||
VirtioMemMappingSource::Device(pci_device_bdf),
|
||||
vfio_user_mapping.clone(),
|
||||
)
|
||||
.map_err(DeviceManagerError::AddDmaMappingHandlerVirtioMem)?;
|
||||
}
|
||||
|
||||
for (_, zone) in self.memory_manager.lock().unwrap().memory_zones().iter() {
|
||||
for region in zone.regions() {
|
||||
vfio_user_pci_device
|
||||
@ -3564,6 +3577,7 @@ impl DeviceManager {
|
||||
.pci_device_handle
|
||||
.ok_or(DeviceManagerError::MissingPciDevice)?;
|
||||
let (pci_device, bus_device, virtio_device) = match pci_device_handle {
|
||||
// No need to remove any virtio-mem mapping here as the container outlives all devices
|
||||
PciDeviceHandle::Vfio(vfio_pci_device) => (
|
||||
Arc::clone(&vfio_pci_device) as Arc<Mutex<dyn PciDevice>>,
|
||||
Arc::clone(&vfio_pci_device) as Arc<Mutex<dyn BusDevice>>,
|
||||
@ -3594,6 +3608,14 @@ impl DeviceManager {
|
||||
}
|
||||
}
|
||||
|
||||
for virtio_mem_device in self.virtio_mem_devices.iter() {
|
||||
virtio_mem_device
|
||||
.lock()
|
||||
.unwrap()
|
||||
.remove_dma_mapping_handler(VirtioMemMappingSource::Device(pci_device_bdf))
|
||||
.map_err(DeviceManagerError::RemoveDmaMappingHandlerVirtioMem)?;
|
||||
}
|
||||
|
||||
(
|
||||
Arc::clone(&vfio_user_pci_device) as Arc<Mutex<dyn PciDevice>>,
|
||||
Arc::clone(&vfio_user_pci_device) as Arc<Mutex<dyn BusDevice>>,
|
||||
|
Loading…
x
Reference in New Issue
Block a user