add simple syscall architecture

Signed-off-by: Julien CLEMENT <julien.clement@epita.fr>
This commit is contained in:
Julien CLEMENT 2023-01-04 20:49:06 +01:00
parent a1a01124de
commit 689f7c8810
6 changed files with 112 additions and 35 deletions

@ -53,7 +53,41 @@ extern "x86-interrupt" fn breakpoint_handler(stack_frame: InterruptStackFrame) {
}
extern "x86-interrupt" fn syscall_handler_32(_stack_frame: InterruptStackFrame) {
let rax: u64;
let rbx: u64;
let rcx: u64;
let rdx: u64;
let rsi: u64;
let rdi: u64;
let rbp: u64;
unsafe {
asm!(
"push rax",
"push rbx",
"push rcx",
"push rdx",
"push rsi",
"push rdi",
"push rbp",
"pop {rbp}",
"pop {rdi}",
"pop {rsi}",
"pop {rdx}",
"pop {rcx}",
"pop {rbx}",
"pop {rax}",
rax = out(reg) rax,
rbx = out(reg) rbx,
rcx = out(reg) rcx,
rdx = out(reg) rdx,
rsi = out(reg) rsi,
rdi = out(reg) rdi,
rbp = out(reg) rbp,
)
}
println!("Received syscall");
crate::syscalls::syscall_routine(rax);
}
extern "x86-interrupt" fn page_fault_handler(

@ -23,7 +23,7 @@ pub const K_THREAD_ID: ThreadId = ThreadId(0); // Kernel main thread identifier
struct ThreadStream {
ids: ArrayQueue<ThreadId>,
waker: AtomicWaker
waker: AtomicWaker,
}
impl ThreadStream {
@ -35,9 +35,7 @@ impl ThreadStream {
}
pub fn register(&mut self, id: ThreadId) {
self.ids
.push(id)
.expect("Thread queue full");
self.ids.push(id).expect("Thread queue full");
self.waker.wake();
}
}
@ -84,10 +82,10 @@ impl Scheduler {
res
}
pub async fn run(&mut self) {
while let Some(id) = self.thread_queue.next().await {
if let Some(thread) = self.get_thread(id) { // Thread still exists
if let Some(thread) = self.get_thread(id) {
// Thread still exists
unsafe {
(&mut *thread.as_ptr()).run();
}

@ -1,7 +1,7 @@
use crate::println;
use crate::utils::mutex::AsyncMutex;
use super::scheduler::{SCHEDULER, K_THREAD_ID};
use super::scheduler::{K_THREAD_ID, SCHEDULER};
use core::arch::asm;
use core::sync::atomic::{AtomicU64, Ordering};
@ -25,24 +25,11 @@ impl ThreadId {
}
}
pub fn exit() {
println!("Exiting thread");
{
let mut scheduler = SCHEDULER.try_lock().unwrap();
scheduler.exit(*RUNNING_THREAD.try_lock().unwrap());
} // Drop scheduler mutex guard
resume_k_thread();
}
pub fn resume_k_thread() {
pub async fn resume_k_thread() {
let k_thread: *mut Thread;
{
let mut scheduler = SCHEDULER.try_lock().unwrap();
k_thread = scheduler
.get_thread(K_THREAD_ID)
.unwrap()
.as_ptr();
let mut scheduler = SCHEDULER.lock().await;
k_thread = scheduler.get_thread(K_THREAD_ID).unwrap().as_ptr();
} // Drop scheduler mutex guard
unsafe {
@ -52,7 +39,7 @@ pub fn resume_k_thread() {
pub fn routine() {
println!("Routine executed");
exit();
crate::syscalls::syscall_routine(crate::syscalls::EXIT_ID); // Call exit
}
pub struct Thread {
@ -60,7 +47,7 @@ pub struct Thread {
pub entry_point: u64,
pub started: bool,
pub rsp: u64,
pub base_stack: u64
pub base_stack: u64,
}
impl Thread {
@ -79,7 +66,10 @@ impl Thread {
pub fn exit(&self) {
unsafe {
dealloc(self.base_stack as *mut u8, Layout::new::<[u8; STACK_SIZE]>());
dealloc(
self.base_stack as *mut u8,
Layout::new::<[u8; STACK_SIZE]>(),
);
}
}
@ -98,8 +88,8 @@ impl Thread {
out = out(reg) current_rsp, // Save thread rsp
);
current_thread.borrow_mut().rsp = current_rsp;
}
else { // Thread does not exists anymore
} else {
// Thread does not exists anymore
*current_thread_guard = self.id; // change running thread
asm!( // Just switch to new thead without saving registers
"push {rsp}", // Set stack pointer to the new thread

3
src/syscalls/ids.rs Normal file

@ -0,0 +1,3 @@
pub type SyscallId = u64;
pub const EXIT_ID: u64 = 0;

@ -1,5 +1,47 @@
pub mod io;
use crate::proc::thread::{resume_k_thread, RUNNING_THREAD};
use crate::task::executor::EXECUTOR;
use crate::task::Task;
pub fn syscall_dispatcher() -> u64 {
0
pub use ids::*;
use alloc::sync::Arc;
use core::cell::RefCell;
pub mod ids;
pub mod io;
pub mod proc;
pub type SyscallContextT = Arc<RefCell<SyscallContext>>;
pub struct SyscallContext {
id: SyscallId,
res: u64,
thread_id: crate::proc::thread::ThreadId,
}
pub fn syscall_dispatcher(context: SyscallContextT) -> Task {
match context.borrow().id {
EXIT_ID => Task::new(proc::exit(context.clone())),
_ => Task::new(bad_syscall()),
}
}
pub fn syscall_routine(syscall_id: SyscallId) -> u64 {
let context: SyscallContextT = Arc::new(RefCell::new(SyscallContext {
id: syscall_id,
res: 0,
thread_id: *RUNNING_THREAD.try_lock().unwrap(),
}));
EXECUTOR
.try_lock()
.unwrap()
.spawn(syscall_dispatcher(context.clone()));
resume_k_thread();
let res = context.borrow().res;
res
}
async fn bad_syscall() {}

10
src/syscalls/proc.rs Normal file

@ -0,0 +1,10 @@
use crate::println;
use crate::proc::scheduler::SCHEDULER;
use super::SyscallContextT;
pub async fn exit(context: SyscallContextT) {
println!("Exiting thread");
let mut scheduler = SCHEDULER.lock().await;
scheduler.exit(context.borrow().thread_id);
}