diff --git a/src/lib/twizzler-abi/Cargo.toml b/src/lib/twizzler-abi/Cargo.toml index a7a90e85..52678b0f 100644 --- a/src/lib/twizzler-abi/Cargo.toml +++ b/src/lib/twizzler-abi/Cargo.toml @@ -15,6 +15,8 @@ bitset-core = { version = "0.1", optional = true, default-features = false } cfg-if = "1.0" num_enum = { version = "0.7", default-features = false } thiserror = { package = "thiserror-no-std", version = "2.0", default-features = false } +stable-vec = "0.4.1" +lazy_static = { version = "1.5.0", features = ["spin_no_std"] } [dependencies.volatile] optional = true diff --git a/src/lib/twizzler-abi/src/runtime/fs.rs b/src/lib/twizzler-abi/src/runtime/fs.rs index 6cd48a1e..168be496 100644 --- a/src/lib/twizzler-abi/src/runtime/fs.rs +++ b/src/lib/twizzler-abi/src/runtime/fs.rs @@ -19,7 +19,10 @@ use core::{intrinsics::size_of, ptr::NonNull}; use rustc_alloc::{borrow::ToOwned, sync::Arc}; use crate::runtime::object::slot; -use twizzler_runtime_api::{OwnedFd, FsError, SeekFrom}; +use twizzler_runtime_api::{RawFd, FsError, SeekFrom}; + +use stable_vec::{self, StableVec}; +use lazy_static::lazy_static; struct FileDesc { slot_id: u32, @@ -37,15 +40,16 @@ struct FileMetadata { const MAGIC_NUMBER: u64 = 0xBEEFDEAD; -static FD_SLOTS: Mutex>>> = Mutex::new(BTreeMap::new()); -static FD_ID_COUNTER: IdCounter = IdCounter::new_one(); +lazy_static! { + static ref FD_SLOTS: Mutex>>> = Mutex::new(StableVec::new()); +} -fn get_fd_slots() -> &'static Mutex>>> { +fn get_fd_slots() -> &'static Mutex>>> { &FD_SLOTS } impl RustFsRuntime for MinimalRuntime { - fn open(&self, path: &core::ffi::CStr) -> Result { + fn open(&self, path: &core::ffi::CStr) -> Result { let obj_id = ObjID::new( path .to_str() @@ -66,63 +70,60 @@ impl RustFsRuntime for MinimalRuntime { } }; } - let fd = FD_ID_COUNTER.fresh(); - get_fd_slots() + let fd = get_fd_slots() .lock() - .insert(fd, Arc::new(Mutex::new(FileDesc { + .push(Arc::new(Mutex::new(FileDesc { slot_id: 0, pos: 0, handle: handle }))); - - Ok (OwnedFd{ - internal_fd: fd - }) + + Ok (fd.try_into().unwrap()) } - fn read(&self, fd: OwnedFd, buf: *mut u8, len: usize) -> Result { + fn read(&self, fd: RawFd, buf: &mut [u8]) -> Result { let binding = get_fd_slots() .lock(); let mut file_desc = binding - .get(&fd.internal_fd) + .get(fd.try_into().unwrap()) .ok_or(FsError::LookupError)?; let mut binding = file_desc.lock(); - unsafe { buf.copy_from(binding.handle.start.offset(NULLPAGE_SIZE as isize + binding.pos as isize + size_of::() as isize), len) } + unsafe { buf.as_mut_ptr().copy_from(binding.handle.start.offset(NULLPAGE_SIZE as isize + binding.pos as isize + size_of::() as isize), buf.len()) } - binding.pos += len as u64; + binding.pos += buf.len() as u64; - Ok(len) + Ok(buf.len()) } - fn write(&self, fd: OwnedFd, buf: *const u8, len: usize) -> Result { + fn write(&self, fd: RawFd, buf: &[u8]) -> Result { let binding = get_fd_slots() .lock(); let file_desc = binding - .get(&fd.internal_fd) + .get(fd.try_into().unwrap()) .ok_or(FsError::LookupError)?; let mut binding = file_desc.lock(); - unsafe { + unsafe { binding.handle.start .offset(NULLPAGE_SIZE as isize + binding.pos as isize + size_of::() as isize) - .copy_from(buf, len) + .copy_from(buf.as_ptr(), buf.len()) } - binding.pos += len as u64; + binding.pos += buf.len() as u64; - Ok(len) + Ok(buf.len()) } - fn close(&self, fd: OwnedFd) -> Result<(), FsError> { + fn close(&self, fd: RawFd) -> Result<(), FsError> { let file_desc = get_fd_slots() .lock() - .remove(&fd.internal_fd) + .remove(fd.try_into().unwrap()) .ok_or(FsError::LookupError)?; let mut binding = file_desc.lock(); @@ -132,13 +133,13 @@ impl RustFsRuntime for MinimalRuntime { Ok(()) } - fn seek(&self, fd: OwnedFd, pos: SeekFrom) -> Result { + fn seek(&self, fd: RawFd, pos: SeekFrom) -> Result { let binding = get_fd_slots() .lock(); let file_desc = binding - .get(&fd.internal_fd) + .get(fd.try_into().unwrap()) .ok_or(FsError::LookupError)?; let mut binding = file_desc.lock(); diff --git a/src/lib/twizzler-runtime-api/src/lib.rs b/src/lib/twizzler-runtime-api/src/lib.rs index f778e142..15598f7d 100644 --- a/src/lib/twizzler-runtime-api/src/lib.rs +++ b/src/lib/twizzler-runtime-api/src/lib.rs @@ -498,11 +498,27 @@ pub struct BasicReturn { pub enum FsError { /// Error is unclassified. Other, + // Path provided isn't a valid u128 integer InvalidPath, // Couldn't find the file descriptor - LookupError + LookupError, + // Seek Error + SeekError, +} + +impl Display for FsError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + FsError::Other => write!(f, "unknown error"), + FsError::InvalidPath => write!(f, "Path is invalid"), + FsError::LookupError => write!(f, "Couldn't find file descriptor"), + FsError::SeekError => write!(f, "Couldn't seek to this position"), + } + } } +impl core::error::Error for FsError {} + #[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq, Hash)] pub enum SeekFrom { Start(u64), @@ -510,31 +526,19 @@ pub enum SeekFrom { Current(i64), } - -#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq, Hash)] -pub struct OwnedFd { - pub internal_fd: u32 -} - -/*impl core::fmt::Debug for OwnedFd { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - f.debug_struct("OwnedFd") - .field("internal_fd", &self.internal_fd) - .finish() - } -}*/ +pub type RawFd = u32; /// Runtime that implements std's FS support. Currently being implemented. pub trait RustFsRuntime { - fn open(&self, path: &CStr) -> Result; + fn open(&self, path: &CStr) -> Result; - fn read(&self, fd: OwnedFd, buf: *mut u8, len: usize) -> Result; + fn read(&self, fd: RawFd, buf: &mut [u8]) -> Result; - fn write(&self, fd: OwnedFd, buf: *const u8, len: usize) -> Result; + fn write(&self, fd: RawFd, buf: &[u8]) -> Result; - fn close(&self, fd: OwnedFd) -> Result<(), FsError>; + fn close(&self, fd: RawFd) -> Result<(), FsError>; - fn seek(&self, fd: OwnedFd, pos: SeekFrom) -> Result; + fn seek(&self, fd: RawFd, pos: SeekFrom) -> Result; } /// Runtime that implements std's process and command support. Currently unimplemented. diff --git a/src/runtime/twz-rt/Cargo.toml b/src/runtime/twz-rt/Cargo.toml index 3e701ea5..14ccc384 100644 --- a/src/runtime/twz-rt/Cargo.toml +++ b/src/runtime/twz-rt/Cargo.toml @@ -22,7 +22,7 @@ elf = "0.7" static_assertions = "1.1" monitor-api = { path = "../monitor-api" } secgate = { path = "../secgate" } - +stable-vec = "0.4.1" [features] runtime = [] diff --git a/src/runtime/twz-rt/src/runtime/file.rs b/src/runtime/twz-rt/src/runtime/file.rs index d38c2545..e63bc6b3 100644 --- a/src/runtime/twz-rt/src/runtime/file.rs +++ b/src/runtime/twz-rt/src/runtime/file.rs @@ -1,8 +1,7 @@ +use super::ReferenceRuntime; + use atomic::Atomic; use dynlink::engines::twizzler; -use twizzler_runtime_api::RustFsRuntime; - -use super::ReferenceRuntime; use twizzler_abi::{ object::{ObjID, Protections, MAX_SIZE, NULLPAGE_SIZE}, @@ -23,7 +22,10 @@ use std::sync::Mutex; use atomic::Ordering; use twizzler_abi::slot; -use twizzler_runtime_api::{OwnedFd, FsError, SeekFrom}; +use twizzler_runtime_api::{RustFsRuntime, RawFd, FsError, SeekFrom}; + +use stable_vec::{self, StableVec}; +use lazy_static::lazy_static; struct FileDesc { slot_id: u32, @@ -32,6 +34,7 @@ struct FileDesc { } #[repr(C)] +#[derive(Clone, Copy)] struct FileMetadata { magic: u64, size: u64, @@ -40,15 +43,16 @@ struct FileMetadata { const MAGIC_NUMBER: u64 = 0xBEEFDEAD; -static FD_SLOTS: Mutex>>> = Mutex::new(BTreeMap::new()); -static FD_ID_COUNTER: AtomicU32 = AtomicU32::new(1); +lazy_static! { + static ref FD_SLOTS: Mutex>>> = Mutex::new(StableVec::new()); +} -fn get_fd_slots() -> &'static Mutex>>> { +fn get_fd_slots() -> &'static Mutex>>> { &FD_SLOTS } impl RustFsRuntime for ReferenceRuntime { - fn open(&self, path: &core::ffi::CStr) -> Result { + fn open(&self, path: &core::ffi::CStr) -> Result { let obj_id = ObjID::new( path .to_str() @@ -60,95 +64,87 @@ impl RustFsRuntime for ReferenceRuntime { let handle = self.map_object(obj_id, flags).unwrap(); - let mut metadata_handle = unsafe{ &mut *handle.start.cast::() }; - if metadata_handle.magic != MAGIC_NUMBER { - metadata_handle = &mut FileMetadata { + let mut metadata_handle = unsafe{ handle.start.offset(NULLPAGE_SIZE as isize).cast::() }; + if (unsafe { *metadata_handle }).magic != MAGIC_NUMBER { + unsafe { *metadata_handle = FileMetadata { magic: MAGIC_NUMBER, size: 0, direct: [0; 10], - }; + } }; } - let fd = FD_ID_COUNTER.fetch_add(1, Ordering::SeqCst); - get_fd_slots() + let fd = get_fd_slots() .lock() .unwrap() - .insert(fd, Arc::new(Mutex::new(FileDesc { + .push(Arc::new(Mutex::new(FileDesc { slot_id: 0, pos: 0, handle: handle }))); - - Ok (OwnedFd{ - internal_fd: fd - }) + + Ok (fd.try_into().unwrap()) } - fn read(&self, fd: OwnedFd, buf: *mut u8, len: usize) -> Result { + fn read(&self, fd: RawFd, buf: &mut [u8]) -> Result { let binding = get_fd_slots() - .lock() - .unwrap(); + .lock().unwrap(); let mut file_desc = binding - .get(&fd.internal_fd) + .get(fd.try_into().unwrap()) .ok_or(FsError::LookupError)?; let mut binding = file_desc.lock().unwrap(); - unsafe { buf.copy_from(binding.handle.start.offset(binding.pos as isize + size_of::() as isize), len) } + unsafe { buf.as_mut_ptr().copy_from(binding.handle.start.offset(NULLPAGE_SIZE as isize + binding.pos as isize + size_of::() as isize), buf.len()) } - binding.pos += len as u64; + binding.pos += buf.len() as u64; - Ok(len) + Ok(buf.len()) } - fn write(&self, fd: OwnedFd, buf: *const u8, len: usize) -> Result { + fn write(&self, fd: RawFd, buf: &[u8]) -> Result { let binding = get_fd_slots() - .lock() - .unwrap(); + .lock().unwrap(); let file_desc = binding - .get(&fd.internal_fd) + .get(fd.try_into().unwrap()) .ok_or(FsError::LookupError)?; let mut binding = file_desc.lock().unwrap(); - unsafe { + unsafe { binding.handle.start - .offset(binding.pos as isize + size_of::() as isize) - .copy_from(buf, len) + .offset(NULLPAGE_SIZE as isize + binding.pos as isize + size_of::() as isize) + .copy_from(buf.as_ptr(), buf.len()) } - binding.pos += len as u64; + binding.pos += buf.len() as u64; - Ok(len) + Ok(buf.len()) } - fn close(&self, fd: OwnedFd) -> Result<(), FsError> { + fn close(&self, fd: RawFd) -> Result<(), FsError> { let file_desc = get_fd_slots() .lock() .unwrap() - .remove(&fd.internal_fd) + .remove(fd.try_into().unwrap()) .ok_or(FsError::LookupError)?; - let mut binding = file_desc - .lock() - .unwrap(); + let mut binding = file_desc.lock().unwrap(); self.release_handle(&mut binding.handle); Ok(()) } - fn seek(&self, fd: OwnedFd, pos: SeekFrom) -> Result { + fn seek(&self, fd: RawFd, pos: SeekFrom) -> Result { let binding = get_fd_slots() - .lock() - .unwrap(); + .lock().unwrap(); let file_desc = binding - .get(&fd.internal_fd) + .get(fd.try_into().unwrap()) .ok_or(FsError::LookupError)?; let mut binding = file_desc.lock().unwrap(); @@ -161,10 +157,11 @@ impl RustFsRuntime for ReferenceRuntime { }; if new_pos > metadata_handle.size.try_into().unwrap() || new_pos < 0 { - Err(FsError::LookupError) + Err(FsError::SeekError) } else { binding.pos = new_pos as u64; - Ok(binding.pos.try_into().unwrap()) + Ok(binding.pos.try_into().unwrap()) } } -} \ No newline at end of file +} + diff --git a/toolchain/src/rust b/toolchain/src/rust index 96cf961f..ce7a391b 160000 --- a/toolchain/src/rust +++ b/toolchain/src/rust @@ -1 +1 @@ -Subproject commit 96cf961f30b249ec08007ea78cba4f01bef5802b +Subproject commit ce7a391b6c269c6beabd5c3fd332525b56d9047e