implement evtchn support

This commit is contained in:
Alex Zenla 2024-01-08 17:07:00 -08:00
parent 7ca32dd413
commit 47b924d618
No known key found for this signature in database
GPG Key ID: 067B238899B51269
11 changed files with 179 additions and 6 deletions

View File

@ -1,5 +1,6 @@
[workspace] [workspace]
members = [ members = [
"xsd" "xenstore",
"xenevtchn"
] ]
resolver = "2" resolver = "2"

16
xenevtchn/Cargo.toml Normal file
View File

@ -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"

View File

@ -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(())
}

103
xenevtchn/src/lib.rs Normal file
View File

@ -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<std::io::Error> for EventChannelError {
fn from(value: std::io::Error) -> Self {
EventChannelError::new(value.to_string().as_str())
}
}
impl From<Errno> for EventChannelError {
fn from(value: Errno) -> Self {
EventChannelError::new(value.to_string().as_str())
}
}
impl EventChannel {
pub fn open() -> Result<EventChannel, EventChannelError> {
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<u32, EventChannelError> {
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<u32, EventChannelError> {
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<u32, EventChannelError> {
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<u32, EventChannelError> {
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<u32, EventChannelError> {
unsafe {
let mut request = Notify { port };
Ok(sys::notify(self.handle.as_raw_fd(), &mut request)? as u32)
}
}
pub fn reset(&mut self) -> Result<u32, EventChannelError> {
unsafe { Ok(sys::reset(self.handle.as_raw_fd())? as u32) }
}
}

43
xenevtchn/src/sys.rs Normal file
View File

@ -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);

View File

@ -1,5 +1,5 @@
[package] [package]
name = "xsd" name = "xenstore"
version = "0.0.1" version = "0.0.1"
edition = "2021" edition = "2021"
resolver = "2" resolver = "2"
@ -15,5 +15,5 @@ version = "1.14.0"
features = ["derive"] features = ["derive"]
[[example]] [[example]]
name = "xsd-list" name = "xenstore-ls"
path = "examples/list.rs" path = "examples/list.rs"

View File

@ -1,6 +1,6 @@
use xsd::bus::XsdBusError; use xenstore::bus::XsdBusError;
use xsd::client::{XsdClient, XsdInterface}; use xenstore::client::{XsdClient, XsdInterface};
use xsd::sys::XSD_ERROR_EINVAL; use xenstore::sys::XSD_ERROR_EINVAL;
fn list_recursive(client: &mut XsdClient, level: usize, path: &str) -> Result<(), XsdBusError> { fn list_recursive(client: &mut XsdClient, level: usize, path: &str) -> Result<(), XsdBusError> {
let children = match client.list(path) { let children = match client.list(path) {