mirror of
https://github.com/edera-dev/krata.git
synced 2025-08-03 05:10:55 +00:00
xen: begin work on xen grant mappings
This commit is contained in:
parent
001409378e
commit
0a5948aa50
@ -12,6 +12,7 @@ members = [
|
|||||||
"crates/xen/xencall",
|
"crates/xen/xencall",
|
||||||
"crates/xen/xenclient",
|
"crates/xen/xenclient",
|
||||||
"crates/xen/xenevtchn",
|
"crates/xen/xenevtchn",
|
||||||
|
"crates/xen/xengnt",
|
||||||
"crates/xen/xenstore",
|
"crates/xen/xenstore",
|
||||||
]
|
]
|
||||||
resolver = "2"
|
resolver = "2"
|
||||||
|
14
crates/xen/xengnt/Cargo.toml
Normal file
14
crates/xen/xengnt/Cargo.toml
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
[package]
|
||||||
|
name = "xengnt"
|
||||||
|
version.workspace = true
|
||||||
|
edition = "2021"
|
||||||
|
resolver = "2"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
log = { workspace = true }
|
||||||
|
thiserror = { workspace = true }
|
||||||
|
nix = { workspace = true, features = ["ioctl"] }
|
||||||
|
tokio = { workspace = true }
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
name = "xengnt"
|
13
crates/xen/xengnt/src/error.rs
Normal file
13
crates/xen/xengnt/src/error.rs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
use std::io;
|
||||||
|
|
||||||
|
#[derive(thiserror::Error, Debug)]
|
||||||
|
pub enum Error {
|
||||||
|
#[error("kernel error")]
|
||||||
|
Kernel(#[from] nix::errno::Errno),
|
||||||
|
#[error("io issue encountered")]
|
||||||
|
Io(#[from] io::Error),
|
||||||
|
#[error("failed to read structure")]
|
||||||
|
StructureReadFailed,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type Result<T> = std::result::Result<T, Error>;
|
142
crates/xen/xengnt/src/lib.rs
Normal file
142
crates/xen/xengnt/src/lib.rs
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
pub mod error;
|
||||||
|
pub mod sys;
|
||||||
|
|
||||||
|
use error::{Error, Result};
|
||||||
|
use std::{
|
||||||
|
fs::{File, OpenOptions},
|
||||||
|
os::fd::AsRawFd,
|
||||||
|
};
|
||||||
|
use sys::{
|
||||||
|
AllocGref, DeallocGref, GetOffsetForVaddr, GrantRef, MapGrantRef, SetMaxGrants, UnmapGrantRef,
|
||||||
|
UnmapNotify, UNMAP_NOTIFY_CLEAR_BYTE, UNMAP_NOTIFY_SEND_EVENT,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct GrantDevice {
|
||||||
|
handle: File,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GrantDevice {
|
||||||
|
pub fn open() -> Result<GrantDevice> {
|
||||||
|
let handle = OpenOptions::new()
|
||||||
|
.read(true)
|
||||||
|
.write(true)
|
||||||
|
.open("/dev/xen/gntdev")?;
|
||||||
|
Ok(GrantDevice { handle })
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn map_grant_ref(&self, count: u32) -> Result<(u64, Vec<GrantRef>)> {
|
||||||
|
let refs: Vec<GrantRef> = vec![
|
||||||
|
GrantRef {
|
||||||
|
domid: 0,
|
||||||
|
reference: 0
|
||||||
|
};
|
||||||
|
count as usize
|
||||||
|
];
|
||||||
|
let mut request = MapGrantRef::write(refs.as_slice());
|
||||||
|
unsafe {
|
||||||
|
sys::map_grant_ref(self.handle.as_raw_fd(), request.as_mut_ptr())?;
|
||||||
|
};
|
||||||
|
let result =
|
||||||
|
MapGrantRef::read(refs.len() as u32, request).ok_or(Error::StructureReadFailed)?;
|
||||||
|
Ok((result.index, result.refs))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn unmap_grant_ref(&self, index: u64, count: u32) -> Result<()> {
|
||||||
|
let mut request = UnmapGrantRef {
|
||||||
|
index,
|
||||||
|
count,
|
||||||
|
pad: 0,
|
||||||
|
};
|
||||||
|
unsafe {
|
||||||
|
sys::unmap_grant_ref(self.handle.as_raw_fd(), &mut request)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_offset_for_vaddr(&self, vaddr: u64) -> Result<(u64, u32)> {
|
||||||
|
let mut request = GetOffsetForVaddr {
|
||||||
|
vaddr,
|
||||||
|
pad: 0,
|
||||||
|
offset: 0,
|
||||||
|
count: 0,
|
||||||
|
};
|
||||||
|
unsafe {
|
||||||
|
sys::get_offset_for_vaddr(self.handle.as_raw_fd(), &mut request)?;
|
||||||
|
}
|
||||||
|
Ok((request.offset, request.count))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_max_grants(&self, count: u32) -> Result<()> {
|
||||||
|
let mut request = SetMaxGrants { count };
|
||||||
|
unsafe {
|
||||||
|
sys::set_max_grants(self.handle.as_raw_fd(), &mut request)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn unmap_notify(&self, index: u64, send: bool, port: u32) -> Result<()> {
|
||||||
|
let mut request = UnmapNotify {
|
||||||
|
index,
|
||||||
|
action: if send {
|
||||||
|
UNMAP_NOTIFY_SEND_EVENT
|
||||||
|
} else {
|
||||||
|
UNMAP_NOTIFY_CLEAR_BYTE
|
||||||
|
},
|
||||||
|
port,
|
||||||
|
};
|
||||||
|
unsafe {
|
||||||
|
sys::unmap_notify(self.handle.as_raw_fd(), &mut request)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct GrantAlloc {
|
||||||
|
handle: File,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GrantAlloc {
|
||||||
|
pub fn open() -> Result<GrantAlloc> {
|
||||||
|
let handle = OpenOptions::new()
|
||||||
|
.read(true)
|
||||||
|
.write(true)
|
||||||
|
.open("/dev/xen/gntalloc")?;
|
||||||
|
Ok(GrantAlloc { handle })
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn alloc_gref(&self, domid: u16, flags: u16, count: u32) -> Result<(u64, Vec<u32>)> {
|
||||||
|
let mut request = AllocGref::write(AllocGref {
|
||||||
|
domid,
|
||||||
|
flags,
|
||||||
|
count,
|
||||||
|
});
|
||||||
|
unsafe {
|
||||||
|
sys::alloc_gref(self.handle.as_raw_fd(), request.as_mut_ptr())?;
|
||||||
|
};
|
||||||
|
AllocGref::read(count, request).ok_or(Error::StructureReadFailed)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn dealloc_gref(&self, index: u64, count: u32) -> Result<()> {
|
||||||
|
let mut request = DeallocGref { index, count };
|
||||||
|
unsafe {
|
||||||
|
sys::dealloc_gref(self.handle.as_raw_fd(), &mut request)?;
|
||||||
|
};
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn unmap_notify(&self, index: u64, send: bool, port: u32) -> Result<()> {
|
||||||
|
let mut request = UnmapNotify {
|
||||||
|
index,
|
||||||
|
action: if send {
|
||||||
|
UNMAP_NOTIFY_SEND_EVENT
|
||||||
|
} else {
|
||||||
|
UNMAP_NOTIFY_CLEAR_BYTE
|
||||||
|
},
|
||||||
|
port,
|
||||||
|
};
|
||||||
|
unsafe {
|
||||||
|
sys::unmap_notify(self.handle.as_raw_fd(), &mut request)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
177
crates/xen/xengnt/src/sys.rs
Normal file
177
crates/xen/xengnt/src/sys.rs
Normal file
@ -0,0 +1,177 @@
|
|||||||
|
use std::mem::size_of;
|
||||||
|
|
||||||
|
use nix::{ioc, ioctl_readwrite_bad};
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct GrantRef {
|
||||||
|
pub domid: u32,
|
||||||
|
pub reference: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct MapGrantRef {
|
||||||
|
pub count: u32,
|
||||||
|
pub pad: u32,
|
||||||
|
pub index: u64,
|
||||||
|
pub refs: Vec<GrantRef>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MapGrantRef {
|
||||||
|
pub fn write(slice: &[GrantRef]) -> Vec<u32> {
|
||||||
|
let mut values = vec![slice.len() as u32, 0, 0, 0];
|
||||||
|
for r in slice {
|
||||||
|
values.push(r.domid);
|
||||||
|
values.push(r.reference);
|
||||||
|
}
|
||||||
|
values
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read(count: u32, data: Vec<u32>) -> Option<MapGrantRef> {
|
||||||
|
let mut refs = Vec::new();
|
||||||
|
|
||||||
|
if data.len() < (4 + (count as u64 * 2)) as usize {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let index = (*data.get(2)? as u64) << 32 | *data.get(3)? as u64;
|
||||||
|
for i in (4..data.len()).step_by(2) {
|
||||||
|
let Some(domid) = data.get(i) else {
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
let Some(reference) = data.get(i + 1) else {
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
refs.push(GrantRef {
|
||||||
|
domid: *domid,
|
||||||
|
reference: *reference,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(MapGrantRef {
|
||||||
|
count,
|
||||||
|
pad: 0,
|
||||||
|
index,
|
||||||
|
refs,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct UnmapGrantRef {
|
||||||
|
pub index: u64,
|
||||||
|
pub count: u32,
|
||||||
|
pub pad: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct GetOffsetForVaddr {
|
||||||
|
pub vaddr: u64,
|
||||||
|
pub offset: u64,
|
||||||
|
pub count: u32,
|
||||||
|
pub pad: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct SetMaxGrants {
|
||||||
|
pub count: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct UnmapNotify {
|
||||||
|
pub index: u64,
|
||||||
|
pub action: u32,
|
||||||
|
pub port: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const UNMAP_NOTIFY_CLEAR_BYTE: u32 = 0x1;
|
||||||
|
pub const UNMAP_NOTIFY_SEND_EVENT: u32 = 0x2;
|
||||||
|
|
||||||
|
ioctl_readwrite_bad!(map_grant_ref, ioc!(nix::sys::ioctl::NONE, 'G', 0, 24), u32);
|
||||||
|
ioctl_readwrite_bad!(
|
||||||
|
unmap_grant_ref,
|
||||||
|
ioc!(nix::sys::ioctl::NONE, 'G', 1, size_of::<UnmapGrantRef>()),
|
||||||
|
UnmapGrantRef
|
||||||
|
);
|
||||||
|
ioctl_readwrite_bad!(
|
||||||
|
get_offset_for_vaddr,
|
||||||
|
ioc!(
|
||||||
|
nix::sys::ioctl::NONE,
|
||||||
|
'G',
|
||||||
|
2,
|
||||||
|
size_of::<GetOffsetForVaddr>()
|
||||||
|
),
|
||||||
|
GetOffsetForVaddr
|
||||||
|
);
|
||||||
|
ioctl_readwrite_bad!(
|
||||||
|
set_max_grants,
|
||||||
|
ioc!(nix::sys::ioctl::NONE, 'G', 3, size_of::<SetMaxGrants>()),
|
||||||
|
SetMaxGrants
|
||||||
|
);
|
||||||
|
ioctl_readwrite_bad!(
|
||||||
|
unmap_notify,
|
||||||
|
ioc!(nix::sys::ioctl::NONE, 'G', 7, size_of::<UnmapNotify>()),
|
||||||
|
UnmapNotify
|
||||||
|
);
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct AllocGref {
|
||||||
|
pub domid: u16,
|
||||||
|
pub flags: u16,
|
||||||
|
pub count: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AllocGref {
|
||||||
|
pub fn write(gref: AllocGref) -> Vec<u16> {
|
||||||
|
let mut values = vec![
|
||||||
|
gref.domid,
|
||||||
|
gref.flags,
|
||||||
|
(gref.count << 16) as u16,
|
||||||
|
gref.count as u16,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
];
|
||||||
|
for _ in 0..gref.count {
|
||||||
|
values.push(0);
|
||||||
|
values.push(0);
|
||||||
|
}
|
||||||
|
values
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read(count: u32, data: Vec<u16>) -> Option<(u64, Vec<u32>)> {
|
||||||
|
let mut refs = Vec::new();
|
||||||
|
|
||||||
|
if data.len() < (8 + (count as u64 * 2)) as usize {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let index = (*data.get(4)? as u64) << 48
|
||||||
|
| (*data.get(5)? as u64) << 32
|
||||||
|
| (*data.get(6)? as u64) << 16
|
||||||
|
| *data.get(7)? as u64;
|
||||||
|
for i in (8..data.len()).step_by(2) {
|
||||||
|
let Some(bits_low) = data.get(i) else {
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
let Some(bits_high) = data.get(i + 1) else {
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
refs.push((*bits_low as u32) << 16 | *bits_high as u32);
|
||||||
|
}
|
||||||
|
Some((index, refs))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct DeallocGref {
|
||||||
|
pub index: u64,
|
||||||
|
pub count: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
ioctl_readwrite_bad!(alloc_gref, ioc!(nix::sys::ioctl::NONE, 'G', 5, 20), u16);
|
||||||
|
ioctl_readwrite_bad!(
|
||||||
|
dealloc_gref,
|
||||||
|
ioc!(nix::sys::ioctl::NONE, 'G', 6, size_of::<DeallocGref>()),
|
||||||
|
DeallocGref
|
||||||
|
);
|
Loading…
Reference in New Issue
Block a user