diff --git a/Cargo.toml b/Cargo.toml index 5b803b4..ca7e713 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,4 +10,4 @@ description = "Rust bindings for Xen's xenctrl library" license = "GPL-3.0-only" [dependencies] -xenctrl-sys = { git = "https://github.com/Wenzel/xenctrl-sys" } +xenctrl-sys = { git = "https://github.com/Wenzel/xenctrl-sys.git" } diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 0000000..1b80af3 --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1,6 @@ +edition = "2018" +indent_style = "block" +format_strings = true +merge_imports = true +reorder_imports = true +wrap_comments = true diff --git a/src/consts.rs b/src/consts.rs new file mode 100644 index 0000000..d519d29 --- /dev/null +++ b/src/consts.rs @@ -0,0 +1,10 @@ +pub const PAGE_SHIFT: u32 = xenctrl_sys::XC_PAGE_SHIFT; +pub const PAGE_SIZE: u32 = xenctrl_sys::XC_PAGE_SIZE; +pub const PAGE_MASK: i32 = xenctrl_sys::XC_PAGE_MASK; + +pub const CORE_MAGIC: u32 = xenctrl_sys::XC_CORE_MAGIC; +pub const CORE_MAGIC_HVM: u32 = xenctrl_sys::XC_CORE_MAGIC_HVM; + +pub const CPUPOOL_POOLID_ANY: u32 = xenctrl_sys::XC_CPUPOOL_POOLID_ANY; + +pub const MAX_ERROR_MSG_LEN: u32 = xenctrl_sys::XC_MAX_ERROR_MSG_LEN; diff --git a/src/error.rs b/src/error.rs new file mode 100644 index 0000000..e9e1159 --- /dev/null +++ b/src/error.rs @@ -0,0 +1,38 @@ +use std::{ + error, ffi, + fmt::{self, Debug, Display, Formatter}, +}; + +use xenctrl_sys::{xc_error_code, xc_error_code_to_desc}; + +#[derive(Copy, Clone)] +pub struct Error(xc_error_code); + +impl Error { + pub fn new(code: xc_error_code) -> Self { + Self(code) + } + + pub fn desc(self) -> &'static str { + unsafe { + let desc = xc_error_code_to_desc(self.0 as _); + ffi::CStr::from_ptr(desc).to_str().unwrap() + } + } +} + +impl Display for Error { + #[inline] + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.desc()) + } +} + +impl Debug for Error { + #[inline] + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.desc()) + } +} + +impl error::Error for Error {} diff --git a/src/lib.rs b/src/lib.rs index f8ddb05..0341ea0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,90 +1,117 @@ +pub mod error; +pub mod support; +pub mod consts; + +#[macro_use] +mod macros; + extern crate xenctrl_sys; -use std::io::Error; -use std::ptr::{null_mut}; -use std::os::raw::{c_void, c_ulong}; +use std::{ + mem, + ptr::{null_mut, NonNull}, +}; + +use xenctrl_sys::{ + xc_clear_last_error, xc_domain_maximum_gpfn, xc_domain_pause, xc_domain_unpause, xc_error_code, + xc_get_last_error, xc_interface, xc_interface_close, xc_interface_open, xc_monitor_disable, + xc_monitor_enable, xentoollog_logger, +}; -pub const PAGE_SHIFT: u32 = xenctrl_sys::XC_PAGE_SHIFT; -pub const PAGE_SIZE: u32 = xenctrl_sys::XC_PAGE_SIZE; +use error::Error; +use support::PageInfo; + +type Result = std::result::Result; #[derive(Debug)] -pub struct Xc { - handle: *mut xenctrl_sys::xc_interface, - evtchn_port: *mut u32, +pub struct XenControl { + handle: NonNull, + evtchn_port: u32, } -impl Xc { - - pub fn new() -> Result { +impl XenControl { + pub fn new( + logger: Option<&mut xentoollog_logger>, + dombuild_logger: Option<&mut xentoollog_logger>, + open_flags: u32, + ) -> Result { let xc_handle = unsafe { - xenctrl_sys::xc_interface_open(null_mut(), null_mut(), 0) + xc_interface_open( + logger.map_or_else(|| null_mut(), |l| l as *mut _), + dombuild_logger.map_or_else(|| null_mut(), |l| l as *mut _), + open_flags, + ) }; - if xc_handle == null_mut() { - return Err(Error::last_os_error()); - } - Ok(Xc { - handle: xc_handle, - evtchn_port: null_mut() - }) + + NonNull::new(xc_handle) + .ok_or_else(|| Error::new(xc_error_code::XC_INTERNAL_ERROR)) + .map(|handle| XenControl { + handle, + evtchn_port: 0u32, + }) } - pub fn monitor_enable(&self, domid: u32) -> *mut c_void { - unsafe { - xenctrl_sys::xc_monitor_enable(self.handle, domid, self.evtchn_port) - } + pub fn default() -> Result { + Self::new(None, None, 0) } - pub fn monitor_disable(&self, domid: u32) { + pub fn monitor_enable(&mut self, domid: u32) -> Result<&PageInfo> { + let xc = self.handle.as_ptr(); + let ring_page = unsafe { + xc_clear_last_error(xc); + xc_monitor_enable(xc, domid, &mut self.evtchn_port as _) as *const PageInfo + }; + last_error!(xc, &*ring_page) + } + + pub fn monitor_disable(&self, domid: u32) -> Result<()> { + let xc = self.handle.as_ptr(); unsafe { - xenctrl_sys::xc_monitor_disable(self.handle, domid); + xc_clear_last_error(xc); + xc_monitor_disable(xc, domid); }; + last_error!(xc, ()) } - pub fn domain_pause(&self, domid: u32) -> Result<(),&str> { + pub fn domain_pause(&self, domid: u32) -> Result<()> { + let xc = self.handle.as_ptr(); unsafe { - match xenctrl_sys::xc_domain_pause(self.handle, domid) { - 0 => Ok(()), - -1 => Err("Fail to pause domain"), - _ => panic!("unexpected value"), - } - } + xc_clear_last_error(xc); + xc_domain_pause(xc, domid); + }; + last_error!(xc, ()) } - pub fn domain_unpause(&self, domid: u32) -> Result<(),&str> { + pub fn domain_unpause(&self, domid: u32) -> Result<()> { + let xc = self.handle.as_ptr(); unsafe { - match xenctrl_sys::xc_domain_unpause(self.handle, domid) { - 0 => Ok(()), - -1 => Err("Fail to unpause domain"), - _ => panic!("unexpected value"), - } + xc_clear_last_error(xc); + xc_domain_unpause(xc, domid); } + last_error!(xc, ()) } - pub fn domain_maximum_gpfn(&self, domid: u32) -> Result { - let mut max_gpfn: c_ulong = 0; - let ptr_max_gpfn: *mut c_ulong = &mut max_gpfn; - let result = unsafe { - xenctrl_sys::xc_domain_maximum_gpfn(self.handle, domid, ptr_max_gpfn) - }; - match result { - 0 => Ok(max_gpfn as u64), - -1 => Err("Fail to get max gpfn"), - _ => panic!("unexpected value"), + pub fn domain_maximum_gpfn(&self, domid: u32) -> Result { + let xc = self.handle.as_ptr(); + let mut max_gpfn: u64; + unsafe { + max_gpfn = mem::uninitialized(); + xc_clear_last_error(xc); + xc_domain_maximum_gpfn(xc, domid, &mut max_gpfn as _); } + last_error!(xc, max_gpfn) } - fn close(&mut self) -> Result<(),&str>{ - let result = unsafe { - xenctrl_sys::xc_interface_close(self.handle) - }; - match result { - 0 => Ok(()), - -1 => Err("Fail to close xc interface"), - _ => panic!("unexpected value"), + fn close(&mut self) -> Result<()> { + let xc = self.handle.as_ptr(); + unsafe { + xc_clear_last_error(xc); + xc_interface_close(xc); } + last_error!(xc, ()) } } -impl Drop for Xc { +impl Drop for XenControl { fn drop(&mut self) { self.close().unwrap(); } diff --git a/src/macros.rs b/src/macros.rs new file mode 100644 index 0000000..b6873bc --- /dev/null +++ b/src/macros.rs @@ -0,0 +1,11 @@ +macro_rules! last_error { + ($xc:expr, $ok:expr) => { + unsafe { + let err = xc_get_last_error($xc); + match (*err).code { + xc_error_code::XC_ERROR_NONE => Ok($ok), + code => Err(Error::new(code)), + } + } + }; +} diff --git a/src/support.rs b/src/support.rs new file mode 100644 index 0000000..70c8793 --- /dev/null +++ b/src/support.rs @@ -0,0 +1,4 @@ +#[repr(C)] +pub struct PageInfo { + opaque: [u8; 0], +}