diff --git a/.vscode/settings.json b/.vscode/settings.json index a96dafd..15d67e0 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -11,4 +11,5 @@ "rust-analyzer.linkedProjects": [ "./kernel/Cargo.toml" ], + "rust-analyzer.showUnlinkedFileNotification": false, } \ No newline at end of file diff --git a/kernel/src/arch/riscv/trap.rs b/kernel/src/arch/riscv/trap.rs index 9bfbb57..c080f51 100644 --- a/kernel/src/arch/riscv/trap.rs +++ b/kernel/src/arch/riscv/trap.rs @@ -1,11 +1,11 @@ use crate::entry::HART_ID; use crate::plat::console::CONSOLE; -use log::trace; -use riscv::register::scause::{Interrupt as I, Trap as T}; -use riscv::register::stvec::TrapMode; - use crate::plat::timer::{Timer, TimerOps}; use crate::plat::trap::{Trap, TrapContextOps, TrapOps}; +use crate::scheduler::SCHEDULER; +use log::trace; +use riscv::register::scause::{Exception as E, Interrupt as I, Trap as T}; +use riscv::register::stvec::TrapMode; core::arch::global_asm!(include_str!("./asm/trap64.S")); core::arch::global_asm!(include_str!("./asm/trap_common.S")); @@ -17,29 +17,52 @@ extern "C" { #[no_mangle] extern "C" fn kernel_trap_handler(tf: &mut TrapContext) { - // TODO: consider redesigning this, should we allow trap in kernel? + // TODO: Replace CONSOLE Mutex to ReentrantLock unsafe { CONSOLE.force_unlock() } trap_handler(tf, true) } -fn trap_handler(_tf: &mut TrapContext, _from_kernel: bool) { +fn trap_handler(tf: &mut TrapContext, from_kernel: bool) { let scause = riscv::register::scause::read(); - trace!("[Interrupt] cpu@{} scause: {:?}", HART_ID.get(), scause.cause()); + trace!("[Trap] cpu@{} scause: {:?}", HART_ID.get(), scause.cause()); + + macro_rules! panic_fatal { + ($msg:expr) => { + panic!( + "[Trap] {}, scause: {:?}, bits: {:#x}, sepc: {:#x}, stval: {:#x}", + $msg, + scause.cause(), + scause.bits(), + tf.sepc, + riscv::register::stval::read() + ) + }; + } + match scause.cause() { T::Interrupt(I::SupervisorTimer) => { - // TODO: refactor this - trace!("[Interrupt] Tick: {}", riscv::register::time::read64()); - Timer::tick(); + if !from_kernel { + SCHEDULER.schedule() + } }, - _ => { - panic!( - "[Interrupt] Unhandled Trap, scause: {:?}, bits: {:#x}", - scause.cause(), - scause.bits() - ); + T::Exception(E::UserEnvCall) => { + // TODO: handle syscall + tf.sepc += 4; }, + T::Interrupt(I::SupervisorExternal) => { + // TODO: handle external interrupt, e.g. plic + }, + T::Exception(E::InstructionPageFault) | T::Exception(E::LoadPageFault) | T::Exception(E::StorePageFault) => { + if from_kernel { + panic_fatal!("Page Fault in Kernel"); + } + // TODO: handle page fault + }, + _ => panic_fatal!("Unhandled Trap"), } - trace!("[Interrupt] exiting..."); + + Timer::tick(); + trace!("[Trap] exiting..."); } impl TrapOps for Trap { diff --git a/kernel/src/main.rs b/kernel/src/main.rs index 1bcb8af..f2a7808 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -29,6 +29,7 @@ mod lang; mod logging; mod objects; mod plat; +mod scheduler; // test infrastructure #[cfg(test)] diff --git a/kernel/src/scheduler/mod.rs b/kernel/src/scheduler/mod.rs new file mode 100644 index 0000000..60cdcf3 --- /dev/null +++ b/kernel/src/scheduler/mod.rs @@ -0,0 +1,15 @@ +pub static SCHEDULER: Scheduler = Scheduler::new(); + +pub struct Scheduler {} + +impl Scheduler { + pub const fn new() -> Self { + // TODO: implement Scheduler::new + Self {} + } + + #[inline(never)] + pub fn schedule(&self) { + todo!("Scheduler::schedule"); + } +}