summary refs log tree commit diff
path: root/devices/src/virtio/vhost_user/vu_common_ctrl.rs
diff options
context:
space:
mode:
Diffstat (limited to 'devices/src/virtio/vhost_user/vu_common_ctrl.rs')
-rw-r--r--devices/src/virtio/vhost_user/vu_common_ctrl.rs115
1 files changed, 115 insertions, 0 deletions
diff --git a/devices/src/virtio/vhost_user/vu_common_ctrl.rs b/devices/src/virtio/vhost_user/vu_common_ctrl.rs
new file mode 100644
index 0000000..38b7b4f
--- /dev/null
+++ b/devices/src/virtio/vhost_user/vu_common_ctrl.rs
@@ -0,0 +1,115 @@
+// Copyright 2019 Intel Corporation. All Rights Reserved.
+// SPDX-License-Identifier: Apache-2.0
+
+use libc;
+use libc::EFD_NONBLOCK;
+use std::os::unix::io::AsRawFd;
+use std::vec::Vec;
+use sys_util::{EventFd, GuestMemory};
+
+use vm_memory::{Address, Error as MmapError};
+
+use super::super::Queue;
+use super::{Error, Result};
+use vhost_rs::vhost_user::{Master, VhostUserMaster};
+use vhost_rs::{VhostBackend, VhostUserMemoryRegionInfo, VringConfigData};
+
+#[derive(Debug, Copy, Clone)]
+pub struct VhostUserConfig<'a> {
+    pub sock: &'a str,
+    pub num_queues: usize,
+    pub queue_size: u16,
+}
+
+pub fn setup_vhost_user_vring(
+    vu: &mut Master,
+    mem: &GuestMemory,
+    queues: Vec<Queue>,
+    queue_evts: Vec<EventFd>,
+) -> Result<Vec<(vmm_sys_util::eventfd::EventFd, Queue)>> {
+    let mut regions: Vec<VhostUserMemoryRegionInfo> = Vec::new();
+    mem.with_regions(
+        |_index,
+         region_guest_base,
+         region_mapping_size,
+         region_mapping_as_ptr,
+         region_memfd_offset| {
+            let vhost_user_net_reg = VhostUserMemoryRegionInfo {
+                guest_phys_addr: region_guest_base.0,
+                memory_size: region_mapping_size as u64,
+                userspace_addr: region_mapping_as_ptr as u64,
+                mmap_offset: region_memfd_offset as u64,
+                mmap_handle: mem.as_raw_fd(),
+            };
+
+            regions.push(vhost_user_net_reg);
+
+            Ok(())
+        },
+    )
+    .map_err(Error::VhostUserMemoryRegion)?;
+
+    vu.set_mem_table(regions.as_slice())
+        .map_err(Error::VhostUserSetMemTable)?;
+
+    let mut vu_interrupt_list = Vec::new();
+
+    for (queue_index, queue) in queues.into_iter().enumerate() {
+        vu.set_vring_num(queue_index, queue.max_size)
+            .map_err(Error::VhostUserSetVringNum)?;
+
+        let config_data = VringConfigData {
+            queue_max_size: queue.max_size,
+            queue_size: queue.actual_size(),
+            flags: 0u32,
+            desc_table_addr: mem
+                .get_host_address(queue.desc_table)
+                .map_err(Error::DescriptorTableAddress)? as u64,
+            used_ring_addr: mem
+                .get_host_address(queue.used_ring)
+                .map_err(Error::UsedAddress)? as u64,
+            avail_ring_addr: mem
+                .get_host_address(queue.avail_ring)
+                .map_err(Error::AvailAddress)? as u64,
+            log_addr: None,
+        };
+
+        vu.set_vring_addr(queue_index, &config_data)
+            .map_err(Error::VhostUserSetVringAddr)?;
+        vu.set_vring_base(queue_index, 0u16)
+            .map_err(Error::VhostUserSetVringBase)?;
+
+        let vhost_user_interrupt =
+            vmm_sys_util::eventfd::EventFd::new(EFD_NONBLOCK).map_err(Error::VhostIrqCreate)?;
+        vu.set_vring_call(queue_index, &vhost_user_interrupt)
+            .map_err(Error::VhostUserSetVringCall)?;
+        vu_interrupt_list.push((vhost_user_interrupt, queue));
+
+        vu.set_vring_kick(queue_index, &queue_evts[queue_index])
+            .map_err(Error::VhostUserSetVringKick)?;
+    }
+
+    Ok(vu_interrupt_list)
+}
+
+pub fn setup_vhost_user(
+    vu: &mut Master,
+    mem: &GuestMemory,
+    queues: Vec<Queue>,
+    queue_evts: Vec<EventFd>,
+    acked_features: u64,
+) -> Result<Vec<(vmm_sys_util::eventfd::EventFd, Queue)>> {
+    for i in 0..queues.len() {
+        vu.set_vring_enable(i, true)
+            .map_err(Error::VhostUserSetVringEnable)?;
+    }
+
+    let backend_features = vu.get_features().unwrap();
+    vu.set_features(acked_features & backend_features)
+        .map_err(Error::VhostUserSetFeatures)?;
+
+    match setup_vhost_user_vring(vu, mem, queues, queue_evts) {
+        Ok(vu_interrupt_list) => Ok(vu_interrupt_list),
+        Err(_) => Err(Error::VhostUserSetupVringFailed),
+    }
+}