feat: userspace program loading and task spawning

This commit is contained in:
Zoe
2026-09-07 08:24:46 -05:00
parent 028ac8fb13
commit 3308fd2959
28 changed files with 1605 additions and 676 deletions
+167 -4
View File
@@ -12,6 +12,14 @@ pub enum Status {
OutOfMemory = 5,
}
// Opaque handle type
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Handle(usize);
// our own address space and thread handle are always given to us
pub const SELF_AS: Handle = Handle(0);
pub const SELF_THREAD: Handle = Handle(1);
impl From<usize> for Status {
fn from(value: usize) -> Self {
match value {
@@ -25,6 +33,21 @@ impl From<usize> for Status {
}
}
#[repr(u64)]
pub enum SyscallNumber {
Yield = 1,
Exit = 2,
Write = 3,
Send = 4,
Recv = 5,
FrameAlloc = 6,
FrameDealloc = 7,
AsCreate = 8,
Map = 9,
Unmap = 10,
TaskCreate = 11,
}
pub fn sys_yield() {
unsafe {
asm!(
@@ -46,7 +69,7 @@ fn debug_write(buf: &str) -> Result<(), Status> {
in("rsi") buf.as_ptr(),
in("rdx") buf.len(),
in("r10") 0,
inlateout("rax") 3usize => status,
inlateout("rax") SyscallNumber::Write as usize => status,
lateout("rcx") _,
lateout("r11") _
);
@@ -96,7 +119,7 @@ pub fn sys_exit(exit_code: usize) -> ! {
asm!(
"syscall",
in("rdi") exit_code,
in("rax") 2usize,
in("rax") SyscallNumber::Exit as usize,
options(noreturn)
);
}
@@ -111,7 +134,7 @@ pub fn sys_send(dest_task_id: usize, msg_ptr: usize, len: usize) -> Result<(), S
in("rdi") dest_task_id,
in("rsi") msg_ptr,
in("rdx") len,
inlateout("rax") 4usize => status,
inlateout("rax") SyscallNumber::Send as usize => status,
lateout("rcx") _,
lateout("r11") _,
);
@@ -137,7 +160,7 @@ pub fn sys_recv(buf_ptr: usize, max_len: usize) -> Result<(usize, usize), Status
in("rsi") max_len,
in("rdx") &raw mut actual_len as usize,
in("r10") &raw mut sender as usize,
inlateout("rax") 5usize => status,
inlateout("rax") SyscallNumber::Recv as usize => status,
lateout("rcx") _,
lateout("r11") _,
);
@@ -149,3 +172,143 @@ pub fn sys_recv(buf_ptr: usize, max_len: usize) -> Result<(usize, usize), Status
}
}
}
pub fn sys_frame_alloc() -> Result<Handle, Status> {
let mut handle: usize = 0;
unsafe {
let status: usize;
asm!(
"syscall",
in("rdi") &raw mut handle as usize,
inlateout("rax") SyscallNumber::FrameAlloc as usize => status,
lateout("rcx") _,
lateout("r11") _,
);
if status != 0 {
Err(status.into())
} else {
Ok(Handle(handle))
}
}
}
pub fn sys_frame_dealloc(frame_handle: Handle) -> Result<(), Status> {
unsafe {
let status: usize;
asm!(
"syscall",
in("rdi") frame_handle.0,
inlateout("rax") SyscallNumber::FrameDealloc as usize => status,
lateout("rcx") _,
lateout("r11") _,
);
if status != 0 {
Err(status.into())
} else {
Ok(())
}
}
}
pub fn sys_as_create() -> Result<Handle, Status> {
let mut handle: usize = 0;
unsafe {
let status: usize;
asm!(
"syscall",
in("rdi") &raw mut handle as usize,
inlateout("rax") SyscallNumber::AsCreate as usize => status,
lateout("rcx") _,
lateout("r11") _,
);
if status != 0 {
Err(status.into())
} else {
Ok(Handle(handle))
}
}
}
pub fn sys_map(
as_handle: Handle,
frame_handle: Handle,
virtual_addr: usize,
permissions: usize,
) -> Result<(), Status> {
unsafe {
let status: usize;
asm!(
"syscall",
in("rdi") as_handle.0,
in("rsi") frame_handle.0,
in("rdx") virtual_addr,
in("r10") permissions,
inlateout("rax") SyscallNumber::Map as usize => status,
lateout("rcx") _,
lateout("r11") _,
);
if status != 0 {
Err(status.into())
} else {
Ok(())
}
}
}
pub fn sys_unmap(as_handle: Handle, virtual_addr: usize) -> Result<(), Status> {
unsafe {
let status: usize;
asm!(
"syscall",
in("rdi") as_handle.0,
in("rsi") virtual_addr,
inlateout("rax") SyscallNumber::Unmap as usize => status,
lateout("rcx") _,
lateout("r11") _,
);
if status != 0 {
Err(status.into())
} else {
Ok(())
}
}
}
pub fn sys_task_create(
as_handle: Handle,
entry: usize,
user_stack: usize,
) -> Result<Handle, Status> {
let mut handle: usize = 0;
unsafe {
let status: usize;
asm!(
"syscall",
in("rdi") as_handle.0,
in("rsi") entry,
in("rdx") user_stack,
in("r10") &raw mut handle as usize,
inlateout("rax") SyscallNumber::TaskCreate as usize => status,
lateout("rcx") _,
lateout("r11") _,
);
if status != 0 {
Err(status.into())
} else {
Ok(Handle(handle))
}
}
}