167 lines
4.7 KiB
Rust
167 lines
4.7 KiB
Rust
//! System function call handlers
|
|
use core::time::Duration;
|
|
|
|
use abi::{
|
|
error::Error,
|
|
io::{OpenFlags, RawFd},
|
|
syscall::SyscallFunction,
|
|
};
|
|
use vfs::{Read, Write};
|
|
use yggdrasil_abi::{
|
|
error::SyscallResult,
|
|
io::{MountOptions, UnmountOptions},
|
|
};
|
|
|
|
use crate::{
|
|
fs,
|
|
mem::table::{PageAttributes, VirtualMemoryManager},
|
|
proc::wait,
|
|
task::process::Process,
|
|
};
|
|
|
|
mod arg;
|
|
use arg::*;
|
|
|
|
fn syscall_handler(func: SyscallFunction, args: &[u64]) -> Result<usize, Error> {
|
|
match func {
|
|
SyscallFunction::DebugTrace => {
|
|
let pid = Process::get_current()
|
|
.as_deref()
|
|
.map(Process::id)
|
|
.unwrap_or(0);
|
|
let arg = arg_user_str(args[0] as usize, args[1] as usize)?;
|
|
debugln!("[{}] TRACE: {:?}", pid, arg);
|
|
|
|
Ok(0)
|
|
}
|
|
SyscallFunction::Nanosleep => {
|
|
let seconds = args[0];
|
|
let nanos = args[1] as u32;
|
|
let duration = Duration::new(seconds, nanos);
|
|
let mut remaining = Duration::ZERO;
|
|
|
|
wait::sleep(duration, &mut remaining).unwrap();
|
|
|
|
Ok(0)
|
|
}
|
|
SyscallFunction::Exit => {
|
|
Process::current().exit(args[0] as _);
|
|
panic!();
|
|
}
|
|
SyscallFunction::MapMemory => {
|
|
let len = args[1] as usize;
|
|
|
|
let proc = Process::current();
|
|
let space = proc.address_space();
|
|
|
|
if len & 0xFFF != 0 {
|
|
todo!();
|
|
}
|
|
|
|
let addr = space.allocate(None, len / 0x1000, PageAttributes::AP_BOTH_READWRITE);
|
|
debugln!("mmap({:#x}) = {:x?}", len, addr);
|
|
|
|
addr
|
|
}
|
|
SyscallFunction::UnmapMemory => {
|
|
let addr = args[0] as usize;
|
|
let len = args[1] as usize;
|
|
|
|
let proc = Process::current();
|
|
let space = proc.address_space();
|
|
|
|
if len & 0xFFF != 0 {
|
|
todo!();
|
|
}
|
|
|
|
debugln!("munmap({:#x}, {:#x})", addr, len);
|
|
space.deallocate(addr, len)?;
|
|
|
|
Ok(0)
|
|
}
|
|
SyscallFunction::Write => {
|
|
let fd = RawFd(args[0] as u32);
|
|
let data = arg_buffer_ref(args[1] as _, args[2] as _)?;
|
|
|
|
let proc = Process::current();
|
|
let io = proc.io.lock();
|
|
let file = io.file(fd)?;
|
|
let mut file_borrow = file.borrow_mut();
|
|
|
|
file_borrow.write(data)
|
|
}
|
|
SyscallFunction::Read => {
|
|
let fd = RawFd(args[0] as u32);
|
|
let data = arg_buffer_mut(args[1] as _, args[2] as _)?;
|
|
|
|
let proc = Process::current();
|
|
let io = proc.io.lock();
|
|
let file = io.file(fd)?;
|
|
let mut file_borrow = file.borrow_mut();
|
|
|
|
file_borrow.read(data)
|
|
}
|
|
SyscallFunction::Open => {
|
|
let path = arg_user_str(args[0] as usize, args[1] as usize)?;
|
|
let opts = OpenFlags(args[2] as u32);
|
|
|
|
let proc = Process::current();
|
|
let mut io = proc.io.lock();
|
|
|
|
let file = io.ioctx().open(None, path, opts)?;
|
|
let fd = io.place_file(file)?;
|
|
|
|
Ok(fd.0 as usize)
|
|
}
|
|
SyscallFunction::Close => {
|
|
let fd = RawFd(args[0] as u32);
|
|
|
|
let proc = Process::current();
|
|
let mut io = proc.io.lock();
|
|
io.close_file(fd)?;
|
|
Ok(0)
|
|
}
|
|
SyscallFunction::Mount => {
|
|
let options = arg_user_ref::<MountOptions>(args[0] as usize)?;
|
|
|
|
let proc = Process::current();
|
|
let mut io = proc.io.lock();
|
|
|
|
let target_node = io.ioctx().find(None, options.target, true, false)?;
|
|
if !target_node.is_directory() {
|
|
return Err(Error::NotADirectory);
|
|
}
|
|
|
|
let fs_root = fs::create_filesystem(options)?;
|
|
|
|
target_node.mount(fs_root)?;
|
|
|
|
debugln!("{:?}", vfs::VnodeDump::new(io.ioctx().root().clone()));
|
|
|
|
Ok(0)
|
|
}
|
|
SyscallFunction::Unmount => {
|
|
let options = arg_user_ref::<UnmountOptions>(args[0] as usize)?;
|
|
|
|
let proc = Process::current();
|
|
let mut io = proc.io.lock();
|
|
|
|
let mountpoint = io.ioctx().find(None, options.mountpoint, true, false)?;
|
|
mountpoint.unmount_target()?;
|
|
|
|
debugln!("{:?}", vfs::VnodeDump::new(io.ioctx().root().clone()));
|
|
|
|
Ok(0)
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Entrypoint for system calls that takes raw argument values
|
|
pub fn raw_syscall_handler(func: u64, args: &[u64]) -> u64 {
|
|
let Ok(func) = SyscallFunction::try_from(func as usize) else {
|
|
todo!("Undefined syscall: {}", func);
|
|
};
|
|
|
|
syscall_handler(func, args).into_syscall_result() as u64
|
|
}
|