mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +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:
@@ -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),
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user