Supervisor mode
This commit is contained in:
178
src/interrupt.rs
Normal file
178
src/interrupt.rs
Normal file
@@ -0,0 +1,178 @@
|
||||
use crate::{
|
||||
boot::sbi::{TimeFID, EID},
|
||||
clear_csr, generate_trap_handler, read_csr,
|
||||
riscv::disable_interrupt,
|
||||
set_csr,
|
||||
time::{setup_next_timer_interrupt, IRQ_M_TIMER},
|
||||
write_csr,
|
||||
};
|
||||
use core::arch::naked_asm;
|
||||
|
||||
use crate::time::{setup_timer_interrupt, timer_interrupt};
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
unsafe extern "C" fn machine_trap_handler(mcause: u64, mie: u64, mip: u64) {
|
||||
let mepc = read_csr!(mepc);
|
||||
let mtval = read_csr!(mtval);
|
||||
if mcause & (1 << 63) == 0 {
|
||||
let message = match mcause & !(1 << 63) {
|
||||
0 => "Instruction address misaligned",
|
||||
1 => "Instruction access fault",
|
||||
2 => "Illegal instruction",
|
||||
3 => "Breakpoint",
|
||||
4 => "Load address misaligned",
|
||||
5 => "Load access fault",
|
||||
6 => "Store/AMO address misaligned",
|
||||
7 => "Store/AMO access fault",
|
||||
8 => "Environment call from U-mode",
|
||||
9 => {
|
||||
// Environment call from S-mode
|
||||
let eid: u64;
|
||||
let fid: u64;
|
||||
unsafe {
|
||||
core::arch::asm!(
|
||||
"mv {}, a7",
|
||||
"mv {}, a6",
|
||||
out(reg) eid,
|
||||
out(reg) fid,
|
||||
);
|
||||
}
|
||||
|
||||
#[allow(clippy::single_match)]
|
||||
match eid {
|
||||
c if c == EID::Time as u64 => match fid {
|
||||
c if c == TimeFID::SetTimer as u64 => {
|
||||
clear_csr!(mip, 1 << 5);
|
||||
setup_next_timer_interrupt();
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
|
||||
// Advance mepc to exit the ecall
|
||||
let mepc = read_csr!(mepc);
|
||||
write_csr!(mepc, mepc + 4);
|
||||
return;
|
||||
}
|
||||
11 => "Environment call from M-mode",
|
||||
12 => "Instruction page fault",
|
||||
13 => "Load page fault",
|
||||
15 => "Store/AMO page fault",
|
||||
16 => "Double trap",
|
||||
18 => "Software check",
|
||||
19 => "Hardware error",
|
||||
_ => panic!(
|
||||
"unknown exception, mcause={}, mie={}, mip={}",
|
||||
mcause, mie, mip
|
||||
),
|
||||
};
|
||||
disable_interrupt();
|
||||
panic!("{} at PC=0x{:x}, mtval={}", message, mepc, mtval);
|
||||
} else {
|
||||
#[allow(clippy::single_match)]
|
||||
match mcause & !(1 << 63) {
|
||||
7 => {
|
||||
setup_next_timer_interrupt();
|
||||
set_csr!(mip, 1 << 5);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
unsafe extern "C" fn supervisor_trap_handler(scause: u64, _sie: u64, _sip: u64) {
|
||||
#[allow(clippy::single_match)]
|
||||
match scause & !(1 << 63) {
|
||||
5 => {
|
||||
unsafe {
|
||||
core::arch::asm!(
|
||||
"ecall",
|
||||
in("a0") 0,
|
||||
in("a6") TimeFID::SetTimer as u64,
|
||||
in("a7") EID::Time as u64,
|
||||
);
|
||||
}
|
||||
timer_interrupt();
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn setup_machine_trap_handler() {
|
||||
write_csr!(mtvec, _machine_mode_trap);
|
||||
set_csr!(mie, IRQ_M_TIMER);
|
||||
}
|
||||
pub unsafe fn setup_supervisor_trap_handler() {
|
||||
write_csr!(stvec, _supervisor_mode_trap);
|
||||
setup_timer_interrupt();
|
||||
}
|
||||
|
||||
generate_trap_handler! {
|
||||
_machine_mode_trap, machine_trap_handler, m
|
||||
}
|
||||
generate_trap_handler! {
|
||||
_supervisor_mode_trap, supervisor_trap_handler, s
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! generate_trap_handler {
|
||||
($name:ident, $jump_to:ident, $mode:ident) => {
|
||||
#[unsafe(naked)]
|
||||
#[unsafe(no_mangle)]
|
||||
unsafe extern "C" fn $name() {
|
||||
naked_asm!(
|
||||
concat!("
|
||||
addi sp, sp, -128
|
||||
|
||||
sd ra, 120(sp)
|
||||
|
||||
sd a0, 0(sp)
|
||||
sd a1, 8(sp)
|
||||
sd a2, 16(sp)
|
||||
sd a3, 24(sp)
|
||||
sd a4, 32(sp)
|
||||
sd a5, 40(sp)
|
||||
sd a6, 48(sp)
|
||||
sd a7, 56(sp)
|
||||
|
||||
sd t0, 64(sp)
|
||||
sd t1, 72(sp)
|
||||
sd t2, 80(sp)
|
||||
sd t3, 88(sp)
|
||||
sd t4, 96(sp)
|
||||
sd t5, 104(sp)
|
||||
sd t6, 112(sp)
|
||||
|
||||
csrr a0, ", stringify!($mode),"cause
|
||||
csrr a1, ", stringify!($mode),"ie
|
||||
csrr a2, ", stringify!($mode),"ip
|
||||
jal ", stringify!($jump_to), "
|
||||
|
||||
ld a0, 0(sp)
|
||||
ld a1, 8(sp)
|
||||
ld a2, 16(sp)
|
||||
ld a3, 24(sp)
|
||||
ld a4, 32(sp)
|
||||
ld a5, 40(sp)
|
||||
ld a6, 48(sp)
|
||||
ld a7, 56(sp)
|
||||
|
||||
ld t0, 64(sp)
|
||||
ld t1, 72(sp)
|
||||
ld t2, 80(sp)
|
||||
ld t3, 88(sp)
|
||||
ld t4, 96(sp)
|
||||
ld t5, 104(sp)
|
||||
ld t6, 112(sp)
|
||||
|
||||
ld ra, 120(sp)
|
||||
|
||||
addi sp, sp, 128
|
||||
|
||||
", stringify!($mode),"ret")
|
||||
)
|
||||
}
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user