| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112 |
- mod captured;
- mod default;
- mod trap_context;
- use core::arch::{global_asm, naked_asm};
- use core::mem::{offset_of, size_of};
- use core::num::NonZero;
- use core::ptr::NonNull;
- use captured::{_captured_trap_entry, _captured_trap_return};
- use default::_default_trap_entry;
- use eonix_hal_traits::context::RawTaskContext;
- use eonix_hal_traits::trap::{IrqState as IrqStateTrait, TrapReturn};
- use riscv::asm::sfence_vma_all;
- use riscv::register::sstatus::{self, Sstatus};
- use riscv::register::stvec::{self, Stvec, TrapMode};
- use riscv::register::{scause, sepc, sscratch, stval};
- use sbi::SbiError;
- pub use trap_context::*;
- use super::config::platform::virt::*;
- impl TrapReturn for TrapContext {
- unsafe fn trap_return(&mut self) {
- let irq_states = disable_irqs_save();
- let old_stvec = stvec::read();
- stvec::write({
- let mut stvec_val = Stvec::from_bits(0);
- stvec_val.set_address(_captured_trap_entry as usize);
- stvec_val.set_trap_mode(TrapMode::Direct);
- stvec_val
- });
- let old_trap_ctx = sscratch::read();
- sscratch::write(&raw mut *self as usize);
- unsafe {
- _captured_trap_return(self);
- }
- sscratch::write(old_trap_ctx);
- stvec::write(old_stvec);
- irq_states.restore();
- }
- unsafe fn trap_return_noreturn(&mut self) -> ! {
- disable_irqs();
- unsafe {
- _captured_trap_return(self);
- }
- unreachable!("trap_return_noreturn should not return");
- }
- }
- fn setup_trap_handler(trap_entry_addr: usize) {
- let mut stvec_val = Stvec::from_bits(0);
- stvec_val.set_address(trap_entry_addr);
- stvec_val.set_trap_mode(TrapMode::Direct);
- unsafe {
- stvec::write(stvec_val);
- }
- }
- pub fn setup_trap() {
- setup_trap_handler(_default_trap_entry as usize);
- }
- #[derive(Debug, Clone, Copy, PartialEq, Eq)]
- pub struct IrqState(Sstatus);
- impl IrqState {
- #[inline]
- pub fn save() -> Self {
- IrqState(sstatus::read())
- }
- }
- impl IrqStateTrait for IrqState {
- fn restore(self) {
- let Self(state) = self;
- unsafe {
- sstatus::write(state);
- }
- }
- }
- #[inline]
- pub fn disable_irqs() {
- unsafe {
- sstatus::clear_sie();
- }
- }
- #[inline]
- pub fn enable_irqs() {
- unsafe {
- sstatus::set_sie();
- }
- }
- #[inline]
- pub fn disable_irqs_save() -> IrqState {
- let state = IrqState::save();
- disable_irqs();
- state
- }
|