1mod context;
16
17use crate::batch::run_next_app;
18use crate::syscall::syscall;
19use core::arch::global_asm;
20use riscv::interrupt::{Exception, Interrupt, Trap};
21use riscv::register::{mtvec::TrapMode, scause, stval, stvec};
22
23global_asm!(include_str!("trap.S"));
24
25pub fn init() {
27 unsafe extern "C" {
28 safe fn __alltraps();
29 }
30 unsafe {
31 stvec::write(stvec::Stvec::new(
32 linker_symbol_addr!(__alltraps),
33 TrapMode::Direct,
34 ));
35 }
36}
37
38#[unsafe(no_mangle)]
39pub fn trap_handler(cx: &mut TrapContext) -> &mut TrapContext {
41 let scause = scause::read(); let stval = stval::read(); let trap: Trap<Interrupt, Exception> = match scause.cause().try_into() {
44 Ok(trap) => trap,
45 Err(_) => panic!(
46 "Unsupported trap {:?}, stval = {:#x}!",
47 scause.cause(),
48 stval
49 ),
50 };
51 match trap {
52 Trap::Exception(Exception::UserEnvCall) => {
53 cx.sepc += 4;
54 cx.x[10] = syscall(cx.x[17], [cx.x[10], cx.x[11], cx.x[12]]) as usize;
55 }
56 Trap::Exception(Exception::StoreFault) | Trap::Exception(Exception::StorePageFault) => {
57 println!("[kernel] PageFault in application, kernel killed it.");
58 run_next_app();
59 }
60 Trap::Exception(Exception::IllegalInstruction) => {
61 println!("[kernel] IllegalInstruction in application, kernel killed it.");
62 run_next_app();
63 }
64 _ => {
65 panic!("Unsupported trap {:?}, stval = {:#x}!", trap, stval);
66 }
67 }
68 cx
69}
70
71pub use context::TrapContext;