Skip to main content

os/trap/
mod.rs

1//! Trap handling functionality
2//!
3//! For rCore, we have a single trap entry point, namely `__alltraps`. At
4//! initialization in [`init()`], we set the `stvec` CSR to point to it.
5//!
6//! All traps go through `__alltraps`, which is defined in `trap.S`. The
7//! assembly language code does just enough work restore the kernel space
8//! context, ensuring that Rust code safely runs, and transfers control to
9//! [`trap_handler()`].
10//!
11//! It then calls different functionality based on what exactly the exception
12//! was. For example, timer interrupts trigger task preemption, and syscalls go
13//! to [`syscall()`].
14
15mod context;
16
17use crate::syscall::syscall;
18use core::arch::global_asm;
19use riscv::interrupt::{Exception, Interrupt, Trap};
20use riscv::register::{mtvec::TrapMode, scause, stval, stvec};
21
22global_asm!(include_str!("trap.S"));
23
24/// initialize CSR `stvec` as the entry of `__alltraps`
25pub fn init() {
26    unsafe extern "C" {
27        safe fn __alltraps();
28    }
29    unsafe {
30        stvec::write(stvec::Stvec::new(
31            linker_symbol_addr!(__alltraps),
32            TrapMode::Direct,
33        ));
34    }
35}
36
37#[unsafe(no_mangle)]
38/// handle an interrupt, exception, or system call from user space
39pub fn trap_handler(cx: &mut TrapContext) -> &mut TrapContext {
40    let scause = scause::read(); // get trap cause
41    let stval = stval::read(); // get extra value
42    let trap: Trap<Interrupt, Exception> = match scause.cause().try_into() {
43        Ok(trap) => trap,
44        Err(_) => panic!(
45            "Unsupported trap {:?}, stval = {:#x}!",
46            scause.cause(),
47            stval
48        ),
49    };
50    match trap {
51        Trap::Exception(Exception::UserEnvCall) => {
52            cx.sepc += 4;
53            cx.x[10] = syscall(cx.x[17], [cx.x[10], cx.x[11], cx.x[12]]) as usize;
54        }
55        Trap::Exception(Exception::StoreFault) | Trap::Exception(Exception::StorePageFault) => {
56            println!(
57                "[kernel] PageFault in application, bad addr = {:#x}, bad instruction = {:#x}, kernel killed it.",
58                stval, cx.sepc
59            );
60            panic!("[kernel] Cannot continue!");
61            //run_next_app();
62        }
63        Trap::Exception(Exception::IllegalInstruction) => {
64            println!("[kernel] IllegalInstruction in application, kernel killed it.");
65            panic!("[kernel] Cannot continue!");
66            //run_next_app();
67        }
68        _ => {
69            panic!("Unsupported trap {:?}, stval = {:#x}!", trap, stval);
70        }
71    }
72    cx
73}
74
75pub use context::TrapContext;