From 47b924d618d87f0e6a82363ab8afb0207e4daf70 Mon Sep 17 00:00:00 2001 From: Alex Zenla Date: Mon, 8 Jan 2024 17:07:00 -0800 Subject: [PATCH] implement evtchn support --- Cargo.toml | 3 +- xenevtchn/Cargo.toml | 16 +++++ xenevtchn/examples/simple.rs | 10 +++ xenevtchn/src/lib.rs | 103 +++++++++++++++++++++++++++++ xenevtchn/src/sys.rs | 43 ++++++++++++ {xsd => xenstore}/Cargo.toml | 4 +- {xsd => xenstore}/examples/list.rs | 6 +- {xsd => xenstore}/src/bus.rs | 0 {xsd => xenstore}/src/client.rs | 0 {xsd => xenstore}/src/lib.rs | 0 {xsd => xenstore}/src/sys.rs | 0 11 files changed, 179 insertions(+), 6 deletions(-) create mode 100644 xenevtchn/Cargo.toml create mode 100644 xenevtchn/examples/simple.rs create mode 100644 xenevtchn/src/lib.rs create mode 100644 xenevtchn/src/sys.rs rename {xsd => xenstore}/Cargo.toml (85%) rename {xsd => xenstore}/examples/list.rs (88%) rename {xsd => xenstore}/src/bus.rs (100%) rename {xsd => xenstore}/src/client.rs (100%) rename {xsd => xenstore}/src/lib.rs (100%) rename {xsd => xenstore}/src/sys.rs (100%) diff --git a/Cargo.toml b/Cargo.toml index 04ed257..8cd9f33 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,6 @@ [workspace] members = [ - "xsd" + "xenstore", + "xenevtchn" ] resolver = "2" diff --git a/xenevtchn/Cargo.toml b/xenevtchn/Cargo.toml new file mode 100644 index 0000000..ffe8099 --- /dev/null +++ b/xenevtchn/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "xenevtchn" +version = "0.0.1" +edition = "2021" +resolver = "2" + +[dependencies.nix] +version = "0.27.1" +features = ["ioctl"] + +[lib] +path = "src/lib.rs" + +[[example]] +name = "xenevtchn-simple" +path = "examples/simple.rs" diff --git a/xenevtchn/examples/simple.rs b/xenevtchn/examples/simple.rs new file mode 100644 index 0000000..651b441 --- /dev/null +++ b/xenevtchn/examples/simple.rs @@ -0,0 +1,10 @@ +use xenevtchn::{EventChannel, EventChannelError}; + +fn main() -> Result<(), EventChannelError> { + let mut channel = EventChannel::open()?; + println!("Channel opened."); + let port = channel.bind_unbound_port(1)?; + println!("port: {}", port); + channel.unbind(port)?; + Ok(()) +} diff --git a/xenevtchn/src/lib.rs b/xenevtchn/src/lib.rs new file mode 100644 index 0000000..15d0a8c --- /dev/null +++ b/xenevtchn/src/lib.rs @@ -0,0 +1,103 @@ +pub mod sys; + +use crate::sys::{BindInterdomain, BindUnboundPort, BindVirq, Notify, UnbindPort}; +use nix::errno::Errno; +use std::error::Error; +use std::fmt::{Display, Formatter}; +use std::fs::{File, OpenOptions}; +use std::os::fd::AsRawFd; + +pub struct EventChannel { + pub handle: File, +} + +#[derive(Debug)] +pub struct EventChannelError { + message: String, +} + +impl EventChannelError { + pub fn new(msg: &str) -> EventChannelError { + EventChannelError { + message: msg.to_string(), + } + } +} + +impl Display for EventChannelError { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.message) + } +} + +impl Error for EventChannelError { + fn description(&self) -> &str { + &self.message + } +} + +impl From for EventChannelError { + fn from(value: std::io::Error) -> Self { + EventChannelError::new(value.to_string().as_str()) + } +} + +impl From for EventChannelError { + fn from(value: Errno) -> Self { + EventChannelError::new(value.to_string().as_str()) + } +} + +impl EventChannel { + pub fn open() -> Result { + let file = OpenOptions::new() + .read(true) + .write(true) + .open("/dev/xen/evtchn")?; + Ok(EventChannel { handle: file }) + } + + pub fn bind_virq(&mut self, virq: u32) -> Result { + unsafe { + let mut request = BindVirq { virq }; + Ok(sys::bind_virq(self.handle.as_raw_fd(), &mut request)? as u32) + } + } + + pub fn bind_interdomain(&mut self, domid: u32, port: u32) -> Result { + unsafe { + let mut request = BindInterdomain { + remote_domain: domid, + remote_port: port, + }; + Ok(sys::bind_interdomain(self.handle.as_raw_fd(), &mut request)? as u32) + } + } + + pub fn bind_unbound_port(&mut self, domid: u32) -> Result { + unsafe { + let mut request = BindUnboundPort { + remote_domain: domid, + }; + Ok(sys::bind_unbound_port(self.handle.as_raw_fd(), &mut request)? as u32) + } + } + + pub fn unbind(&mut self, port: u32) -> Result { + unsafe { + let mut request = UnbindPort { port }; + Ok(sys::unbind(self.handle.as_raw_fd(), &mut request)? as u32) + } + } + + pub fn notify(&mut self, port: u32) -> Result { + unsafe { + let mut request = Notify { port }; + Ok(sys::notify(self.handle.as_raw_fd(), &mut request)? as u32) + } + } + + pub fn reset(&mut self) -> Result { + unsafe { Ok(sys::reset(self.handle.as_raw_fd())? as u32) } + } +} diff --git a/xenevtchn/src/sys.rs b/xenevtchn/src/sys.rs new file mode 100644 index 0000000..891840c --- /dev/null +++ b/xenevtchn/src/sys.rs @@ -0,0 +1,43 @@ +use nix::{ioctl_none, ioctl_readwrite_bad, request_code_none}; +use std::ffi::c_uint; + +#[repr(C)] +pub struct BindVirq { + pub virq: c_uint, +} + +#[repr(C)] +pub struct BindInterdomain { + pub remote_domain: c_uint, + pub remote_port: c_uint, +} + +#[repr(C)] +pub struct BindUnboundPort { + pub remote_domain: c_uint, +} + +#[repr(C)] +pub struct UnbindPort { + pub port: c_uint, +} + +#[repr(C)] +pub struct Notify { + pub port: c_uint, +} + +ioctl_readwrite_bad!(bind_virq, request_code_none!(b'E', 0), BindVirq); +ioctl_readwrite_bad!( + bind_interdomain, + request_code_none!(b'E', 1), + BindInterdomain +); +ioctl_readwrite_bad!( + bind_unbound_port, + request_code_none!(b'E', 2), + BindUnboundPort +); +ioctl_readwrite_bad!(unbind, request_code_none!(b'E', 3), UnbindPort); +ioctl_readwrite_bad!(notify, request_code_none!(b'E', 4), Notify); +ioctl_none!(reset, b'E', 5); diff --git a/xsd/Cargo.toml b/xenstore/Cargo.toml similarity index 85% rename from xsd/Cargo.toml rename to xenstore/Cargo.toml index fd3d6b2..89fa175 100644 --- a/xsd/Cargo.toml +++ b/xenstore/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "xsd" +name = "xenstore" version = "0.0.1" edition = "2021" resolver = "2" @@ -15,5 +15,5 @@ version = "1.14.0" features = ["derive"] [[example]] -name = "xsd-list" +name = "xenstore-ls" path = "examples/list.rs" diff --git a/xsd/examples/list.rs b/xenstore/examples/list.rs similarity index 88% rename from xsd/examples/list.rs rename to xenstore/examples/list.rs index 1ca9ed8..9843427 100644 --- a/xsd/examples/list.rs +++ b/xenstore/examples/list.rs @@ -1,6 +1,6 @@ -use xsd::bus::XsdBusError; -use xsd::client::{XsdClient, XsdInterface}; -use xsd::sys::XSD_ERROR_EINVAL; +use xenstore::bus::XsdBusError; +use xenstore::client::{XsdClient, XsdInterface}; +use xenstore::sys::XSD_ERROR_EINVAL; fn list_recursive(client: &mut XsdClient, level: usize, path: &str) -> Result<(), XsdBusError> { let children = match client.list(path) { diff --git a/xsd/src/bus.rs b/xenstore/src/bus.rs similarity index 100% rename from xsd/src/bus.rs rename to xenstore/src/bus.rs diff --git a/xsd/src/client.rs b/xenstore/src/client.rs similarity index 100% rename from xsd/src/client.rs rename to xenstore/src/client.rs diff --git a/xsd/src/lib.rs b/xenstore/src/lib.rs similarity index 100% rename from xsd/src/lib.rs rename to xenstore/src/lib.rs diff --git a/xsd/src/sys.rs b/xenstore/src/sys.rs similarity index 100% rename from xsd/src/sys.rs rename to xenstore/src/sys.rs