Add more syscalls
All checks were successful
Build / build (push) Successful in 2m45s

This commit is contained in:
Mathieu Strypsteen 2024-12-25 21:34:19 +01:00
parent f0b4236407
commit a6a88e7f3b
4 changed files with 75 additions and 20 deletions

View file

@ -36,9 +36,10 @@ static PHYSICAL_FRAMES: Spinlock<OnceCell<BitVec<u64>>> = Spinlock::new(OnceCell
static HEAP_PHYS_MAPPING: Spinlock<Vec<u64>> = Spinlock::new(Vec::new());
const KERNEL_MAPPINGS_START: u64 = 0xfffffffd00000000;
const KERNEL_MAPPINGS_END: u64 = 0xfffffffe00000000;
pub const USER_END: u64 = 0x800000000000 - 0x1000; // Avoid accidentally jumping to non-canonical address
impl AddressSpace {
fn get_page(&mut self, virt: u64) -> Option<&mut PageEntry> {
pub fn get_page(&mut self, virt: u64) -> Option<&mut PageEntry> {
let virt_page = virt as usize / 0x1000;
let table_i = virt_page % 512;
let directory_i = virt_page / 512 % 512;

View file

@ -4,12 +4,13 @@ use elf::{abi::PT_LOAD, endian::LittleEndian, ElfBytes};
use log::info;
use crate::{
cpu::cpu::{disable_user_memory_access, enable_user_memory_access},
cpu::{
cpu::{disable_user_memory_access, enable_user_memory_access},
paging::USER_END,
},
sys::{lapic::get_current_lapic_id, task::CURRENT_TASKS},
};
const USER_END: u64 = 0x800000000000 - 0x1000; // Avoid accidentally jumping to non-canonical address
extern "C" {
fn jump_usermode(address: u64) -> !;
}
@ -33,11 +34,9 @@ pub fn load_binary() {
}
let write = i.p_flags & 2 != 0;
let exec = i.p_flags & 1 != 0;
assert!(i.p_vaddr + i.p_memsz < USER_END);
assert!(i.p_vaddr + i.p_memsz >= i.p_vaddr);
assert!(i.p_vaddr.checked_add(i.p_memsz).unwrap_or(USER_END + 1) <= USER_END);
assert!(i.p_filesz <= i.p_memsz);
assert!(i.p_offset + i.p_filesz <= binary.len() as u64);
assert!(i.p_offset + i.p_filesz >= i.p_offset);
assert!(i.p_offset.checked_add(i.p_filesz).unwrap_or(binary.len() as u64 + 1) <= binary.len() as u64);
assert!(!write || !exec);
let start = i.p_vaddr / 0x1000 * 0x1000;
let end = (i.p_vaddr + i.p_memsz + 0xfff) / 0x1000 * 0x1000;

View file

@ -1,21 +1,70 @@
use log::debug;
use core::{error::Error, ptr::copy};
use super::task::terminate_current_task;
use alloc::{boxed::Box, string::String, vec::Vec};
use log::{debug, trace};
use crate::cpu::{
cpu::{disable_user_memory_access, enable_user_memory_access},
paging::USER_END,
};
use super::{
lapic::get_current_lapic_id,
task::{terminate_current_task, CURRENT_TASKS},
};
struct SyscallArgs {
_arg1: usize,
_arg2: usize,
arg1: usize,
arg2: usize,
_arg3: usize,
_arg4: usize,
_arg5: usize,
}
const SYSCALL_TABLE: [fn(SyscallArgs) -> usize; 1] = [syscall_get_kernel_version];
const SYSCALL_TABLE: [fn(SyscallArgs) -> Result<usize, Box<dyn Error>>; 3] = [syscall_get_kernel_version, syscall_exit, syscall_debug_print];
fn syscall_get_kernel_version(_args: SyscallArgs) -> usize {
0
fn copy_from_user(start: u64, size: usize) -> Result<Vec<u8>, Box<dyn Error>> {
if size > 16 * 1024 * 1024 {
return Err("Too large copy requested".into());
}
let end = start.checked_add(size as u64).ok_or("Invalid copy requested")?;
if end > USER_END {
return Err("Invalid copy requested".into());
}
let process;
{
let tasks = CURRENT_TASKS.lock();
process = tasks[get_current_lapic_id()].as_ref().unwrap().process.clone();
}
let mut process = process.lock();
for i in start / 0x1000..(end + 0xfff) / 0x1000 {
let page = process.address_space.get_page(i * 0x1000);
if page.is_none() || page.unwrap().present() == 0 {
return Err("Invalid copy requested".into());
}
}
let mut buffer = Vec::with_capacity(size);
buffer.resize(size, 0);
enable_user_memory_access();
unsafe {
copy(start as *const u8, buffer.as_mut_ptr(), size);
}
disable_user_memory_access();
Ok(buffer)
}
fn syscall_get_kernel_version(_args: SyscallArgs) -> Result<usize, Box<dyn Error>> {
Ok(0)
}
fn syscall_exit(_args: SyscallArgs) -> Result<usize, Box<dyn Error>> {
// TODO: Also terminate other threads
terminate_current_task();
}
fn syscall_debug_print(args: SyscallArgs) -> Result<usize, Box<dyn Error>> {
let data = copy_from_user(args.arg1 as u64, args.arg2)?;
let string = String::from_utf8(data)?;
trace!("{}", string);
Ok(0)
}
#[no_mangle]
extern "C" fn syscall_handler(syscall: u64, arg1: u64, arg2: u64, arg3: u64, arg4: u64, arg5: u64) -> u64 {
if syscall as usize >= SYSCALL_TABLE.len() {
@ -23,12 +72,16 @@ extern "C" fn syscall_handler(syscall: u64, arg1: u64, arg2: u64, arg3: u64, arg
terminate_current_task();
}
let args = SyscallArgs {
_arg1: arg1 as usize,
_arg2: arg2 as usize,
arg1: arg1 as usize,
arg2: arg2 as usize,
_arg3: arg3 as usize,
_arg4: arg4 as usize,
_arg5: arg5 as usize,
};
let result = SYSCALL_TABLE[syscall as usize](args);
result as u64
if result.is_err() {
debug!("Error during syscall: {}", result.err().unwrap());
terminate_current_task();
}
result.unwrap() as u64
}

View file

@ -146,7 +146,9 @@ fn create_idle_task() {
}
}
pub fn terminate_current_task() -> ! {
{
CURRENT_TASKS.lock()[get_current_lapic_id()].as_mut().unwrap().task_state = TaskState::Terminated;
}
yield_task();
panic!("Failed to terminate task");
}