vhost_kern: add IOTLB message support
Implement VhostIotlbBackend trait for vhost_kern handling both vhost_msg and vhost_msg_v2 messages according to acked backend features. Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
This commit is contained in:
parent
a2bc456bed
commit
58680d5826
1 changed files with 125 additions and 3 deletions
|
|
@ -11,15 +11,18 @@
|
|||
//! communicate with userspace applications. This sub module provides ioctl based interfaces to
|
||||
//! control the in-kernel net, scsi, vsock vhost drivers.
|
||||
|
||||
use std::mem;
|
||||
use std::os::unix::io::{AsRawFd, RawFd};
|
||||
|
||||
use libc::{c_void, ssize_t, write};
|
||||
|
||||
use vm_memory::{Address, GuestAddress, GuestAddressSpace, GuestMemory, GuestUsize};
|
||||
use vmm_sys_util::eventfd::EventFd;
|
||||
use vmm_sys_util::ioctl::{ioctl, ioctl_with_mut_ref, ioctl_with_ptr, ioctl_with_ref};
|
||||
|
||||
use super::{
|
||||
Error, Result, VhostBackend, VhostUserDirtyLogRegion, VhostUserMemoryRegionInfo,
|
||||
VringConfigData, VHOST_MAX_MEMORY_REGIONS,
|
||||
Error, Result, VhostBackend, VhostIotlbBackend, VhostIotlbMsg, VhostIotlbMsgParser,
|
||||
VhostUserDirtyLogRegion, VhostUserMemoryRegionInfo, VringConfigData, VHOST_MAX_MEMORY_REGIONS,
|
||||
};
|
||||
|
||||
pub mod vhost_binding;
|
||||
|
|
@ -37,6 +40,15 @@ fn ioctl_result<T>(rc: i32, res: T) -> Result<T> {
|
|||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn io_result<T>(rc: isize, res: T) -> Result<T> {
|
||||
if rc < 0 {
|
||||
Err(Error::IOError(std::io::Error::last_os_error()))
|
||||
} else {
|
||||
Ok(res)
|
||||
}
|
||||
}
|
||||
|
||||
/// Represent an in-kernel vhost device backend.
|
||||
pub trait VhostKernBackend: AsRawFd {
|
||||
/// Associated type to access guest memory.
|
||||
|
|
@ -314,4 +326,114 @@ pub trait VhostKernFeatures: Sized + AsRawFd {
|
|||
|
||||
ioctl_result(ret, ())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Handle IOTLB messeges for in-kernel vhost device backend.
|
||||
impl<I: VhostKernBackend + VhostKernFeatures> VhostIotlbBackend for I {
|
||||
/// Send an IOTLB message to the in-kernel vhost backend.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `msg` - IOTLB message to send.
|
||||
fn send_iotlb_msg(&self, msg: &VhostIotlbMsg) -> Result<()> {
|
||||
let ret: ssize_t;
|
||||
|
||||
if self.get_backend_features_acked() & (1 << VHOST_BACKEND_F_IOTLB_MSG_V2) != 0 {
|
||||
let mut msg_v2 = vhost_msg_v2 {
|
||||
type_: VHOST_IOTLB_MSG_V2,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
msg_v2.__bindgen_anon_1.iotlb.iova = msg.iova;
|
||||
msg_v2.__bindgen_anon_1.iotlb.size = msg.size;
|
||||
msg_v2.__bindgen_anon_1.iotlb.uaddr = msg.userspace_addr;
|
||||
msg_v2.__bindgen_anon_1.iotlb.perm = msg.perm as u8;
|
||||
msg_v2.__bindgen_anon_1.iotlb.type_ = msg.msg_type as u8;
|
||||
|
||||
ret = unsafe {
|
||||
write(
|
||||
self.as_raw_fd(),
|
||||
&msg_v2 as *const vhost_msg_v2 as *const c_void,
|
||||
mem::size_of::<vhost_msg_v2>(),
|
||||
)
|
||||
};
|
||||
} else {
|
||||
let mut msg_v1 = vhost_msg {
|
||||
type_: VHOST_IOTLB_MSG,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
msg_v1.__bindgen_anon_1.iotlb.iova = msg.iova;
|
||||
msg_v1.__bindgen_anon_1.iotlb.size = msg.size;
|
||||
msg_v1.__bindgen_anon_1.iotlb.uaddr = msg.userspace_addr;
|
||||
msg_v1.__bindgen_anon_1.iotlb.perm = msg.perm as u8;
|
||||
msg_v1.__bindgen_anon_1.iotlb.type_ = msg.msg_type as u8;
|
||||
|
||||
ret = unsafe {
|
||||
write(
|
||||
self.as_raw_fd(),
|
||||
&msg_v1 as *const vhost_msg as *const c_void,
|
||||
mem::size_of::<vhost_msg>(),
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
io_result(ret, ())
|
||||
}
|
||||
|
||||
/// Parse a buffer received from the in-kernel vhost backend and fill a VhostIotlbMsg.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `buffer` - Buffer containing the raw data received from the in-kernel vhost backend.
|
||||
/// * `msg` - IOTLB message parsed.
|
||||
fn parse_iotlb_msg<T: Sized + VhostIotlbMsgParser>(
|
||||
&self,
|
||||
buffer: &T,
|
||||
msg: &mut VhostIotlbMsg,
|
||||
) -> Result<()> {
|
||||
buffer.parse(msg)
|
||||
}
|
||||
}
|
||||
|
||||
impl VhostIotlbMsgParser for vhost_msg {
|
||||
fn parse(&self, msg: &mut VhostIotlbMsg) -> Result<()> {
|
||||
if self.type_ != VHOST_IOTLB_MSG {
|
||||
return Err(Error::InvalidIotlbMsg);
|
||||
}
|
||||
|
||||
unsafe {
|
||||
if self.__bindgen_anon_1.iotlb.type_ == 0 {
|
||||
return Err(Error::InvalidIotlbMsg);
|
||||
}
|
||||
|
||||
msg.iova = self.__bindgen_anon_1.iotlb.iova;
|
||||
msg.size = self.__bindgen_anon_1.iotlb.size;
|
||||
msg.userspace_addr = self.__bindgen_anon_1.iotlb.uaddr;
|
||||
msg.perm = mem::transmute(self.__bindgen_anon_1.iotlb.perm);
|
||||
msg.msg_type = mem::transmute(self.__bindgen_anon_1.iotlb.type_);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl VhostIotlbMsgParser for vhost_msg_v2 {
|
||||
fn parse(&self, msg: &mut VhostIotlbMsg) -> Result<()> {
|
||||
if self.type_ != VHOST_IOTLB_MSG_V2 {
|
||||
return Err(Error::InvalidIotlbMsg);
|
||||
}
|
||||
|
||||
unsafe {
|
||||
if self.__bindgen_anon_1.iotlb.type_ == 0 {
|
||||
return Err(Error::InvalidIotlbMsg);
|
||||
}
|
||||
|
||||
msg.iova = self.__bindgen_anon_1.iotlb.iova;
|
||||
msg.size = self.__bindgen_anon_1.iotlb.size;
|
||||
msg.userspace_addr = self.__bindgen_anon_1.iotlb.uaddr;
|
||||
msg.perm = mem::transmute(self.__bindgen_anon_1.iotlb.perm);
|
||||
msg.msg_type = mem::transmute(self.__bindgen_anon_1.iotlb.type_);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue