From 960578efc4e85af362ac5dc033df789055ea2065 Mon Sep 17 00:00:00 2001 From: Alex Zenla Date: Sat, 14 Dec 2024 18:00:11 -0500 Subject: [PATCH] feat(xencall): improve asynchronous support (#430) --- crates/xen/xencall/src/error.rs | 4 ++ crates/xen/xencall/src/lib.rs | 77 +++++++++++++++++++-------------- crates/xen/xencall/src/sys.rs | 10 +++++ 3 files changed, 59 insertions(+), 32 deletions(-) diff --git a/crates/xen/xencall/src/error.rs b/crates/xen/xencall/src/error.rs index f6633c2..7e7a1ac 100644 --- a/crates/xen/xencall/src/error.rs +++ b/crates/xen/xencall/src/error.rs @@ -1,5 +1,7 @@ use std::io; +use tokio::task::JoinError; + #[derive(thiserror::Error, Debug)] pub enum Error { #[error("version of xen is not supported")] @@ -16,6 +18,8 @@ pub enum Error { MmapBatchFailed(nix::errno::Errno), #[error("specified value is too long")] ValueTooLong, + #[error("failed to join async task: {0}")] + JoinError(JoinError), } pub type Result = std::result::Result; diff --git a/crates/xen/xencall/src/lib.rs b/crates/xen/xencall/src/lib.rs index 4898607..22d9285 100644 --- a/crates/xen/xencall/src/lib.rs +++ b/crates/xen/xencall/src/lib.rs @@ -35,7 +35,6 @@ use sys::{ XEN_SYSCTL_PHYSINFO, XEN_SYSCTL_PM_OP, XEN_SYSCTL_PM_OP_DISABLE_TURBO, XEN_SYSCTL_PM_OP_ENABLE_TURBO, XEN_SYSCTL_PM_OP_SET_CPUFREQ_GOV, XEN_SYSCTL_READCONSOLE, }; -use tokio::sync::Semaphore; use tokio::time::sleep; use std::fs::{File, OpenOptions}; @@ -46,7 +45,6 @@ use std::slice; #[derive(Clone)] pub struct XenCall { pub handle: Arc, - semaphore: Arc, domctl_interface_version: u32, sysctl_interface_version: u32, } @@ -62,7 +60,6 @@ impl XenCall { let sysctl_interface_version = XenCall::detect_sysctl_interface_version(&handle)?; Ok(XenCall { handle: Arc::new(handle), - semaphore: Arc::new(Semaphore::new(1)), domctl_interface_version, sysctl_interface_version, }) @@ -119,7 +116,6 @@ impl XenCall { } pub async fn mmap(&self, addr: u64, len: u64) -> Option { - let _permit = self.semaphore.acquire().await.ok()?; trace!( "call fd={} mmap addr={:#x} len={}", self.handle.as_raw_fd(), @@ -127,14 +123,20 @@ impl XenCall { len ); unsafe { - let ptr = mmap( - addr as *mut c_void, - len as usize, - PROT_READ | PROT_WRITE, - MAP_SHARED, - self.handle.as_raw_fd(), - 0, - ); + let handle = self.handle.clone(); + let ptr = tokio::task::spawn_blocking(move || { + mmap( + addr as *mut c_void, + len as usize, + PROT_READ | PROT_WRITE, + MAP_SHARED, + handle.as_raw_fd(), + 0, + ) as u64 + }) + .await + .map_err(Error::JoinError) + .ok()? as *mut c_void; if ptr == MAP_FAILED { None } else { @@ -151,18 +153,22 @@ impl XenCall { } pub async fn hypercall(&self, op: c_ulong, arg: [c_ulong; 5]) -> Result { - let _permit = self.semaphore.acquire().await?; trace!( "call fd={} hypercall op={:#x} arg={:?}", self.handle.as_raw_fd(), op, arg ); - unsafe { + + let handle = self.handle.clone(); + tokio::task::spawn_blocking(move || unsafe { let mut call = Hypercall { op, arg }; - let result = sys::hypercall(self.handle.as_raw_fd(), &mut call)?; - Ok(result as c_long) - } + sys::hypercall(handle.as_raw_fd(), &mut call) + .map(|x| x as c_long) + .map_err(|e| e.into()) + }) + .await + .map_err(Error::JoinError)? } pub async fn hypercall0(&self, op: c_ulong) -> Result { @@ -234,18 +240,21 @@ impl XenCall { num: u64, addr: u64, ) -> Result<()> { - let _permit = self.semaphore.acquire().await?; - let mut resource = MmapResource { - dom: domid as u16, - typ, - id, - idx, - num, - addr, - }; - unsafe { - sys::mmap_resource(self.handle.as_raw_fd(), &mut resource)?; - } + let handle = self.handle.clone(); + tokio::task::spawn_blocking(move || { + let mut resource = MmapResource { + dom: domid as u16, + typ, + id, + idx, + num, + addr, + }; + + unsafe { sys::mmap_resource(handle.as_raw_fd(), &mut resource) } + }) + .await + .map_err(Error::JoinError)??; Ok(()) } @@ -256,7 +265,6 @@ impl XenCall { addr: u64, mfns: Vec, ) -> Result { - let _permit = self.semaphore.acquire().await?; trace!( "call fd={} mmap_batch domid={} num={} addr={:#x} mfns={:?}", self.handle.as_raw_fd(), @@ -322,7 +330,7 @@ impl XenCall { break; } - let count = result.unwrap(); + let count = result?; if count <= 0 { break; } @@ -330,7 +338,7 @@ impl XenCall { return Ok(paged as c_long); } - Ok(result.unwrap() as c_long) + Ok(result? as c_long) } } @@ -618,6 +626,11 @@ impl XenCall { } pub async fn get_memory_map(&self, max_entries: u32) -> Result> { + trace!( + "fd={} get_memory_map max_entries={}", + self.handle.as_raw_fd(), + max_entries, + ); let mut memory_map = MemoryMap { count: max_entries, buffer: 0, diff --git a/crates/xen/xencall/src/sys.rs b/crates/xen/xencall/src/sys.rs index 049a05d..10e7ae5 100644 --- a/crates/xen/xencall/src/sys.rs +++ b/crates/xen/xencall/src/sys.rs @@ -205,6 +205,16 @@ pub const XEN_DOMCTL_GDBSX_PAUSEVCPU: u32 = 1001; pub const XEN_DOMCTL_GDBSX_UNPAUSEVCPU: u32 = 1002; pub const XEN_DOMCTL_GDBSX_DOMSTATUS: u32 = 1003; +pub const XEN_DOMINF_DYING: u32 = 1u32 << 0; +pub const XEN_DOMINF_HVM_GUEST: u32 = 1u32 << 1; +pub const XEN_DOMINF_SHUTDOWN: u32 = 1u32 << 2; +pub const XEN_DOMINF_PAUSED: u32 = 1u32 << 3; +pub const XEN_DOMINF_BLOCKED: u32 = 1u32 << 4; +pub const XEN_DOMINF_RUNNING: u32 = 1u32 << 5; +pub const XEN_DOMINF_DEBUGGED: u32 = 1u32 << 6; +pub const XEN_DOMINF_XS_DOMAIN: u32 = 1u32 << 7; +pub const XEN_DOMINF_HAP: u32 = 1u32 << 8; + #[repr(C)] #[derive(Copy, Clone)] pub struct DomCtl {