vmm: Enable vDPA support

Based on the newly added Vdpa device along with the new vdpa parameter,
this patch enables the support for vDPA devices.

It's important to note this the only virtio device for which we provide
an ExternalDmaMapping instance. This will allow for the right DMA ranges
to be mapped/unmapped.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
This commit is contained in:
Sebastien Boeuf 2022-03-11 12:31:25 +01:00
parent 72169686fe
commit c73c6039c3
2 changed files with 129 additions and 2 deletions

View File

@ -11,7 +11,7 @@
use crate::config::{
ConsoleOutputMode, DeviceConfig, DiskConfig, FsConfig, NetConfig, PmemConfig, UserDeviceConfig,
VhostMode, VmConfig, VsockConfig,
VdpaConfig, VhostMode, VmConfig, VsockConfig,
};
use crate::device_tree::{DeviceNode, DeviceTree};
#[cfg(feature = "kvm")]
@ -89,7 +89,7 @@ use vfio_ioctls::{VfioContainer, VfioDevice};
use virtio_devices::transport::VirtioPciDevice;
use virtio_devices::transport::VirtioTransport;
use virtio_devices::vhost_user::VhostUserConfig;
use virtio_devices::{AccessPlatformMapping, VirtioMemMappingSource};
use virtio_devices::{AccessPlatformMapping, VdpaDmaMapping, VirtioMemMappingSource};
use virtio_devices::{Endpoint, IommuMapping};
use virtio_devices::{VirtioSharedMemory, VirtioSharedMemoryList};
use vm_allocator::{AddressAllocator, SystemAllocator};
@ -133,6 +133,7 @@ const BALLOON_DEVICE_NAME: &str = "_balloon";
const NET_DEVICE_NAME_PREFIX: &str = "_net";
const PMEM_DEVICE_NAME_PREFIX: &str = "_pmem";
const RNG_DEVICE_NAME: &str = "_rng";
const VDPA_DEVICE_NAME_PREFIX: &str = "_vdpa";
const VSOCK_DEVICE_NAME_PREFIX: &str = "_vsock";
const WATCHDOG_DEVICE_NAME: &str = "_watchdog";
@ -176,9 +177,15 @@ pub enum DeviceManagerError {
/// Cannot create virtio-pmem device
CreateVirtioPmem(io::Error),
/// Cannot create vDPA device
CreateVdpa(virtio_devices::vdpa::Error),
/// Cannot create virtio-vsock device
CreateVirtioVsock(io::Error),
/// Failed to convert Path to &str for the vDPA device.
CreateVdpaConvertPath,
/// Failed to convert Path to &str for the virtio-vsock device.
CreateVsockConvertPath,
@ -1950,6 +1957,9 @@ impl DeviceManager {
// Add virtio-watchdog device
devices.append(&mut self.make_virtio_watchdog_devices()?);
// Add vDPA devices if required
devices.append(&mut self.make_vdpa_devices()?);
Ok(devices)
}
@ -2893,6 +2903,69 @@ impl DeviceManager {
Ok(devices)
}
fn make_vdpa_device(
&mut self,
vdpa_cfg: &mut VdpaConfig,
) -> DeviceManagerResult<MetaVirtioDevice> {
let id = if let Some(id) = &vdpa_cfg.id {
id.clone()
} else {
let id = self.next_device_name(VDPA_DEVICE_NAME_PREFIX)?;
vdpa_cfg.id = Some(id.clone());
id
};
info!("Creating vDPA device: {:?}", vdpa_cfg);
let device_path = vdpa_cfg
.path
.to_str()
.ok_or(DeviceManagerError::CreateVdpaConvertPath)?;
let vdpa_device = Arc::new(Mutex::new(
virtio_devices::Vdpa::new(
id.clone(),
device_path,
self.memory_manager.lock().unwrap().guest_memory(),
vdpa_cfg.num_queues as u16,
)
.map_err(DeviceManagerError::CreateVdpa)?,
));
// Create the DMA handler that is required by the vDPA device
let vdpa_mapping = Arc::new(VdpaDmaMapping::new(
Arc::clone(&vdpa_device),
Arc::new(self.memory_manager.lock().unwrap().guest_memory()),
));
self.device_tree
.lock()
.unwrap()
.insert(id.clone(), device_node!(id));
Ok(MetaVirtioDevice {
virtio_device: vdpa_device as Arc<Mutex<dyn virtio_devices::VirtioDevice>>,
iommu: false,
id,
pci_segment: vdpa_cfg.pci_segment,
dma_handler: Some(vdpa_mapping),
})
}
fn make_vdpa_devices(&mut self) -> DeviceManagerResult<Vec<MetaVirtioDevice>> {
let mut devices = Vec::new();
// Add vdpa if required
let mut vdpa_devices = self.config.lock().unwrap().vdpa.clone();
if let Some(vdpa_list_cfg) = &mut vdpa_devices {
for vdpa_cfg in vdpa_list_cfg.iter_mut() {
devices.push(self.make_vdpa_device(vdpa_cfg)?);
}
}
self.config.lock().unwrap().vdpa = vdpa_devices;
Ok(devices)
}
fn next_device_name(&mut self, prefix: &str) -> DeviceManagerResult<String> {
let start_id = self.device_id_cnt;
loop {

View File

@ -86,6 +86,27 @@ const VFIO_IOMMU_MAP_DMA: u64 = 0x3b71;
const VFIO_IOMMU_UNMAP_DMA: u64 = 0x3b72;
const VFIO_DEVICE_IOEVENTFD: u64 = 0x3b74;
// See include/uapi/linux/vhost.h in the kernel code
const VHOST_GET_FEATURES: u64 = 0x8008af00;
const VHOST_SET_FEATURES: u64 = 0x4008af00;
const VHOST_SET_OWNER: u64 = 0xaf01;
const VHOST_SET_VRING_NUM: u64 = 0x4008af10;
const VHOST_SET_VRING_ADDR: u64 = 0x4028af11;
const VHOST_SET_VRING_BASE: u64 = 0x4008af12;
const VHOST_SET_VRING_KICK: u64 = 0x4008af20;
const VHOST_SET_VRING_CALL: u64 = 0x4008af21;
const VHOST_SET_BACKEND_FEATURES: u64 = 0x4008af25;
const VHOST_GET_BACKEND_FEATURES: u64 = 0x8008af26;
const VHOST_VDPA_GET_DEVICE_ID: u64 = 0x8004af70;
const VHOST_VDPA_GET_STATUS: u64 = 0x8001af71;
const VHOST_VDPA_SET_STATUS: u64 = 0x4001af72;
const VHOST_VDPA_GET_CONFIG: u64 = 0x8008af73;
const VHOST_VDPA_SET_CONFIG: u64 = 0x4008af74;
const VHOST_VDPA_SET_VRING_ENABLE: u64 = 0x4008af75;
const VHOST_VDPA_GET_VRING_NUM: u64 = 0x8002af76;
const VHOST_VDPA_SET_CONFIG_CALL: u64 = 0x4004af77;
const VHOST_VDPA_GET_IOVA_RANGE: u64 = 0x8010af78;
// See include/uapi/linux/kvm.h in the kernel code.
#[cfg(feature = "kvm")]
mod kvm {
@ -262,6 +283,30 @@ fn create_vmm_ioctl_seccomp_rule_common() -> Result<Vec<SeccompRule>, BackendErr
and![Cond::new(1, ArgLen::Dword, Eq, VFIO_IOMMU_MAP_DMA)?],
and![Cond::new(1, ArgLen::Dword, Eq, VFIO_IOMMU_UNMAP_DMA)?],
and![Cond::new(1, ArgLen::Dword, Eq, VFIO_DEVICE_IOEVENTFD)?],
and![Cond::new(1, ArgLen::Dword, Eq, VHOST_GET_FEATURES)?],
and![Cond::new(1, ArgLen::Dword, Eq, VHOST_SET_FEATURES)?],
and![Cond::new(1, ArgLen::Dword, Eq, VHOST_SET_OWNER)?],
and![Cond::new(1, ArgLen::Dword, Eq, VHOST_SET_VRING_NUM)?],
and![Cond::new(1, ArgLen::Dword, Eq, VHOST_SET_VRING_ADDR)?],
and![Cond::new(1, ArgLen::Dword, Eq, VHOST_SET_VRING_BASE)?],
and![Cond::new(1, ArgLen::Dword, Eq, VHOST_SET_VRING_KICK)?],
and![Cond::new(1, ArgLen::Dword, Eq, VHOST_SET_VRING_CALL)?],
and![Cond::new(1, ArgLen::Dword, Eq, VHOST_SET_BACKEND_FEATURES)?],
and![Cond::new(1, ArgLen::Dword, Eq, VHOST_GET_BACKEND_FEATURES)?],
and![Cond::new(1, ArgLen::Dword, Eq, VHOST_VDPA_GET_DEVICE_ID)?],
and![Cond::new(1, ArgLen::Dword, Eq, VHOST_VDPA_GET_STATUS)?],
and![Cond::new(1, ArgLen::Dword, Eq, VHOST_VDPA_SET_STATUS)?],
and![Cond::new(1, ArgLen::Dword, Eq, VHOST_VDPA_GET_CONFIG)?],
and![Cond::new(1, ArgLen::Dword, Eq, VHOST_VDPA_SET_CONFIG)?],
and![Cond::new(
1,
ArgLen::Dword,
Eq,
VHOST_VDPA_SET_VRING_ENABLE
)?],
and![Cond::new(1, ArgLen::Dword, Eq, VHOST_VDPA_GET_VRING_NUM)?],
and![Cond::new(1, ArgLen::Dword, Eq, VHOST_VDPA_SET_CONFIG_CALL)?],
and![Cond::new(1, ArgLen::Dword, Eq, VHOST_VDPA_GET_IOVA_RANGE)?],
];
let hypervisor_rules = create_vmm_ioctl_seccomp_rule_hypervisor()?;
@ -583,6 +628,15 @@ fn create_vcpu_ioctl_seccomp_rule() -> Result<Vec<SeccompRule>, BackendError> {
and![Cond::new(1, ArgLen::Dword, Eq, VFIO_DEVICE_SET_IRQS)?],
and![Cond::new(1, ArgLen::Dword, Eq, VFIO_GROUP_UNSET_CONTAINER)?],
and![Cond::new(1, ArgLen::Dword, Eq, VFIO_IOMMU_UNMAP_DMA)?],
and![Cond::new(1, ArgLen::Dword, Eq, VHOST_VDPA_SET_STATUS)?],
and![Cond::new(1, ArgLen::Dword, Eq, VHOST_VDPA_GET_CONFIG)?],
and![Cond::new(1, ArgLen::Dword, Eq, VHOST_VDPA_SET_CONFIG)?],
and![Cond::new(
1,
ArgLen::Dword,
Eq,
VHOST_VDPA_SET_VRING_ENABLE
)?],
];
let hypervisor_rules = create_vcpu_ioctl_seccomp_rule_hypervisor()?;