Skip to content

Commit cab0306

Browse files
committed
WIP: error handling
1 parent 770285a commit cab0306

File tree

6 files changed

+142
-58
lines changed

6 files changed

+142
-58
lines changed

Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@ authors = ["Mathieu Tarral <[email protected]>"]
55
edition = "2018"
66

77
[dependencies]
8-
xenctrl-sys = "0.1.1"
8+
xenctrl-sys = { git = "https://github.com/Wenzel/xenctrl-sys.git" }
9+
libc = "0.2.58"

rustfmt.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
edition = "2018"
2+
indent_style = "block"
3+
format_strings = true
4+
merge_imports = true

src/error.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
use std::{
2+
error, ffi,
3+
fmt::{self, Debug, Display, Formatter},
4+
};
5+
6+
use xenctrl_sys::{xc_error_code, xc_error_code_to_desc};
7+
8+
#[derive(Copy, Clone)]
9+
pub struct Error(xc_error_code);
10+
11+
impl Error {
12+
pub fn new(code: xc_error_code) -> Self {
13+
Self(code)
14+
}
15+
16+
pub fn desc(self) -> &'static str {
17+
unsafe {
18+
let desc = xc_error_code_to_desc(self.0 as _);
19+
ffi::CStr::from_ptr(desc).to_str().unwrap()
20+
}
21+
}
22+
}
23+
24+
impl Display for Error {
25+
#[inline]
26+
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
27+
write!(f, "{}", self.desc())
28+
}
29+
}
30+
31+
impl Debug for Error {
32+
#[inline]
33+
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
34+
write!(f, "{}", self.desc())
35+
}
36+
}
37+
38+
impl error::Error for Error {}

src/lib.rs

Lines changed: 83 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,90 +1,116 @@
1+
pub mod error;
2+
pub mod support;
3+
4+
#[macro_use]
5+
mod macros;
6+
17
extern crate xenctrl_sys;
2-
use std::io::Error;
3-
use std::ptr::{null_mut};
4-
use std::os::raw::{c_void, c_ulong};
8+
use std::{
9+
mem,
10+
ptr::{null_mut, NonNull},
11+
};
12+
13+
use xenctrl_sys::{
14+
xc_clear_last_error, xc_domain_maximum_gpfn, xc_domain_pause, xc_domain_unpause, xc_error_code,
15+
xc_get_last_error, xc_interface, xc_interface_close, xc_interface_open, xc_monitor_disable,
16+
xc_monitor_enable, xentoollog_logger,
17+
};
518

6-
pub const PAGE_SHIFT: u32 = xenctrl_sys::XC_PAGE_SHIFT;
7-
pub const PAGE_SIZE: u32 = xenctrl_sys::XC_PAGE_SIZE;
19+
use error::Error;
20+
use support::PageInfo;
21+
22+
type Result<T> = std::result::Result<T, Error>;
823

