Skip to content

Commit 58680d5

Browse files
stefano-garzarellajiangliu
authored andcommitted
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 <[email protected]>
1 parent a2bc456 commit 58680d5

File tree

1 file changed

+125
-3
lines changed

1 file changed

+125
-3
lines changed

src/vhost_kern/mod.rs

Lines changed: 125 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,18 @@
1111
//! communicate with userspace applications. This sub module provides ioctl based interfaces to
1212
//! control the in-kernel net, scsi, vsock vhost drivers.
1313
14+
use std::mem;
1415
use std::os::unix::io::{AsRawFd, RawFd};
1516

17+
use libc::{c_void, ssize_t, write};
18+
1619
use vm_memory::{Address, GuestAddress, GuestAddressSpace, GuestMemory, GuestUsize};
1720
use vmm_sys_util::eventfd::EventFd;
1821
use vmm_sys_util::ioctl::{ioctl, ioctl_with_mut_ref, ioctl_with_ptr, ioctl_with_ref};
1922

2023
use super::{
21-
Error, Result, VhostBackend, VhostUserDirtyLogRegion, VhostUserMemoryRegionInfo,
22-
VringConfigData, VHOST_MAX_MEMORY_REGIONS,
24+
Error, Result, VhostBackend, VhostIotlbBackend, VhostIotlbMsg, VhostIotlbMsgParser,
25+
VhostUserDirtyLogRegion, VhostUserMemoryRegionInfo, VringConfigData, VHOST_MAX_MEMORY_REGIONS,
2326
};
2427

2528
pub mod vhost_binding;
@@ -37,6 +40,15 @@ fn ioctl_result<T>(rc: i32, res: T) -> Result<T> {
3740
}
3841
}
3942

43+
#[inline]
44+
fn io_result<T>(rc: isize, res: T) -> Result<T> {
45+
if rc < 0 {
46+
Err(Error::IOError(std::io::Error::last_os_error()))
47+
} else {
48+
Ok(res)
49+
}
50+
}
51+
4052
/// Represent an in-kernel vhost device backend.
4153
pub trait VhostKernBackend: AsRawFd {
4254
/// Associated type to access guest memory.
@@ -314,4 +326,114 @@ pub trait VhostKernFeatures: Sized + AsRawFd {
314326

315327
ioctl_result(ret, ())
316328
}
317-
}
329+
}
330+
331+
/// Handle IOTLB messeges for in-kernel vhost device backend.
332+
impl<I: VhostKernBackend + VhostKernFeatures> VhostIotlbBackend for I {
333+
/// Send an IOTLB message to the in-kernel vhost backend.
334+
///
335+
/// # Arguments
336+
/// * `msg` - IOTLB message to send.
337+
fn send_iotlb_msg(&self, msg: &VhostIotlbMsg) -> Result<()> {
338+
let ret: ssize_t;
339+
340+
if self.get_backend_features_acked() & (1 << VHOST_BACKEND_F_IOTLB_MSG_V2) != 0 {
341+
let mut msg_v2 = vhost_msg_v2 {
342+
type_: VHOST_IOTLB_MSG_V2,
343+
..Default::default()
344+
};
345+
346+
msg_v2.__bindgen_anon_1.iotlb.iova = msg.iova;
347+
msg_v2.__bindgen_anon_1.iotlb.size = msg.size;
348+
msg_v2.__bindgen_anon_1.iotlb.uaddr = msg.userspace_addr;
349+
msg_v2.__bindgen_anon_1.iotlb.perm = msg.perm as u8;
350+
msg_v2.__bindgen_anon_1.iotlb.type_ = msg.msg_type as u8;
351+
352+
ret = unsafe {
353+
write(
354+
self.as_raw_fd(),
355+
&msg_v2 as *const vhost_msg_v2 as *const c_void,
356+
mem::size_of::<vhost_msg_v2>(),
357+
)
358+
};
359+
} else {
360+
let mut msg_v1 = vhost_msg {
361+
type_: VHOST_IOTLB_MSG,
362+
..Default::default()
363+
};
364+
365+
msg_v1.__bindgen_anon_1.iotlb.iova = msg.iova;
366+
msg_v1.__bindgen_anon_1.iotlb.size = msg.size;
367+
msg_v1.__bindgen_anon_1.iotlb.uaddr = msg.userspace_addr;
368+
msg_v1.__bindgen_anon_1.iotlb.perm = msg.perm as u8;
369+
msg_v1.__bindgen_anon_1.iotlb.type_ = msg.msg_type as u8;
370+
371+
ret = unsafe {
372+
write(
373+
self.as_raw_fd(),
374+
&msg_v1 as *const vhost_msg as *const c_void,
375+
mem::size_of::<vhost_msg>(),
376+
)
377+
};
378+
}
379+
380+
io_result(ret, ())
381+
}
382+
383+
/// Parse a buffer received from the in-kernel vhost backend and fill a VhostIotlbMsg.
384+
///
385+
/// # Arguments
386+
/// * `buffer` - Buffer containing the raw data received from the in-kernel vhost backend.
387+
/// * `msg` - IOTLB message parsed.
388+
fn parse_iotlb_msg<T: Sized + VhostIotlbMsgParser>(
389+
&self,
390+
buffer: &T,
391+
msg: &mut VhostIotlbMsg,
392+
) -> Result<()> {
393+
buffer.parse(msg)
394+
}
395+
}
396+
397+
impl VhostIotlbMsgParser for vhost_msg {
398+
fn parse(&self, msg: &mut VhostIotlbMsg) -> Result<()> {
399+
if self.type_ != VHOST_IOTLB_MSG {
400+
return Err(Error::InvalidIotlbMsg);
401+
}
402+
403+
unsafe {
404+
if self.__bindgen_anon_1.iotlb.type_ == 0 {
405+
return Err(Error::InvalidIotlbMsg);
406+
}
407+
408+
msg.iova = self.__bindgen_anon_1.iotlb.iova;
409+
msg.size = self.__bindgen_anon_1.iotlb.size;
410+
msg.userspace_addr = self.__bindgen_anon_1.iotlb.uaddr;
411+
msg.perm = mem::transmute(self.__bindgen_anon_1.iotlb.perm);
412+
msg.msg_type = mem::transmute(self.__bindgen_anon_1.iotlb.type_);
413+
}
414+
415+
Ok(())
416+
}
417+
}
418+
419+
impl VhostIotlbMsgParser for vhost_msg_v2 {
420+
fn parse(&self, msg: &mut VhostIotlbMsg) -> Result<()> {
421+
if self.type_ != VHOST_IOTLB_MSG_V2 {
422+
return Err(Error::InvalidIotlbMsg);
423+
}
424+
425+
unsafe {
426+
if self.__bindgen_anon_1.iotlb.type_ == 0 {
427+
return Err(Error::InvalidIotlbMsg);
428+
}
429+
430+
msg.iova = self.__bindgen_anon_1.iotlb.iova;
431+
msg.size = self.__bindgen_anon_1.iotlb.size;
432+
msg.userspace_addr = self.__bindgen_anon_1.iotlb.uaddr;
433+
msg.perm = mem::transmute(self.__bindgen_anon_1.iotlb.perm);
434+
msg.msg_type = mem::transmute(self.__bindgen_anon_1.iotlb.type_);
435+
}
436+
437+
Ok(())
438+
}
439+
}

0 commit comments

Comments
 (0)