use core::arch::{asm, global_asm};
#[cfg(target_arch = "riscv32")]
global_asm!(
r"
.equ XLENB, 4
.macro LOAD_SP a1, a2
lw \a1, \a2*XLENB(sp)
.endm
.macro STORE_SP a1, a2
sw \a1, \a2*XLENB(sp)
.endm
",
include_str!("trap.S")
);
#[cfg(target_arch = "riscv64")]
global_asm!(
r"
.equ XLENB, 8
.macro LOAD_SP a1, a2
ld \a1, \a2*XLENB(sp)
.endm
.macro STORE_SP a1, a2
sd \a1, \a2*XLENB(sp)
.endm
",
include_str!("trap.S")
);
pub unsafe fn init() {
asm!("csrw sscratch, zero");
asm!("csrw stvec, {}", in(reg) trap_entry as usize);
}
#[no_mangle]
#[linkage = "weak"]
extern "C" fn trap_handler(tf: &mut TrapFrame) {
unimplemented!("TRAP: tf={:#x?}", tf);
}
#[derive(Debug, Default, Clone, Copy)]
#[repr(C)]
pub struct TrapFrame {
pub general: GeneralRegs,
pub sstatus: usize,
pub sepc: usize,
}
#[derive(Debug, Default, Clone, Copy)]
#[repr(C)]
pub struct UserContext {
pub general: GeneralRegs,
pub sstatus: usize,
pub sepc: usize,
}
impl UserContext {
pub fn run(&mut self) {
unsafe { run_user(self) }
}
}
#[derive(Debug, Default, Clone, Copy)]
#[repr(C)]
pub struct GeneralRegs {
pub zero: usize,
pub ra: usize,
pub sp: usize,
pub gp: usize,
pub tp: usize,
pub t0: usize,
pub t1: usize,
pub t2: usize,
pub s0: usize,
pub s1: usize,
pub a0: usize,
pub a1: usize,
pub a2: usize,
pub a3: usize,
pub a4: usize,
pub a5: usize,
pub a6: usize,
pub a7: usize,
pub s2: usize,
pub s3: usize,
pub s4: usize,
pub s5: usize,
pub s6: usize,
pub s7: usize,
pub s8: usize,
pub s9: usize,
pub s10: usize,
pub s11: usize,
pub t3: usize,
pub t4: usize,
pub t5: usize,
pub t6: usize,
}
impl UserContext {
pub fn get_syscall_num(&self) -> usize {
self.general.a7
}
pub fn get_syscall_ret(&self) -> usize {
self.general.a0
}
pub fn set_syscall_ret(&mut self, ret: usize) {
self.general.a0 = ret;
}
pub fn get_syscall_args(&self) -> [usize; 6] {
[
self.general.a0,
self.general.a1,
self.general.a2,
self.general.a3,
self.general.a4,
self.general.a5,
]
}
pub fn set_ip(&mut self, ip: usize) {
self.sepc = ip;
}
pub fn set_sp(&mut self, sp: usize) {
self.general.sp = sp;
}
pub fn get_sp(&self) -> usize {
self.general.sp
}
pub fn set_tls(&mut self, tls: usize) {
self.general.tp = tls;
}
}
#[allow(improper_ctypes)]
extern "C" {
fn trap_entry();
fn run_user(regs: &mut UserContext);
}