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) {
|
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");
|
println!("Received syscall");
|
||||||
|
crate::syscalls::syscall_routine(rax);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "x86-interrupt" fn page_fault_handler(
|
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 {
|
struct ThreadStream {
|
||||||
ids: ArrayQueue<ThreadId>,
|
ids: ArrayQueue<ThreadId>,
|
||||||
waker: AtomicWaker
|
waker: AtomicWaker,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ThreadStream {
|
impl ThreadStream {
|
||||||
@ -35,9 +35,7 @@ impl ThreadStream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn register(&mut self, id: ThreadId) {
|
pub fn register(&mut self, id: ThreadId) {
|
||||||
self.ids
|
self.ids.push(id).expect("Thread queue full");
|
||||||
.push(id)
|
|
||||||
.expect("Thread queue full");
|
|
||||||
self.waker.wake();
|
self.waker.wake();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -84,12 +82,12 @@ impl Scheduler {
|
|||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub async fn run(&mut self) {
|
pub async fn run(&mut self) {
|
||||||
while let Some(id) = self.thread_queue.next().await {
|
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 {
|
unsafe {
|
||||||
(&mut*thread.as_ptr()).run();
|
(&mut *thread.as_ptr()).run();
|
||||||
}
|
}
|
||||||
self.thread_queue.register(id);
|
self.thread_queue.register(id);
|
||||||
}
|
}
|
||||||
@ -123,4 +121,4 @@ pub async fn scheduler_run() {
|
|||||||
let mut scheduler = SCHEDULER.lock().await;
|
let mut scheduler = SCHEDULER.lock().await;
|
||||||
SCHEDULER.force_unlock();
|
SCHEDULER.force_unlock();
|
||||||
scheduler.run().await;
|
scheduler.run().await;
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::println;
|
use crate::println;
|
||||||
use crate::utils::mutex::AsyncMutex;
|
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::arch::asm;
|
||||||
use core::sync::atomic::{AtomicU64, Ordering};
|
use core::sync::atomic::{AtomicU64, Ordering};
|
||||||
@ -25,34 +25,21 @@ impl ThreadId {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn exit() {
|
pub async fn resume_k_thread() {
|
||||||
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() {
|
|
||||||
let k_thread: *mut Thread;
|
let k_thread: *mut Thread;
|
||||||
{
|
{
|
||||||
let mut scheduler = SCHEDULER.try_lock().unwrap();
|
let mut scheduler = SCHEDULER.lock().await;
|
||||||
k_thread = scheduler
|
k_thread = scheduler.get_thread(K_THREAD_ID).unwrap().as_ptr();
|
||||||
.get_thread(K_THREAD_ID)
|
|
||||||
.unwrap()
|
|
||||||
.as_ptr();
|
|
||||||
} // Drop scheduler mutex guard
|
} // Drop scheduler mutex guard
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
(&mut* k_thread).run();
|
(&mut *k_thread).run();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn routine() {
|
pub fn routine() {
|
||||||
println!("Routine executed");
|
println!("Routine executed");
|
||||||
exit();
|
crate::syscalls::syscall_routine(crate::syscalls::EXIT_ID); // Call exit
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Thread {
|
pub struct Thread {
|
||||||
@ -60,7 +47,7 @@ pub struct Thread {
|
|||||||
pub entry_point: u64,
|
pub entry_point: u64,
|
||||||
pub started: bool,
|
pub started: bool,
|
||||||
pub rsp: u64,
|
pub rsp: u64,
|
||||||
pub base_stack: u64
|
pub base_stack: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Thread {
|
impl Thread {
|
||||||
@ -79,7 +66,10 @@ impl Thread {
|
|||||||
|
|
||||||
pub fn exit(&self) {
|
pub fn exit(&self) {
|
||||||
unsafe {
|
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
|
out = out(reg) current_rsp, // Save thread rsp
|
||||||
);
|
);
|
||||||
current_thread.borrow_mut().rsp = current_rsp;
|
current_thread.borrow_mut().rsp = current_rsp;
|
||||||
}
|
} else {
|
||||||
else { // Thread does not exists anymore
|
// Thread does not exists anymore
|
||||||
*current_thread_guard = self.id; // change running thread
|
*current_thread_guard = self.id; // change running thread
|
||||||
asm!( // Just switch to new thead without saving registers
|
asm!( // Just switch to new thead without saving registers
|
||||||
"push {rsp}", // Set stack pointer to the new thread
|
"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 {
|
pub use ids::*;
|
||||||
0
|
|
||||||
}
|
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