mirror of
https://github.com/panpaul/tiny_os
synced 2024-09-20 01:35:19 +08:00
Compare commits
3 Commits
753515700f
...
a867e77e3c
Author | SHA1 | Date | |
---|---|---|---|
a867e77e3c | |||
6bbc889d7f | |||
917629f16e |
@ -39,4 +39,4 @@ uart_16550 = "0.3"
|
||||
|
||||
[target.'cfg(target_arch = "riscv64")'.dependencies]
|
||||
riscv = { version = "0.11", features = ["s-mode"] }
|
||||
sbi-rt = { version = "0.0" }
|
||||
sbi-rt = { version = "0.0.3" }
|
||||
|
@ -2,19 +2,28 @@ use super::layout::{BSS_END, BSS_START, TEXT_END, TEXT_START};
|
||||
use crate::plat::backtrace::FrameWalker;
|
||||
use utils::addr::{AddressOps, VirtAddr};
|
||||
|
||||
#[inline]
|
||||
pub fn read_fp() -> usize {
|
||||
let fp;
|
||||
unsafe { core::arch::asm!("mv {}, fp", out(reg) fp) }
|
||||
fp
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn read_sp() -> usize {
|
||||
let sp;
|
||||
unsafe { core::arch::asm!("mv {}, sp", out(reg) sp) }
|
||||
sp
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn read_ra() -> usize {
|
||||
let ra;
|
||||
unsafe { core::arch::asm!("mv {}, ra", out(reg) ra) }
|
||||
ra
|
||||
}
|
||||
|
||||
impl FrameWalker {
|
||||
fn read_fp() -> usize {
|
||||
let fp;
|
||||
unsafe { core::arch::asm!("mv {}, fp", out(reg) fp) }
|
||||
fp
|
||||
}
|
||||
|
||||
fn read_ra() -> usize {
|
||||
let ra;
|
||||
unsafe { core::arch::asm!("mv {}, ra", out(reg) ra) }
|
||||
ra
|
||||
}
|
||||
|
||||
fn is_valid(&self) -> bool {
|
||||
let fp_valid = unsafe { BSS_START.as_virt_addr() <= self.current_fp && self.current_fp < BSS_END.as_virt_addr() };
|
||||
let pc_valid = unsafe { TEXT_START.as_virt_addr() <= self.current_pc && self.current_pc < TEXT_END.as_virt_addr() };
|
||||
@ -28,8 +37,8 @@ impl FrameWalker {
|
||||
pub fn new() -> Self {
|
||||
// current_{fp, pc} is deliberately missed for printing
|
||||
Self {
|
||||
current_fp: VirtAddr::from(FrameWalker::read_fp()),
|
||||
current_pc: VirtAddr::from(FrameWalker::read_ra()),
|
||||
current_fp: VirtAddr::from(read_fp()),
|
||||
current_pc: VirtAddr::from(read_ra()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
use crate::arch::riscv::backtrace::read_sp;
|
||||
use crate::entry::HART_ID;
|
||||
use crate::objects::*;
|
||||
use crate::plat::console::CONSOLE;
|
||||
use crate::plat::irq::IRQ_MANAGER;
|
||||
use crate::plat::timer::{Timer, TimerOps};
|
||||
use crate::plat::trap::{Trap, TrapContextOps, TrapOps};
|
||||
use core::ops::{Index, IndexMut};
|
||||
@ -18,8 +20,7 @@ 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
|
||||
// No trap in kernel
|
||||
unsafe { CONSOLE.force_unlock() }
|
||||
tf.handle_trap(true);
|
||||
}
|
||||
@ -56,12 +57,19 @@ impl TrapContextOps for TrapContext {
|
||||
|
||||
fn configure_idle_thread(&mut self) {
|
||||
self.sepc = idle_thread as usize;
|
||||
self.sstatus = (1 << 5) | (1 << 8); // SPIE + SPP
|
||||
self.sstatus = (1 << 5) // SPIE: enable interrupt in idle thread
|
||||
| (1 << 8) // SPP: run in kernel mode in idle thread
|
||||
;
|
||||
}
|
||||
|
||||
fn handle_trap(&mut self, from_kernel: bool) {
|
||||
let scause = riscv::register::scause::read();
|
||||
trace!("[Trap] cpu@{} scause: {:?}", HART_ID.get(), scause.cause());
|
||||
trace!(
|
||||
"[Trap] cpu@{} scause: {:?} sp: {:#x}",
|
||||
HART_ID.get(),
|
||||
scause.cause(),
|
||||
read_sp()
|
||||
);
|
||||
|
||||
macro_rules! panic_fatal {
|
||||
($msg:expr) => {
|
||||
@ -76,6 +84,10 @@ impl TrapContextOps for TrapContext {
|
||||
};
|
||||
}
|
||||
|
||||
if from_kernel {
|
||||
panic_fatal!("Buggy kernel: trap in kernel mode");
|
||||
}
|
||||
|
||||
let tcb = self.as_object_mut();
|
||||
|
||||
match scause.cause() {
|
||||
@ -85,14 +97,17 @@ impl TrapContextOps for TrapContext {
|
||||
tcb.do_tick();
|
||||
}
|
||||
},
|
||||
T::Interrupt(I::SupervisorExternal) => {
|
||||
IRQ_MANAGER.lock().dispatch();
|
||||
},
|
||||
T::Interrupt(I::SupervisorSoft) => {
|
||||
// This should never happen
|
||||
panic_fatal!("Buggy kernel: supervisor software interrupt triggered");
|
||||
},
|
||||
T::Exception(E::UserEnvCall) => {
|
||||
tcb.handle_syscall();
|
||||
self.sepc += 4;
|
||||
},
|
||||
T::Interrupt(I::SupervisorExternal) => {
|
||||
// TODO: handle external interrupt, e.g. plic
|
||||
panic_fatal!("Unhandled External Interrupt");
|
||||
},
|
||||
T::Exception(E::InstructionPageFault) | T::Exception(E::LoadPageFault) | T::Exception(E::StorePageFault) => {
|
||||
if from_kernel {
|
||||
panic_fatal!("Page Fault in Kernel");
|
||||
|
@ -52,7 +52,7 @@ pub struct IrqManager {
|
||||
state: [IrqState; IRQ_NUM],
|
||||
}
|
||||
|
||||
pub static IRQ_MANAGER: Mutex<Lazy<IrqManager>> = Mutex::new(Lazy::new(IrqManager::new));
|
||||
pub static IRQ_MANAGER: Lazy<Mutex<IrqManager>> = Lazy::new(|| Mutex::new(IrqManager::new()));
|
||||
|
||||
impl IrqManager {
|
||||
pub fn new() -> Self {
|
||||
@ -61,4 +61,8 @@ impl IrqManager {
|
||||
state: [IrqState::Inactive; IRQ_NUM],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn dispatch(&mut self) {
|
||||
todo!("forward to endpoint cap");
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user