This adds support to issue the set ioeventfd ioctl via the privcmd file.
Signed-off-by: Viresh Kumar viresh.kumar@linaro.org --- V3: Privatize config_ioeventfd() V2: Change based on merged kernel code.
crates/xen-ioctls/Cargo.toml | 1 + crates/xen-ioctls/src/private.rs | 15 +++++- crates/xen-ioctls/src/xdm/types.rs | 18 +++++++ crates/xen-ioctls/src/xdm/xdm.rs | 82 ++++++++++++++++++++++++++++++ 4 files changed, 115 insertions(+), 1 deletion(-)
diff --git a/crates/xen-ioctls/Cargo.toml b/crates/xen-ioctls/Cargo.toml index a9e26f9fe0e0..bc4d21e5847b 100644 --- a/crates/xen-ioctls/Cargo.toml +++ b/crates/xen-ioctls/Cargo.toml @@ -11,3 +11,4 @@ edition = "2018" [dependencies] libc = ">=0.2.95" vmm-sys-util = ">=0.9.0" +xen-bindings = { path = "../xen-bindings" } diff --git a/crates/xen-ioctls/src/private.rs b/crates/xen-ioctls/src/private.rs index 50833e750f2d..13cb3fc8c669 100644 --- a/crates/xen-ioctls/src/private.rs +++ b/crates/xen-ioctls/src/private.rs @@ -14,7 +14,9 @@ use std::io::Error; use std::os::unix::io::AsRawFd; use vmm_sys_util::ioctl::{_IOC_NONE, _IOC_WRITE};
-use crate::xdm::types::{PrivcmdDeviceModelIrqFd, PrivcmdDeviceModelOp}; +use crate::xdm::types::{ + PrivcmdDeviceModelIoeventFd, PrivcmdDeviceModelIrqFd, PrivcmdDeviceModelOp, +}; use crate::xfm::types::{PrivCmdMmapBatchV2, PrivCmdMmapResource};
pub const PAGE_SHIFT: u32 = 12; @@ -84,6 +86,17 @@ ioctl_ioc_nr!( std::mem::size_of::<PrivcmdDeviceModelIrqFd>() as u32 );
+/* + * #define IOCTL_PRIVCMD_IOEVENTFD _IOW('P', 9, privcmd_ioeventfd_t) + */ +ioctl_ioc_nr!( + IOCTL_PRIVCMD_IOEVENTFD, + _IOC_WRITE, + XEN_PRIVCMD_TYPE, + 9 as u32, + std::mem::size_of::<PrivcmdDeviceModelIoeventFd>() as u32 +); + pub const HYPERCALL_EVTCHN: &str = "/dev/xen/evtchn"; pub const HYPERCALL_PRIVCMD: &str = "/dev/xen/privcmd"; pub const HYPERCALL_BUFFER_FILE: &str = "/dev/xen/hypercall"; diff --git a/crates/xen-ioctls/src/xdm/types.rs b/crates/xen-ioctls/src/xdm/types.rs index b000a68f0cf1..963583e34b97 100644 --- a/crates/xen-ioctls/src/xdm/types.rs +++ b/crates/xen-ioctls/src/xdm/types.rs @@ -157,3 +157,21 @@ pub struct PrivcmdDeviceModelIrqFd { pub domid: u16, pub pad: [u8; 2], } + +pub const PRIVCMD_IOEVENTFD_FLAG_DEASSIGN: u32 = 1; + +#[repr(C)] +#[derive(Debug, Copy, Clone)] +// tools/include/xen-sys/Linux/privcmd.h::privcmd_ioeventfd +pub struct PrivcmdDeviceModelIoeventFd { + pub ioreq: *mut c_void, + pub ports: *const u32, + pub addr: u64, + pub addr_len: u32, + pub event_fd: u32, + pub vcpus: u32, + pub vq: u32, + pub flags: u32, + pub domid: u16, + pub pad: [u8; 2], +} diff --git a/crates/xen-ioctls/src/xdm/xdm.rs b/crates/xen-ioctls/src/xdm/xdm.rs index 06b589967dde..7a48ec63ac1f 100644 --- a/crates/xen-ioctls/src/xdm/xdm.rs +++ b/crates/xen-ioctls/src/xdm/xdm.rs @@ -17,6 +17,8 @@ use std::os::unix::io::AsRawFd;
use vmm_sys_util::eventfd::EventFd;
+use xen_bindings::bindings::ioreq; + #[cfg(target_arch = "aarch64")] use crate::aarch64::types::*; #[cfg(target_arch = "x86_64")] @@ -307,4 +309,84 @@ impl XenDeviceModelHandle { ) -> Result<(), std::io::Error> { self.config_irqfd(fd, domid, irq, level, PRIVCMD_IRQFD_FLAG_DEASSIGN) } + + fn config_ioeventfd( + &self, + kick: &EventFd, + ioreq: &mut ioreq, + ports: &[u32], + addr: u64, + addr_len: u32, + vq: u32, + vcpus: u32, + domid: u16, + flags: u32, + ) -> Result<(), std::io::Error> { + let mut ioeventfd = PrivcmdDeviceModelIoeventFd { + ioreq: ioreq as *mut _ as *mut c_void, + ports: ports as *const _ as *const u32, + addr, + addr_len, + event_fd: kick.as_raw_fd() as u32, + vcpus, + vq, + flags, + domid, + pad: [0; 2], + }; + + let ret = unsafe { + // The expression "&mut ioeventfd as *mut _" creates a reference to ioeventfd before casting it + // to a *mut c_void. + ioctl( + self.fd.as_raw_fd(), + IOCTL_PRIVCMD_IOEVENTFD(), + &mut ioeventfd as *mut _ as *mut c_void, + ) + }; + + if ret < 0 { + return Err(Error::last_os_error()); + } + + Ok(()) + } + + pub fn set_ioeventfd( + &self, + kick: &EventFd, + ioreq: &mut ioreq, + ports: &[u32], + addr: u64, + addr_len: u32, + vq: u32, + vcpus: u32, + domid: u16, + ) -> Result<(), std::io::Error> { + self.config_ioeventfd(kick, ioreq, ports, addr, addr_len, vq, vcpus, domid, 0) + } + + pub fn clear_ioeventfd( + &self, + kick: &EventFd, + ioreq: &mut ioreq, + ports: &[u32], + addr: u64, + addr_len: u32, + vq: u32, + vcpus: u32, + domid: u16, + ) -> Result<(), std::io::Error> { + self.config_ioeventfd( + kick, + ioreq, + ports, + addr, + addr_len, + vq, + vcpus, + domid, + PRIVCMD_IOEVENTFD_FLAG_DEASSIGN, + ) + } }