add simple syscall architecture
Signed-off-by: Julien CLEMENT <julien.clement@epita.fr>
This commit is contained in:
		
							parent
							
								
									a1a01124de
								
							
						
					
					
						commit
						689f7c8810
					
				@ -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,12 +82,12 @@ 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();
 | 
			
		||||
                    (&mut *thread.as_ptr()).run();
 | 
			
		||||
                }
 | 
			
		||||
                self.thread_queue.register(id);
 | 
			
		||||
            }
 | 
			
		||||
@ -123,4 +121,4 @@ pub async fn scheduler_run() {
 | 
			
		||||
    let mut scheduler = SCHEDULER.lock().await;
 | 
			
		||||
    SCHEDULER.force_unlock();
 | 
			
		||||
    scheduler.run().await;
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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,34 +25,21 @@ 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 {
 | 
			
		||||
        (&mut* k_thread).run();
 | 
			
		||||
        (&mut *k_thread).run();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										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
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										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);
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user