1mod 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
24pub 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)]
38pub fn trap_handler(cx: &mut TrapContext) -> &mut TrapContext {
40 let scause = scause::read(); let stval = stval::read(); 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 }
63 Trap::Exception(Exception::IllegalInstruction) => {
64 println!("[kernel] IllegalInstruction in application, kernel killed it.");
65 panic!("[kernel] Cannot continue!");
66 }
68 _ => {
69 panic!("Unsupported trap {:?}, stval = {:#x}!", trap, stval);
70 }
71 }
72 cx
73}
74
75pub use context::TrapContext;