Adds syscall for sleep and print and makes process work in user mode
This commit is contained in:
105
src/interrupt.rs
105
src/interrupt.rs
@@ -1,20 +1,29 @@
|
||||
use alloc::str;
|
||||
use log::info;
|
||||
|
||||
use crate::{
|
||||
boot::sbi::{EextensionID, TimerFunctionID},
|
||||
clear_csr, generate_trap_handler,
|
||||
process::ExecutionContext,
|
||||
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;
|
||||
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) {
|
||||
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 {
|
||||
@@ -30,27 +39,19 @@ unsafe extern "C" fn machine_trap_handler(mcause: u64, mie: u64, mip: u64) {
|
||||
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,
|
||||
);
|
||||
}
|
||||
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 u64 => match fid {
|
||||
c if c == TimerFunctionID::SetTimer as u64 => {
|
||||
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
|
||||
@@ -86,26 +87,56 @@ unsafe extern "C" fn machine_trap_handler(mcause: u64, mie: u64, mip: u64) {
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
unsafe extern "C" fn supervisor_trap_handler(
|
||||
interrupt_state: *const ExecutionContext,
|
||||
interrupt_state: *mut ExecutionContext,
|
||||
scause: u64,
|
||||
_sie: u64,
|
||||
_sip: u64,
|
||||
) -> *const ExecutionContext {
|
||||
#[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,
|
||||
);
|
||||
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!("{}", unsafe {
|
||||
str::from_raw_parts(a1 as *const u8, a2 as usize)
|
||||
})
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
timer_interrupt();
|
||||
return scheduler(unsafe { *interrupt_state });
|
||||
_ => {}
|
||||
}
|
||||
} 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,
|
||||
);
|
||||
}
|
||||
timer_interrupt();
|
||||
return scheduler(unsafe { *interrupt_state });
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
interrupt_state
|
||||
}
|
||||
@@ -147,6 +178,7 @@ unsafe extern "C" fn _machine_mode_trap() {
|
||||
csrr a0, mcause
|
||||
csrr a1, mie
|
||||
csrr a2, mip
|
||||
mv a3, sp
|
||||
jal machine_trap_handler
|
||||
|
||||
# Restore registers
|
||||
@@ -240,8 +272,8 @@ macro_rules! generate_trap_handler {
|
||||
# Restore registers
|
||||
ld t0, 248(a0)
|
||||
csrw sepc, t0
|
||||
// ld t0, 256(a0)
|
||||
// csrw sstatus, t0
|
||||
ld t0, 256(a0)
|
||||
csrw sstatus, t0
|
||||
ld ra, 0(a0)
|
||||
ld sp, 8(a0)
|
||||
ld gp, 16(a0)
|
||||
@@ -275,8 +307,6 @@ macro_rules! generate_trap_handler {
|
||||
|
||||
ld a0, 32(a0)
|
||||
|
||||
// addi sp, sp, 264
|
||||
|
||||
",
|
||||
stringify!($mode),
|
||||
"ret"
|
||||
@@ -284,3 +314,10 @@ macro_rules! generate_trap_handler {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
struct MachineInterruptState {
|
||||
pub a: [usize; 8],
|
||||
pub t: [usize; 7],
|
||||
pub ra: usize,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user