Skip to content

Commit

Permalink
Use hypercall definitions from uhyve-interface
Browse files Browse the repository at this point in the history
  • Loading branch information
jounathaen committed Dec 17, 2024
1 parent 430da84 commit 12eebc9
Show file tree
Hide file tree
Showing 5 changed files with 132 additions and 189 deletions.
25 changes: 24 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ talc = { version = "4" }
time = { version = "0.3", default-features = false }
volatile = "0.6"
zerocopy = { version = "0.8", default-features = false }
uhyve-interface = "0.1.2"

[dependencies.smoltcp]
version = "0.11"
Expand Down
222 changes: 59 additions & 163 deletions src/fs/uhyve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,159 +3,22 @@ use alloc::boxed::Box;
use alloc::string::{String, ToString};
use alloc::sync::Arc;
use alloc::vec::Vec;
#[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))]
use core::ptr;

use async_lock::Mutex;
use async_trait::async_trait;
use memory_addresses::{PhysAddr, VirtAddr};
#[cfg(target_arch = "x86_64")]
use x86::io::outl;
use memory_addresses::VirtAddr;
use uhyve_interface::parameters::{
CloseParams, LseekParams, OpenParams, ReadParams, UnlinkParams, WriteParams,
};
use uhyve_interface::{GuestPhysAddr, GuestVirtAddr, Hypercall};

use crate::arch::mm::paging;
use crate::env::is_uhyve;
use crate::fs::{
self, AccessPermission, FileAttr, NodeKind, ObjectInterface, OpenOption, SeekWhence, VfsNode,
};
use crate::io;

/// forward a request to the hypervisor uhyve
#[inline]
#[cfg(target_arch = "x86_64")]
fn uhyve_send<T>(port: u16, data: &mut T) {
let ptr = VirtAddr::from_ptr(ptr::from_mut(data));
let physical_address = paging::virtual_to_physical(ptr).unwrap();

unsafe {
outl(port, physical_address.as_u64() as u32);
}
}

/// forward a request to the hypervisor uhyve
#[inline]
#[cfg(target_arch = "aarch64")]
fn uhyve_send<T>(port: u16, data: &mut T) {
use core::arch::asm;

let ptr = VirtAddr::from_ptr(ptr::from_mut(data));
let physical_address = paging::virtual_to_physical(ptr).unwrap();

unsafe {
asm!(
"str x8, [{port}]",
port = in(reg) u64::from(port),
in("x8") physical_address.as_u64(),
options(nostack),
);
}
}

/// forward a request to the hypervisor uhyve
#[inline]
#[cfg(target_arch = "riscv64")]
fn uhyve_send<T>(_port: u16, _data: &mut T) {
todo!()
}

const UHYVE_PORT_WRITE: u16 = 0x400;
const UHYVE_PORT_OPEN: u16 = 0x440;
const UHYVE_PORT_CLOSE: u16 = 0x480;
const UHYVE_PORT_READ: u16 = 0x500;
const UHYVE_PORT_LSEEK: u16 = 0x580;
const UHYVE_PORT_UNLINK: u16 = 0x840;

#[repr(C, packed)]
struct SysOpen {
name: PhysAddr,
flags: i32,
mode: u32,
ret: i32,
}

impl SysOpen {
fn new(name: VirtAddr, flags: i32, mode: u32) -> SysOpen {
SysOpen {
name: paging::virtual_to_physical(name).unwrap(),
flags,
mode,
ret: -1,
}
}
}

#[repr(C, packed)]
struct SysClose {
fd: i32,
ret: i32,
}

impl SysClose {
fn new(fd: i32) -> SysClose {
SysClose { fd, ret: -1 }
}
}

#[repr(C, packed)]
struct SysRead {
fd: i32,
buf: *const u8,
len: usize,
ret: isize,
}

impl SysRead {
fn new(fd: i32, buf: *const u8, len: usize) -> SysRead {
SysRead {
fd,
buf,
len,
ret: -1,
}
}
}

#[repr(C, packed)]
struct SysWrite {
fd: i32,
buf: *const u8,
len: usize,
}

impl SysWrite {
pub fn new(fd: i32, buf: *const u8, len: usize) -> SysWrite {
SysWrite { fd, buf, len }
}
}

#[repr(C, packed)]
struct SysLseek {
pub fd: i32,
pub offset: isize,
pub whence: i32,
}

impl SysLseek {
fn new(fd: i32, offset: isize, whence: SeekWhence) -> SysLseek {
let whence: i32 = num::ToPrimitive::to_i32(&whence).unwrap();

SysLseek { fd, offset, whence }
}
}

#[repr(C, packed)]
struct SysUnlink {
name: PhysAddr,
ret: i32,
}

