Try loading code at runtime

This commit is contained in:
2026-02-13 17:22:23 +01:00
parent a53e11d6dd
commit 27a3847c13
28 changed files with 96 additions and 144 deletions

View File

@@ -1,324 +0,0 @@
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::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,
}