feat: add idle thread

This commit is contained in:
Paul Pan 2024-05-20 13:18:38 +08:00
parent cdcc709d70
commit 0d0a5471af
2 changed files with 63 additions and 49 deletions

View File

@ -2,7 +2,6 @@ use crate::entry::HART_ID;
use crate::plat::console::CONSOLE; use crate::plat::console::CONSOLE;
use crate::plat::timer::{Timer, TimerOps}; use crate::plat::timer::{Timer, TimerOps};
use crate::plat::trap::{Trap, TrapContextOps, TrapOps}; use crate::plat::trap::{Trap, TrapContextOps, TrapOps};
use crate::scheduler::SCHEDULER;
use log::trace; use log::trace;
use riscv::register::scause::{Exception as E, Interrupt as I, Trap as T}; use riscv::register::scause::{Exception as E, Interrupt as I, Trap as T};
use riscv::register::stvec::TrapMode; use riscv::register::stvec::TrapMode;
@ -17,54 +16,10 @@ extern "C" {
#[no_mangle] #[no_mangle]
extern "C" fn kernel_trap_handler(tf: &mut TrapContext) { extern "C" fn kernel_trap_handler(tf: &mut TrapContext) {
// No trap in kernel, except from IDLE thread
// TODO: Replace CONSOLE Mutex to ReentrantLock // TODO: Replace CONSOLE Mutex to ReentrantLock
unsafe { CONSOLE.force_unlock() } unsafe { CONSOLE.force_unlock() }
trap_handler(tf, true) tf.trap_handler(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...");
} }
impl TrapOps for Trap { 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 { impl TrapContextOps for TrapContext {
fn restore(&mut self) { fn restore(&mut self) {
unsafe { switch_to_user(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)] #[repr(C)]
pub struct GeneralRegs { pub struct GeneralRegs {
pub ra: usize, pub ra: usize,
@ -118,7 +130,7 @@ pub struct GeneralRegs {
pub t6: usize, pub t6: usize,
} }
#[derive(Debug)] #[derive(Debug, Default)]
#[repr(C)] #[repr(C)]
pub struct TrapContext { pub struct TrapContext {
// [0:30] GPRs exclude zero // [0:30] GPRs exclude zero

View File

@ -6,4 +6,6 @@ pub trait TrapOps {
pub trait TrapContextOps { pub trait TrapContextOps {
fn restore(&mut self); fn restore(&mut self);
fn configure_idle_thread(&mut self);
fn trap_handler(&mut self, from_kernel: bool);
} }