mirror of
https://github.com/panpaul/tiny_os
synced 2024-09-20 09:45:19 +08:00
feat: add idle thread
This commit is contained in:
parent
cdcc709d70
commit
0d0a5471af
@ -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
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user