xengnt: implement memory mapping support

This commit is contained in:
Alex Zenla 2024-03-25 07:24:25 +00:00
parent 0a5948aa50
commit 162579f100
No known key found for this signature in database
GPG Key ID: 067B238899B51269
3 changed files with 88 additions and 15 deletions

View File

@ -5,10 +5,9 @@ edition = "2021"
resolver = "2" resolver = "2"
[dependencies] [dependencies]
log = { workspace = true }
thiserror = { workspace = true } thiserror = { workspace = true }
libc = { workspace = true }
nix = { workspace = true, features = ["ioctl"] } nix = { workspace = true, features = ["ioctl"] }
tokio = { workspace = true }
[lib] [lib]
name = "xengnt" name = "xengnt"

View File

@ -8,6 +8,8 @@ pub enum Error {
Io(#[from] io::Error), Io(#[from] io::Error),
#[error("failed to read structure")] #[error("failed to read structure")]
StructureReadFailed, StructureReadFailed,
#[error("mmap failed")]
MmapFailed,
} }
pub type Result<T> = std::result::Result<T, Error>; pub type Result<T> = std::result::Result<T, Error>;

View File

@ -4,15 +4,18 @@ pub mod sys;
use error::{Error, Result}; use error::{Error, Result};
use std::{ use std::{
fs::{File, OpenOptions}, fs::{File, OpenOptions},
os::fd::AsRawFd, os::{fd::AsRawFd, raw::c_void},
sync::Arc,
}; };
use sys::{ use sys::{
AllocGref, DeallocGref, GetOffsetForVaddr, GrantRef, MapGrantRef, SetMaxGrants, UnmapGrantRef, AllocGref, DeallocGref, GetOffsetForVaddr, GrantRef, MapGrantRef, SetMaxGrants, UnmapGrantRef,
UnmapNotify, UNMAP_NOTIFY_CLEAR_BYTE, UNMAP_NOTIFY_SEND_EVENT, UnmapNotify, UNMAP_NOTIFY_CLEAR_BYTE, UNMAP_NOTIFY_SEND_EVENT,
}; };
use libc::{mmap, munmap, MAP_FAILED, MAP_SHARED, PROT_READ, PROT_WRITE};
pub struct GrantDevice { pub struct GrantDevice {
handle: File, handle: Arc<File>,
} }
impl GrantDevice { impl GrantDevice {
@ -21,17 +24,12 @@ impl GrantDevice {
.read(true) .read(true)
.write(true) .write(true)
.open("/dev/xen/gntdev")?; .open("/dev/xen/gntdev")?;
Ok(GrantDevice { handle }) Ok(GrantDevice {
handle: Arc::new(handle),
})
} }
pub fn map_grant_ref(&self, count: u32) -> Result<(u64, Vec<GrantRef>)> { pub fn map_grant_ref(&self, refs: Vec<GrantRef>) -> 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()); let mut request = MapGrantRef::write(refs.as_slice());
unsafe { unsafe {
sys::map_grant_ref(self.handle.as_raw_fd(), request.as_mut_ptr())?; sys::map_grant_ref(self.handle.as_raw_fd(), request.as_mut_ptr())?;
@ -91,8 +89,9 @@ impl GrantDevice {
} }
} }
#[derive(Clone)]
pub struct GrantAlloc { pub struct GrantAlloc {
handle: File, handle: Arc<File>,
} }
impl GrantAlloc { impl GrantAlloc {
@ -101,7 +100,9 @@ impl GrantAlloc {
.read(true) .read(true)
.write(true) .write(true)
.open("/dev/xen/gntalloc")?; .open("/dev/xen/gntalloc")?;
Ok(GrantAlloc { handle }) Ok(GrantAlloc {
handle: Arc::new(handle),
})
} }
pub fn alloc_gref(&self, domid: u16, flags: u16, count: u32) -> Result<(u64, Vec<u32>)> { pub fn alloc_gref(&self, domid: u16, flags: u16, count: u32) -> Result<(u64, Vec<u32>)> {
@ -140,3 +141,74 @@ impl GrantAlloc {
Ok(()) Ok(())
} }
} }
pub struct GrantTab {
device: GrantDevice,
}
const PAGE_SIZE: usize = 4096;
#[allow(clippy::len_without_is_empty)]
pub struct MappedMemory {
length: usize,
addr: *mut c_void,
}
impl MappedMemory {
pub fn len(&self) -> usize {
self.length
}
pub fn ptr(&self) -> *mut c_void {
self.addr
}
}
impl Drop for MappedMemory {
fn drop(&mut self) {
let _ = unsafe { munmap(self.addr, self.length) };
}
}
impl GrantTab {
pub fn open() -> Result<GrantTab> {
Ok(GrantTab {
device: GrantDevice::open()?,
})
}
pub fn map_grant_refs(
&self,
refs: Vec<GrantRef>,
read: bool,
write: bool,
) -> Result<MappedMemory> {
let (index, refs) = self.device.map_grant_ref(refs)?;
unsafe {
let mut flags: i32 = 0;
if read {
flags |= PROT_READ;
}
if write {
flags |= PROT_WRITE;
}
let addr = mmap(
std::ptr::null_mut(),
PAGE_SIZE * refs.len(),
flags,
MAP_SHARED,
self.device.handle.as_raw_fd(),
index as i64,
);
if addr == MAP_FAILED {
return Err(Error::MmapFailed);
}
Ok(MappedMemory {
addr,
length: PAGE_SIZE * refs.len(),
})
}
}
}