Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use hypercall definitions from uhyve-interface #1393

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -132,6 +132,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.12"
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
Loading