From 0d0a5471aff7eac0af7e3f8f0f36f4a24390b515 Mon Sep 17 00:00:00 2001 From: Paul Pan Date: Mon, 20 May 2024 13:18:38 +0800 Subject: [PATCH] feat: add idle thread --- kernel/src/arch/riscv/trap.rs | 110 +++++++++++++++++++--------------- kernel/src/plat/trap.rs | 2 + 2 files changed, 63 insertions(+), 49 deletions(-) diff --git a/kernel/src/arch/riscv/trap.rs b/kernel/src/arch/riscv/trap.rs index 3fd8471..939a9cf 100644 --- a/kernel/src/arch/riscv/trap.rs +++ b/kernel/src/arch/riscv/trap.rs @@ -2,7 +2,6 @@ use crate::entry::HART_ID; use crate::plat::console::CONSOLE; 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; @@ -17,54 +16,10 @@ extern "C" { #[no_mangle] extern "C" fn kernel_trap_handler(tf: &mut TrapContext) { + // No trap in kernel, except from IDLE thread // TODO: Replace CONSOLE Mutex to ReentrantLock unsafe { CONSOLE.force_unlock() } - trap_handler(tf, true) -} - -fn trap_handler(tf: &mut TrapContext, from_kernel: bool) { - let scause = riscv::register::scause::read(); - 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) => { - Timer::do_tick(); - - if !from_kernel { - SCHEDULER.schedule() - } - }, - 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"), - } - - Timer::set_next(); - trace!("[Trap] exiting..."); + tf.trap_handler(true); } impl TrapOps for Trap { @@ -76,13 +31,70 @@ impl TrapOps for Trap { } } +#[naked] +extern "C" fn idle_thread() { + unsafe { + core::arch::asm!( + " + 1: wfi + j 1b + ", + options(noreturn) + ) + }; +} + impl TrapContextOps for TrapContext { fn restore(&mut self) { unsafe { switch_to_user(self) } } + + fn configure_idle_thread(&mut self) { + self.sepc = idle_thread as usize; + self.sstatus = (1 << 5) | (1 << 8); // SPIE + SPP + } + + fn trap_handler(&mut self, from_kernel: bool) { + let scause = riscv::register::scause::read(); + 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(), + self.sepc, + riscv::register::stval::read() + ) + }; + } + + match scause.cause() { + T::Interrupt(I::SupervisorTimer) => Timer::do_tick(), + T::Exception(E::UserEnvCall) => { + // TODO: handle syscall + self.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"), + } + + Timer::set_next(); + trace!("[Trap] exiting..."); + } } -#[derive(Debug)] +#[derive(Debug, Default)] #[repr(C)] pub struct GeneralRegs { pub ra: usize, @@ -118,7 +130,7 @@ pub struct GeneralRegs { pub t6: usize, } -#[derive(Debug)] +#[derive(Debug, Default)] #[repr(C)] pub struct TrapContext { // [0:30] GPRs exclude zero diff --git a/kernel/src/plat/trap.rs b/kernel/src/plat/trap.rs index 2772a8f..0b4d780 100644 --- a/kernel/src/plat/trap.rs +++ b/kernel/src/plat/trap.rs @@ -6,4 +6,6 @@ pub trait TrapOps { pub trait TrapContextOps { fn restore(&mut self); + fn configure_idle_thread(&mut self); + fn trap_handler(&mut self, from_kernel: bool); }