924
#[derive(Debug)]
10-
pub struct Xc {
11-
handle: *mut xenctrl_sys::xc_interface,
12-
evtchn_port: *mut u32,
25+
pub struct XenControl {
26+
handle: NonNull<xc_interface>,
27+
evtchn_port: u32,
1328
}
1429

15-
impl Xc {
16-
17-
pub fn new() -> Result<Self,Error> {
30+
impl XenControl {
31+
pub fn from(
32+
logger: Option<&mut xentoollog_logger>,
33+
dombuild_logger: Option<&mut xentoollog_logger>,
34+
open_flags: u32,
35+
) -> Result<Self> {
1836
let xc_handle = unsafe {
19-
xenctrl_sys::xc_interface_open(null_mut(), null_mut(), 0)
37+
xc_interface_open(
38+
logger.map_or_else(|| null_mut(), |l| l as *mut _),
39+
dombuild_logger.map_or_else(|| null_mut(), |l| l as *mut _),
40+
open_flags,
41+
)
2042
};
21-
if xc_handle == null_mut() {
22-
return Err(Error::last_os_error());
23-
}
24-
Ok(Xc {
25-
handle: xc_handle,
26-
evtchn_port: null_mut()
27-
})
43+
44+
NonNull::new(xc_handle)
45+
.ok_or_else(|| Error::new(xc_error_code::XC_INTERNAL_ERROR))
46+
.map(|handle| XenControl {
47+
handle,
48+
evtchn_port: 0u32,
49+
})
2850
}
2951

30-
pub fn monitor_enable(&self, domid: u32) -> *mut c_void {
31-
unsafe {
32-
xenctrl_sys::xc_monitor_enable(self.handle, domid, self.evtchn_port)
33-
}
52+
pub fn default() -> Result<Self> {
53+
Self::from(None, None, 0)
3454
}
3555

36-
pub fn monitor_disable(&self, domid: u32) {
56+
pub fn monitor_enable(&mut self, domid: u32) -> Result<&PageInfo> {
57+
let xc = self.handle.as_ptr();
58+
let ring_page = unsafe {
59+
xc_clear_last_error(xc);
60+
xc_monitor_enable(xc, domid, &mut self.evtchn_port as _) as *const PageInfo
61+
};
62+
last_error!(xc, &*ring_page)
63+
}
64+
65+
pub fn monitor_disable(&self, domid: u32) -> Result<()> {
66+
let xc = self.handle.as_ptr();
3767
unsafe {
38-
xenctrl_sys::xc_monitor_disable(self.handle, domid);
68+
xc_clear_last_error(xc);
69+
xc_monitor_disable(xc, domid);
3970
};
71+
last_error!(xc, ())
4072
}
4173

42-
pub fn domain_pause(&self, domid: u32) -> Result<(),&str> {
74+
pub fn domain_pause(&self, domid: u32) -> Result<()> {
75+
let xc = self.handle.as_ptr();
4376
unsafe {
44-
match xenctrl_sys::xc_domain_pause(self.handle, domid) {
45-
0 => Ok(()),
46-
-1 => Err("Fail to pause domain"),
47-
_ => panic!("unexpected value"),
48-
}
49-
}
77+
xc_clear_last_error(xc);
78+
xc_domain_pause(xc, domid);
79+
};
80+
last_error!(xc, ())
5081
}
5182

52-
pub fn domain_unpause(&self, domid: u32) -> Result<(),&str> {
83+
pub fn domain_unpause(&self, domid: u32) -> Result<()> {
84+
let xc = self.handle.as_ptr();
5385
unsafe {
54-
match xenctrl_sys::xc_domain_unpause(self.handle, domid) {
55-
0 => Ok(()),
56-
-1 => Err("Fail to unpause domain"),
57-
_ => panic!("unexpected value"),
58-
}
86+
xc_clear_last_error(xc);
87+
xc_domain_unpause(xc, domid);
5988
}
89+
last_error!(xc, ())
6090
}
6191

62-
pub fn domain_maximum_gpfn(&self, domid: u32) -> Result<u64,&str> {
63-
let mut max_gpfn: c_ulong = 0;
64-
let ptr_max_gpfn: *mut c_ulong = &mut max_gpfn;
65-
let result = unsafe {
66-
xenctrl_sys::xc_domain_maximum_gpfn(self.handle, domid, ptr_max_gpfn)
67-
};
68-
match result {
69-
0 => Ok(max_gpfn as u64),
70-
-1 => Err("Fail to get max gpfn"),
71-
_ => panic!("unexpected value"),
92+
pub fn domain_maximum_gpfn(&self, domid: u32) -> Result<u64> {
93+
let xc = self.handle.as_ptr();
94+
let mut max_gpfn: u64;
95+
unsafe {
96+
max_gpfn = mem::uninitialized();
97+
xc_clear_last_error(xc);
98+
xc_domain_maximum_gpfn(xc, domid, &mut max_gpfn as _);
7299
}
100+
last_error!(xc, max_gpfn)
73101
}
74102

75-
fn close(&mut self) -> Result<(),&str>{
76-
let result = unsafe {
77-
xenctrl_sys::xc_interface_close(self.handle)
78-
};
79-
match result {
80-
0 => Ok(()),
81-
-1 => Err("Fail to close xc interface"),
82-
_ => panic!("unexpected value"),
103+
fn close(&mut self) -> Result<()> {
104+
let xc = self.handle.as_ptr();
105+
unsafe {
106+
xc_clear_last_error(xc);
107+
xc_interface_close(xc);
83108
}
109+
last_error!(xc, ())
84110
}
85111
}
86112

87-
impl Drop for Xc {
113+
impl Drop for XenControl {
88114
fn drop(&mut self) {
89115
self.close().unwrap();
90116
}

src/macros.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
macro_rules! last_error {
2+
($xc:expr, $ok:expr) => {
3+
unsafe {
4+
let err = xc_get_last_error($xc);
5+
match (*err).code {
6+
xc_error_code::XC_ERROR_NONE => Ok($ok),
7+
code => Err(Error::new(code)),
8+
}
9+
}
10+
};
11+
}

src/support.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#[repr(C)]
2+
pub struct PageInfo {
3+
opaque: [u8; 0],
4+
}

0 commit comments

Comments
 (0)