impl SysUnlink {
fn new(name: VirtAddr) -> SysUnlink {
SysUnlink {
name: paging::virtual_to_physical(name).unwrap(),
ret: -1,
}
}
}
use crate::syscalls::interfaces::uhyve::uhyve_hypercall;

#[derive(Debug)]
struct UhyveFileHandleInner(i32);
Expand All @@ -166,29 +29,42 @@ impl UhyveFileHandleInner {
}

fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
let mut sysread = SysRead::new(self.0, buf.as_mut_ptr(), buf.len());
uhyve_send(UHYVE_PORT_READ, &mut sysread);
let mut read_params = ReadParams {
fd: self.0,
buf: GuestVirtAddr::new(buf.as_mut_ptr() as u64),
len: buf.len(),
ret: 0,
};
uhyve_hypercall(Hypercall::FileRead(&mut read_params));

if sysread.ret >= 0 {
Ok(sysread.ret.try_into().unwrap())
if read_params.ret >= 0 {
Ok(read_params.ret.try_into().unwrap())
} else {
Err(io::Error::EIO)
}
}

fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
let mut syswrite = SysWrite::new(self.0, buf.as_ptr(), buf.len());
uhyve_send(UHYVE_PORT_WRITE, &mut syswrite);
let write_params = WriteParams {
fd: self.0,
buf: GuestVirtAddr::new(buf.as_ptr() as u64),
len: buf.len(),
};
uhyve_hypercall(Hypercall::FileWrite(&write_params));

Ok(syswrite.len)
Ok(write_params.len)
}

fn lseek(&self, offset: isize, whence: SeekWhence) -> io::Result<isize> {
let mut syslseek = SysLseek::new(self.0, offset, whence);
uhyve_send(UHYVE_PORT_LSEEK, &mut syslseek);
let mut lseek_params = LseekParams {
fd: self.0,
offset,
whence: num::ToPrimitive::to_i32(&whence).unwrap(),
};
uhyve_hypercall(Hypercall::FileLseek(&mut lseek_params));

if syslseek.offset >= 0 {
Ok(syslseek.offset)
if lseek_params.offset >= 0 {
Ok(lseek_params.offset)
} else {
Err(io::Error::EINVAL)
}
Expand All @@ -197,8 +73,12 @@ impl UhyveFileHandleInner {

impl Drop for UhyveFileHandleInner {
fn drop(&mut self) {
let mut sysclose = SysClose::new(self.0);
uhyve_send(UHYVE_PORT_CLOSE, &mut sysclose);
let mut close_params = CloseParams { fd: self.0, ret: 0 };
uhyve_hypercall(Hypercall::FileClose(&mut close_params));
if close_params.ret != 0 {
let ret = close_params.ret; // circumvent packed field access
panic!("Can't close fd {} - return value {ret}", self.0,);
}
}
}

Expand Down Expand Up @@ -274,11 +154,20 @@ impl VfsNode for UhyveDirectory {
path
};

let mut sysopen = SysOpen::new(VirtAddr::from_ptr(path.as_ptr()), opt.bits(), mode.bits());
uhyve_send(UHYVE_PORT_OPEN, &mut sysopen);
let mut open_params = OpenParams {
name: GuestPhysAddr::new(
paging::virtual_to_physical(VirtAddr::from_ptr(path.as_ptr()))
.unwrap()
.as_u64(),
),
flags: opt.bits(),
mode: mode.bits() as i32,
ret: -1,
};
uhyve_hypercall(Hypercall::FileOpen(&mut open_params));

if sysopen.ret > 0 {
Ok(Arc::new(UhyveFileHandle::new(sysopen.ret)))
if open_params.ret > 0 {
Ok(Arc::new(UhyveFileHandle::new(open_params.ret)))
} else {
Err(io::Error::EIO)
}
Expand All @@ -295,10 +184,17 @@ impl VfsNode for UhyveDirectory {
.collect()
};

let mut sysunlink = SysUnlink::new(VirtAddr::from_ptr(path.as_ptr()));
uhyve_send(UHYVE_PORT_UNLINK, &mut sysunlink);
let mut unlink_params = UnlinkParams {
name: GuestPhysAddr::new(
paging::virtual_to_physical(VirtAddr::from_ptr(path.as_ptr()))
.unwrap()
.as_u64(),
),
ret: -1,
};
uhyve_hypercall(Hypercall::FileUnlink(&mut unlink_params));

if sysunlink.ret == 0 {
if unlink_params.ret == 0 {
Ok(())
} else {
Err(io::Error::EIO)
Expand Down
Loading

0 comments on commit 12eebc9

Please sign in to comment.