diff --git a/Cargo.lock b/Cargo.lock index dfa0777..f3f0caf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -337,18 +337,3 @@ version = "0.1.0" [[package]] name = "user-manager" version = "0.1.0" - -[[package]] -name = "userspace" -version = "0.1.0" -dependencies = [ - "types", -] - -[[package]] -name = "userspace-rt" -version = "0.1.0" -dependencies = [ - "types", - "userspace", -] diff --git a/Cargo.toml b/Cargo.toml index 8bbea9c..fdbac26 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -39,8 +39,6 @@ members = [ "crates/servers/usb-server", "crates/servers/user-manager", "crates/types", - "crates/userspace", - "crates/userspace-rt", "crates/ports/framebuffer", "crates/ports/block-device", "crates/ports/input-device", @@ -66,8 +64,6 @@ elf = { path = "crates/elf" } platform = { path = "crates/platform" } kernel = { path = "crates/kernel" } server-framework = { path = "crates/server-framework" } -userspace = { path = "crates/userspace" } -userspace-rt = { path = "crates/userspace-rt" } # servers accessibility-server = { path = "crates/servers/accessibility-server" } diff --git a/crates/userspace-rt/Cargo.toml b/crates/userspace-rt/Cargo.toml deleted file mode 100644 index 4a75192..0000000 --- a/crates/userspace-rt/Cargo.toml +++ /dev/null @@ -1,8 +0,0 @@ -[package] -name = "userspace-rt" -version = "0.1.0" -edition = "2024" - -[dependencies] -types = { workspace = true } -userspace = { workspace = true } diff --git a/crates/userspace-rt/build.rs b/crates/userspace-rt/build.rs deleted file mode 100644 index c0935ae..0000000 --- a/crates/userspace-rt/build.rs +++ /dev/null @@ -1,5 +0,0 @@ -fn main() { - let ld = std::path::Path::new("linker.ld").canonicalize().unwrap(); - println!("cargo:rustc-link-arg=-T{}", ld.display()); - println!("cargo:rerun-if-changed=linker.ld"); -} diff --git a/crates/userspace-rt/linker.ld b/crates/userspace-rt/linker.ld deleted file mode 100644 index 5d2bb0c..0000000 --- a/crates/userspace-rt/linker.ld +++ /dev/null @@ -1,25 +0,0 @@ -OUTPUT_ARCH(riscv) -ENTRY(_start) - -SECTIONS { - . = 0x10000; - - .text : { - *(.text.entry) - *(.text .text.*) - } - - . = ALIGN(4096); - .rodata : { *(.rodata .rodata.*) } - - . = ALIGN(4096); - .data : { *(.data .data.*) } - - . = ALIGN(4096); - .bss : { - *(.bss .bss.*) - *(.sbss .sbss.*) - } - - /DISCARD/ : { *(.eh_frame) } -} diff --git a/crates/userspace-rt/src/arch/mod.rs b/crates/userspace-rt/src/arch/mod.rs deleted file mode 100644 index 963a1f1..0000000 --- a/crates/userspace-rt/src/arch/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -#[cfg(all(target_arch = "riscv64", target_os = "none"))] -mod riscv; diff --git a/crates/userspace-rt/src/arch/riscv.rs b/crates/userspace-rt/src/arch/riscv.rs deleted file mode 100644 index 169ba6d..0000000 --- a/crates/userspace-rt/src/arch/riscv.rs +++ /dev/null @@ -1,13 +0,0 @@ -use core::arch::global_asm; - -global_asm!( - r#" -.section .text.entry -.globl _start -_start: - call main - li a7, 16 - ecall - j _start -"# -); diff --git a/crates/userspace-rt/src/lib.rs b/crates/userspace-rt/src/lib.rs deleted file mode 100644 index f42c8b5..0000000 --- a/crates/userspace-rt/src/lib.rs +++ /dev/null @@ -1,12 +0,0 @@ -#![no_std] - -mod arch; - -pub use userspace::syscall; -pub use userspace::allocator::KosAllocator; - -#[cfg(target_os = "none")] -#[panic_handler] -fn panic(_: &core::panic::PanicInfo) -> ! { - userspace::syscall::exit(); -} diff --git a/crates/userspace/Cargo.toml b/crates/userspace/Cargo.toml deleted file mode 100644 index 6329ed9..0000000 --- a/crates/userspace/Cargo.toml +++ /dev/null @@ -1,7 +0,0 @@ -[package] -name = "userspace" -version = "0.1.0" -edition = "2024" - -[dependencies] -types = { workspace = true } diff --git a/crates/userspace/src/allocator/mod.rs b/crates/userspace/src/allocator/mod.rs deleted file mode 100644 index 2b5cd8a..0000000 --- a/crates/userspace/src/allocator/mod.rs +++ /dev/null @@ -1,144 +0,0 @@ -#[cfg(test)] -mod tests; - -use core::alloc::{GlobalAlloc, Layout}; -use core::cell::UnsafeCell; -use core::ptr; - -const PAGE_SIZE: usize = 4096; -const MAX_PAGES: usize = 64; - -struct FreeBlock { - size: usize, - next: *mut FreeBlock, -} - -pub struct KosAllocator { - inner: UnsafeCell, -} - -struct AllocatorInner { - free_list: *mut FreeBlock, - pages: [usize; MAX_PAGES], - page_count: usize, -} - -unsafe impl Sync for KosAllocator {} - -impl KosAllocator { - pub const fn new() -> Self { - Self { - inner: UnsafeCell::new(AllocatorInner { - free_list: ptr::null_mut(), - pages: [0; MAX_PAGES], - page_count: 0, - }), - } - } - - fn inner_mut(&self) -> &mut AllocatorInner { - unsafe { &mut *self.inner.get() } - } -} - -impl AllocatorInner { - fn request_page(&mut self) -> *mut u8 { - if self.page_count >= MAX_PAGES { - return ptr::null_mut(); - } - - let count = match types::bounded::PageCount::new(1) { - Some(c) => c, - None => return ptr::null_mut(), - }; - let va = match crate::syscall::request_pages(count) { - Some(va) => va, - None => return ptr::null_mut(), - }; - - self.pages[self.page_count] = va.raw(); - self.page_count += 1; - va.raw() as *mut u8 - } - - fn alloc_from_free_list(&mut self, size: usize, align: usize) -> *mut u8 { - let mut prev: *mut FreeBlock = ptr::null_mut(); - let mut current = self.free_list; - - while !current.is_null() { - let block = unsafe { &mut *current }; - let addr = current as usize; - let aligned = (addr + align - 1) & !(align - 1); - let padding = aligned - addr; - - if block.size >= size + padding { - let remaining = block.size - size - padding; - - if remaining >= core::mem::size_of::() { - let new_block = (aligned + size) as *mut FreeBlock; - unsafe { - (*new_block).size = remaining; - (*new_block).next = block.next; - } - if prev.is_null() { - self.free_list = new_block; - } else { - unsafe { (*prev).next = new_block; } - } - } else { - if prev.is_null() { - self.free_list = block.next; - } else { - unsafe { (*prev).next = block.next; } - } - } - - return aligned as *mut u8; - } - - prev = current; - current = block.next; - } - - ptr::null_mut() - } - - fn add_to_free_list(&mut self, ptr: *mut u8, size: usize) { - let block = ptr as *mut FreeBlock; - unsafe { - (*block).size = size; - (*block).next = self.free_list; - } - self.free_list = block; - } -} - -unsafe impl GlobalAlloc for KosAllocator { - unsafe fn alloc(&self, layout: Layout) -> *mut u8 { - let inner = self.inner_mut(); - let size = layout.size().max(core::mem::size_of::()); - let align = layout.align(); - - let ptr = inner.alloc_from_free_list(size, align); - if !ptr.is_null() { - return ptr; - } - - let pages_needed = (size + PAGE_SIZE - 1) / PAGE_SIZE; - for _ in 0..pages_needed { - let page = inner.request_page(); - if page.is_null() { - return ptr::null_mut(); - } - inner.add_to_free_list(page, PAGE_SIZE); - } - - inner.alloc_from_free_list(size, align) - } - - unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { - let inner = self.inner_mut(); - let size = layout.size().max(core::mem::size_of::()); - inner.add_to_free_list(ptr, size); - } -} diff --git a/crates/userspace/src/allocator/tests.rs b/crates/userspace/src/allocator/tests.rs deleted file mode 100644 index 05741b9..0000000 --- a/crates/userspace/src/allocator/tests.rs +++ /dev/null @@ -1,81 +0,0 @@ -use super::*; -use core::alloc::Layout; - -#[test] -fn allocator_creates_successfully() { - let _alloc = KosAllocator::new(); -} - -#[test] -fn free_list_operations() { - let alloc = KosAllocator::new(); - let inner = alloc.inner_mut(); - - // Simulate a page by using a stack buffer - let mut page = [0u8; 4096]; - let page_ptr = page.as_mut_ptr(); - - inner.add_to_free_list(page_ptr, 4096); - assert!(!inner.free_list.is_null()); - - let ptr = inner.alloc_from_free_list(64, 8); - assert!(!ptr.is_null()); -} - -#[test] -fn alloc_dealloc_roundtrip() { - let alloc = KosAllocator::new(); - let inner = alloc.inner_mut(); - - let mut page = [0u8; 4096]; - inner.add_to_free_list(page.as_mut_ptr(), 4096); - - let layout = Layout::from_size_align(128, 8).unwrap(); - let ptr = inner.alloc_from_free_list(128, 8); - assert!(!ptr.is_null()); - - inner.add_to_free_list(ptr, 128); - let ptr2 = inner.alloc_from_free_list(64, 8); - assert!(!ptr2.is_null()); -} - -#[test] -fn multiple_allocations_from_one_page() { - let alloc = KosAllocator::new(); - let inner = alloc.inner_mut(); - - let mut page = [0u8; 4096]; - inner.add_to_free_list(page.as_mut_ptr(), 4096); - - let p1 = inner.alloc_from_free_list(256, 8); - let p2 = inner.alloc_from_free_list(256, 8); - let p3 = inner.alloc_from_free_list(256, 8); - - assert!(!p1.is_null()); - assert!(!p2.is_null()); - assert!(!p3.is_null()); - assert_ne!(p1, p2); - assert_ne!(p2, p3); -} - -#[test] -fn alignment_respected() { - let alloc = KosAllocator::new(); - let inner = alloc.inner_mut(); - - let mut page = [0u8; 4096]; - inner.add_to_free_list(page.as_mut_ptr(), 4096); - - let ptr = inner.alloc_from_free_list(64, 64); - assert!(!ptr.is_null()); - assert_eq!(ptr as usize % 64, 0); -} - -#[test] -fn exhausted_free_list_returns_null() { - let alloc = KosAllocator::new(); - let inner = alloc.inner_mut(); - - let ptr = inner.alloc_from_free_list(64, 8); - assert!(ptr.is_null()); -} diff --git a/crates/userspace/src/arch/mock.rs b/crates/userspace/src/arch/mock.rs deleted file mode 100644 index 4aef986..0000000 --- a/crates/userspace/src/arch/mock.rs +++ /dev/null @@ -1,27 +0,0 @@ -pub fn syscall0(_nr: usize) -> usize { - 0 -} - -pub fn syscall1(_nr: usize, _a0: usize) -> usize { - 0 -} - -pub fn syscall2(_nr: usize, _a0: usize, _a1: usize) -> usize { - 0 -} - -pub fn syscall3(_nr: usize, _a0: usize, _a1: usize, _a2: usize) -> usize { - 0 -} - -pub fn syscall4(_nr: usize, _a0: usize, _a1: usize, _a2: usize, _a3: usize) -> usize { - 0 -} - -pub fn syscall5(_nr: usize, _a0: usize, _a1: usize, _a2: usize, _a3: usize, _a4: usize) -> usize { - 0 -} - -pub fn syscall_receive(_nr: usize, _a0: usize) -> (usize, usize, usize, usize) { - (0, 0, 0, 0) -} diff --git a/crates/userspace/src/arch/mod.rs b/crates/userspace/src/arch/mod.rs deleted file mode 100644 index 35687a5..0000000 --- a/crates/userspace/src/arch/mod.rs +++ /dev/null @@ -1,9 +0,0 @@ -#[cfg(all(target_arch = "riscv64", target_os = "none"))] -mod riscv; -#[cfg(all(target_arch = "riscv64", target_os = "none"))] -pub use riscv::*; - -#[cfg(not(target_os = "none"))] -mod mock; -#[cfg(not(target_os = "none"))] -pub use mock::*; diff --git a/crates/userspace/src/arch/riscv.rs b/crates/userspace/src/arch/riscv.rs deleted file mode 100644 index 60ba1b2..0000000 --- a/crates/userspace/src/arch/riscv.rs +++ /dev/null @@ -1,106 +0,0 @@ -#[inline(always)] -pub fn syscall0(nr: usize) -> usize { - let ret: usize; - unsafe { - core::arch::asm!( - "ecall", - in("a7") nr, - lateout("a0") ret, - ); - } - ret -} - -#[inline(always)] -pub fn syscall1(nr: usize, a0: usize) -> usize { - let ret: usize; - unsafe { - core::arch::asm!( - "ecall", - in("a7") nr, - inlateout("a0") a0 => ret, - ); - } - ret -} - -#[inline(always)] -pub fn syscall2(nr: usize, a0: usize, a1: usize) -> usize { - let ret: usize; - unsafe { - core::arch::asm!( - "ecall", - in("a7") nr, - inlateout("a0") a0 => ret, - in("a1") a1, - ); - } - ret -} - -#[inline(always)] -pub fn syscall3(nr: usize, a0: usize, a1: usize, a2: usize) -> usize { - let ret: usize; - unsafe { - core::arch::asm!( - "ecall", - in("a7") nr, - inlateout("a0") a0 => ret, - in("a1") a1, - in("a2") a2, - ); - } - ret -} - -#[inline(always)] -pub fn syscall4(nr: usize, a0: usize, a1: usize, a2: usize, a3: usize) -> usize { - let ret: usize; - unsafe { - core::arch::asm!( - "ecall", - in("a7") nr, - inlateout("a0") a0 => ret, - in("a1") a1, - in("a2") a2, - in("a3") a3, - ); - } - ret -} - -#[inline(always)] -pub fn syscall5(nr: usize, a0: usize, a1: usize, a2: usize, a3: usize, a4: usize) -> usize { - let ret: usize; - unsafe { - core::arch::asm!( - "ecall", - in("a7") nr, - inlateout("a0") a0 => ret, - in("a1") a1, - in("a2") a2, - in("a3") a3, - in("a4") a4, - ); - } - ret -} - -#[inline(always)] -pub fn syscall_receive(nr: usize, a0: usize) -> (usize, usize, usize, usize) { - let r0: usize; - let r1: usize; - let r2: usize; - let r3: usize; - unsafe { - core::arch::asm!( - "ecall", - in("a7") nr, - inlateout("a0") a0 => r0, - lateout("a1") r1, - lateout("a2") r2, - lateout("a3") r3, - ); - } - (r0, r1, r2, r3) -} diff --git a/crates/userspace/src/lib.rs b/crates/userspace/src/lib.rs deleted file mode 100644 index 3fee153..0000000 --- a/crates/userspace/src/lib.rs +++ /dev/null @@ -1,5 +0,0 @@ -#![no_std] - -pub mod allocator; -mod arch; -pub mod syscall; diff --git a/crates/userspace/src/syscall.rs b/crates/userspace/src/syscall.rs deleted file mode 100644 index 1299eb6..0000000 --- a/crates/userspace/src/syscall.rs +++ /dev/null @@ -1,85 +0,0 @@ -use crate::arch; -use types::syscall_abi::*; -use types::address::{EntryPoint, StackPointer, VirtualAddress}; -use types::bounded::{CapSlot, PageCount}; -use types::id::ProcessId; -use types::permission::PermissionSet; -use types::time::Ticks; - -pub fn exit() -> ! { - arch::syscall0(SYS_EXIT); - loop {} -} - -pub fn exit_thread() -> ! { - arch::syscall0(SYS_EXIT_THREAD); - loop {} -} - -pub fn yield_now() { - arch::syscall0(SYS_YIELD); -} - -pub fn halt() -> ! { - arch::syscall0(SYS_HALT); - loop {} -} - -pub fn get_time() -> Ticks { - Ticks::from_raw(arch::syscall0(SYS_GET_TIME) as u64) -} - -pub fn get_process_id() -> ProcessId { - ProcessId::from_raw(arch::syscall0(SYS_GET_PROCESS_ID) as u16) -} - -pub fn create_process(create_cap: CapSlot) -> Option { - let r = arch::syscall1(SYS_CREATE_PROCESS, create_cap.value() as usize); - if r == usize::MAX { None } else { CapSlot::new(r as u8) } -} - -pub fn create_endpoint() -> Option { - let r = arch::syscall0(SYS_CREATE_ENDPOINT); - if r == usize::MAX { None } else { CapSlot::new(r as u8) } -} - -pub fn spawn_thread(entry: EntryPoint, stack: StackPointer) -> usize { - arch::syscall2(SYS_SPAWN_THREAD, entry.raw(), stack.raw()) -} - -pub fn spawn_thread_in(process_cap: CapSlot, entry: EntryPoint, stack: StackPointer) -> usize { - arch::syscall3(SYS_SPAWN_THREAD_IN, process_cap.value() as usize, entry.raw(), stack.raw()) -} - -pub fn request_pages(count: PageCount) -> Option { - let r = arch::syscall1(SYS_REQUEST_PAGES, count.value() as usize); - if r == usize::MAX { None } else { Some(VirtualAddress::from_raw(r)) } -} - -pub fn map_page(process_cap: CapSlot, src_va: VirtualAddress, dst_va: VirtualAddress, executable: bool) -> bool { - arch::syscall4(SYS_MAP_PAGE, process_cap.value() as usize, src_va.raw(), dst_va.raw(), executable as usize) == 0 -} - -pub fn send(endpoint: CapSlot, w0: usize, w1: usize, w2: usize, w3: usize) -> usize { - arch::syscall5(SYS_SEND, endpoint.value() as usize, w0, w1, w2, w3) -} - -pub fn receive(endpoint: CapSlot) -> (usize, usize, usize, usize) { - arch::syscall_receive(SYS_RECEIVE, endpoint.value() as usize) -} - -pub fn delegate(slot: CapSlot, to: CapSlot, permissions: PermissionSet) -> bool { - arch::syscall3(SYS_DELEGATE, slot.value() as usize, to.value() as usize, permissions.bits() as usize) == 0 -} - -pub fn kill(process_cap: CapSlot) -> bool { - arch::syscall1(SYS_KILL, process_cap.value() as usize) == 0 -} - -pub fn revoke(slot: CapSlot) -> bool { - arch::syscall1(SYS_REVOKE, slot.value() as usize) == 0 -} - -pub fn debug_putchar(byte: u8) { - arch::syscall1(SYS_DEBUG_PUTCHAR, byte as usize); -}