Load dynamic programs using FAT32
This commit is contained in:
327
src/interrupt.rs
Normal file
327
src/interrupt.rs
Normal file
@@ -0,0 +1,327 @@
|
||||
use alloc::str;
|
||||
use log::info;
|
||||
|
||||
use crate::{
|
||||
boot::sbi::{EextensionID, TimerFunctionID},
|
||||
clear_csr, generate_trap_handler,
|
||||
process::{sleep, ExecutionContext},
|
||||
read_csr,
|
||||
riscv::disable_interrupt,
|
||||
scheduler::scheduler,
|
||||
set_csr,
|
||||
syscall::SysCall,
|
||||
time::{setup_next_timer_interrupt, IRQ_M_TIMER},
|
||||
write_csr,
|
||||
};
|
||||
use core::{arch::naked_asm, time::Duration};
|
||||
|
||||
use crate::time::{setup_timer_interrupt, timer_interrupt};
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
unsafe extern "C" fn machine_trap_handler(
|
||||
mcause: u64,
|
||||
mie: u64,
|
||||
mip: u64,
|
||||
interrupt_state: *const MachineInterruptState,
|
||||
) {
|
||||
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 = unsafe { (*interrupt_state).a[7] };
|
||||
let fid = unsafe { (*interrupt_state).a[6] };
|
||||
|
||||
#[allow(clippy::single_match)]
|
||||
match eid {
|
||||
c if c == EextensionID::Time as usize => match fid {
|
||||
c if c == TimerFunctionID::SetTimer as usize => {
|
||||
clear_csr!(mip, 1 << 5);
|
||||
// setup_next_timer_interrupt();
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
_ => panic!("Unhandled SBI call eid={eid}, fid={fid}"),
|
||||
}
|
||||
|
||||
// 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(
|
||||
interrupt_state: *mut ExecutionContext,
|
||||
scause: u64,
|
||||
_sie: u64,
|
||||
_sip: u64,
|
||||
) -> *const ExecutionContext {
|
||||
if scause & (1 << 63) == 0 {
|
||||
#[allow(clippy::single_match)]
|
||||
match scause & !(1 << 63) {
|
||||
8 => {
|
||||
// Environment call from S-mode
|
||||
let syscall_u64: u64 = unsafe { (*interrupt_state).a[0] };
|
||||
let a1: u64 = unsafe { (*interrupt_state).a[1] };
|
||||
let a2: u64 = unsafe { (*interrupt_state).a[2] };
|
||||
let syscall: SysCall = syscall_u64.into();
|
||||
match syscall {
|
||||
SysCall::NanoSleep => sleep(Duration::new(a1, a2 as u32)),
|
||||
SysCall::WriteTemp => {
|
||||
info!("Print from user space : {}", unsafe {
|
||||
str::from_raw_parts(a1 as *const u8, a2 as usize)
|
||||
})
|
||||
}
|
||||
SysCall::WriteIntTemp => {
|
||||
info!("Print from user space int : {}, {:x}", a1, a1)
|
||||
}
|
||||
SysCall::Unimplemented => {
|
||||
unimplemented!("Syscall {syscall_u64} is not implemented")
|
||||
}
|
||||
}
|
||||
|
||||
// Advance sepc to exit the ecall
|
||||
unsafe {
|
||||
(*interrupt_state).mepc = (*interrupt_state).mepc.byte_add(4);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
} else {
|
||||
#[allow(clippy::single_match)]
|
||||
match scause & !(1 << 63) {
|
||||
5 => {
|
||||
unsafe {
|
||||
core::arch::asm!(
|
||||
"ecall",
|
||||
in("a0") 0,
|
||||
in("a6") TimerFunctionID::SetTimer as u64,
|
||||
in("a7") EextensionID::Time as u64,
|
||||
clobber_abi("system")
|
||||
);
|
||||
}
|
||||
timer_interrupt();
|
||||
return scheduler(unsafe { *interrupt_state });
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
interrupt_state
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
#[unsafe(naked)]
|
||||
#[unsafe(no_mangle)]
|
||||
unsafe extern "C" fn _machine_mode_trap() {
|
||||
naked_asm!(
|
||||
"
|
||||
addi sp, sp, -128
|
||||
|
||||
# Store the current frame
|
||||
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, mcause
|
||||
csrr a1, mie
|
||||
csrr a2, mip
|
||||
mv a3, sp
|
||||
jal machine_trap_handler
|
||||
|
||||
# Restore registers
|
||||
ld ra, 120(sp)
|
||||
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)
|
||||
|
||||
addi sp, sp, 128
|
||||
mret"
|
||||
)
|
||||
}
|
||||
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!(
|
||||
"
|
||||
mv t0, sp
|
||||
addi sp, sp, -264
|
||||
|
||||
# Store the current frame
|
||||
sd ra, 0(sp)
|
||||
sd t0, 8(sp) // sp
|
||||
sd gp, 16(sp)
|
||||
sd tp, 24(sp)
|
||||
sd a0, 32(sp)
|
||||
sd a1, 40(sp)
|
||||
sd a2, 48(sp)
|
||||
sd a3, 56(sp)
|
||||
sd a4, 64(sp)
|
||||
sd a5, 72(sp)
|
||||
sd a6, 80(sp)
|
||||
sd a7, 88(sp)
|
||||
sd t0, 96(sp)
|
||||
sd t1, 104(sp)
|
||||
sd t2, 112(sp)
|
||||
sd t3, 120(sp)
|
||||
sd t4, 128(sp)
|
||||
sd t5, 136(sp)
|
||||
sd t6, 144(sp)
|
||||
sd s0, 152(sp)
|
||||
sd s1, 160(sp)
|
||||
sd s2, 168(sp)
|
||||
sd s3, 176(sp)
|
||||
sd s4, 184(sp)
|
||||
sd s5, 192(sp)
|
||||
sd s6, 200(sp)
|
||||
sd s7, 208(sp)
|
||||
sd s8, 216(sp)
|
||||
sd s9, 224(sp)
|
||||
sd s10, 232(sp)
|
||||
sd s11, 240(sp)
|
||||
csrr t0, sepc
|
||||
sd t0, 248(sp)
|
||||
csrr t0, sstatus
|
||||
sd t0, 256(sp)
|
||||
|
||||
mv a0, sp
|
||||
csrr a1, ",
|
||||
stringify!($mode),
|
||||
"cause
|
||||
csrr a2, ",
|
||||
stringify!($mode),
|
||||
"ie
|
||||
csrr a3, ",
|
||||
stringify!($mode),
|
||||
"ip
|
||||
jal ",
|
||||
stringify!($jump_to),
|
||||
"
|
||||
|
||||
# Restore registers
|
||||
ld t0, 248(a0)
|
||||
csrw sepc, t0
|
||||
ld t0, 256(a0)
|
||||
csrw sstatus, t0
|
||||
ld ra, 0(a0)
|
||||
ld sp, 8(a0)
|
||||
ld gp, 16(a0)
|
||||
ld tp, 24(a0)
|
||||
ld a1, 40(a0)
|
||||
ld a2, 48(a0)
|
||||
ld a3, 56(a0)
|
||||
ld a4, 64(a0)
|
||||
ld a5, 72(a0)
|
||||
ld a6, 80(a0)
|
||||
ld a7, 88(a0)
|
||||
ld t0, 96(a0)
|
||||
ld t1, 104(a0)
|
||||
ld t2, 112(a0)
|
||||
ld t3, 120(a0)
|
||||
ld t4, 128(a0)
|
||||
ld t5, 136(a0)
|
||||
ld t6, 144(a0)
|
||||
ld s0, 152(a0)
|
||||
ld s1, 160(a0)
|
||||
ld s2, 168(a0)
|
||||
ld s3, 176(a0)
|
||||
ld s4, 184(a0)
|
||||
ld s5, 192(a0)
|
||||
ld s6, 200(a0)
|
||||
ld s7, 208(a0)
|
||||
ld s8, 216(a0)
|
||||
ld s9, 224(a0)
|
||||
ld s10, 232(a0)
|
||||
ld s11, 240(a0)
|
||||
|
||||
ld a0, 32(a0)
|
||||
|
||||
",
|
||||
stringify!($mode),
|
||||
"ret"
|
||||
))
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
struct MachineInterruptState {
|
||||
pub a: [usize; 8],
|
||||
pub t: [usize; 7],
|
||||
pub ra: usize,
|
||||
}
|
||||
Reference in New Issue
Block a user