From faf8027590f1bccb309c7ee0769ba57bec263ae9 Mon Sep 17 00:00:00 2001 From: Alex Zenla Date: Mon, 8 Jan 2024 20:45:16 -0800 Subject: [PATCH] add support for hypercalls --- Cargo.toml | 3 +- xencall/Cargo.toml | 16 +++++ xencall/examples/simple.rs | 11 ++++ xencall/src/lib.rs | 118 +++++++++++++++++++++++++++++++++++++ xencall/src/sys.rs | 11 ++++ 5 files changed, 158 insertions(+), 1 deletion(-) create mode 100644 xencall/Cargo.toml create mode 100644 xencall/examples/simple.rs create mode 100644 xencall/src/lib.rs create mode 100644 xencall/src/sys.rs diff --git a/Cargo.toml b/Cargo.toml index 8cd9f33..a846165 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,7 @@ [workspace] members = [ "xenstore", - "xenevtchn" + "xenevtchn", + "xencall" ] resolver = "2" diff --git a/xencall/Cargo.toml b/xencall/Cargo.toml new file mode 100644 index 0000000..f0fd829 --- /dev/null +++ b/xencall/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "xencall" +version = "0.0.1" +edition = "2021" +resolver = "2" + +[lib] +path = "src/lib.rs" + +[dependencies.nix] +version = "0.27.1" +features = ["ioctl"] + +[[example]] +name = "xencall-simple" +path = "examples/simple.rs" diff --git a/xencall/examples/simple.rs b/xencall/examples/simple.rs new file mode 100644 index 0000000..a2bbe9f --- /dev/null +++ b/xencall/examples/simple.rs @@ -0,0 +1,11 @@ +use std::ffi::c_ulong; +use std::ptr::addr_of; +use xencall::{XenCall, XenCallError}; + +fn main() -> Result<(), XenCallError> { + let mut call = XenCall::open()?; + let message = "Hello World"; + let bytes = message.as_bytes(); + call.hypercall3(18, 0, bytes.len() as c_ulong, addr_of!(bytes) as c_ulong)?; + Ok(()) +} diff --git a/xencall/src/lib.rs b/xencall/src/lib.rs new file mode 100644 index 0000000..93f61d7 --- /dev/null +++ b/xencall/src/lib.rs @@ -0,0 +1,118 @@ +mod sys; + +use crate::sys::Hypercall; +use nix::errno::Errno; +use std::error::Error; +use std::ffi::{c_long, c_ulong}; +use std::fmt::{Display, Formatter}; +use std::fs::{File, OpenOptions}; +use std::os::fd::AsRawFd; + +pub struct XenCall { + pub handle: File, +} + +#[derive(Debug)] +pub struct XenCallError { + message: String, +} + +impl XenCallError { + pub fn new(msg: &str) -> XenCallError { + XenCallError { + message: msg.to_string(), + } + } +} + +impl Display for XenCallError { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.message) + } +} + +impl Error for XenCallError { + fn description(&self) -> &str { + &self.message + } +} + +impl From for XenCallError { + fn from(value: std::io::Error) -> Self { + XenCallError::new(value.to_string().as_str()) + } +} + +impl From for XenCallError { + fn from(value: Errno) -> Self { + XenCallError::new(value.to_string().as_str()) + } +} + +impl XenCall { + pub fn open() -> Result { + let file = OpenOptions::new() + .read(true) + .write(true) + .open("/dev/xen/privcmd")?; + Ok(XenCall { handle: file }) + } + + pub fn hypercall(&mut self, op: c_ulong, arg: [c_ulong; 5]) -> Result { + unsafe { + let mut call = Hypercall { op, arg, retval: 0 }; + sys::hypercall(self.handle.as_raw_fd(), &mut call)?; + Ok(call.retval) + } + } + + pub fn hypercall0(&mut self, op: c_ulong) -> Result { + self.hypercall(op, [0, 0, 0, 0, 0]) + } + + pub fn hypercall1(&mut self, op: c_ulong, arg1: c_ulong) -> Result { + self.hypercall(op, [arg1, 0, 0, 0, 0]) + } + + pub fn hypercall2( + &mut self, + op: c_ulong, + arg1: c_ulong, + arg2: c_ulong, + ) -> Result { + self.hypercall(op, [arg1, arg2, 0, 0, 0]) + } + + pub fn hypercall3( + &mut self, + op: c_ulong, + arg1: c_ulong, + arg2: c_ulong, + arg3: c_ulong, + ) -> Result { + self.hypercall(op, [arg1, arg2, arg3, 0, 0]) + } + + pub fn hypercall4( + &mut self, + op: c_ulong, + arg1: c_ulong, + arg2: c_ulong, + arg3: c_ulong, + arg4: c_ulong, + ) -> Result { + self.hypercall(op, [arg1, arg2, arg3, arg4, 0]) + } + + pub fn hypercall5( + &mut self, + op: c_ulong, + arg1: c_ulong, + arg2: c_ulong, + arg3: c_ulong, + arg4: c_ulong, + arg5: c_ulong, + ) -> Result { + self.hypercall(op, [arg1, arg2, arg3, arg4, arg5]) + } +} diff --git a/xencall/src/sys.rs b/xencall/src/sys.rs new file mode 100644 index 0000000..5822358 --- /dev/null +++ b/xencall/src/sys.rs @@ -0,0 +1,11 @@ +use nix::{ioctl_readwrite_bad, request_code_none}; +use std::ffi::{c_long, c_ulong}; + +#[repr(C)] +pub struct Hypercall { + pub op: c_ulong, + pub arg: [c_ulong; 5], + pub retval: c_long, +} + +ioctl_readwrite_bad!(hypercall, request_code_none!(b'E', 0), Hypercall);