mod.rs 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. mod captured;
  2. mod default;
  3. mod trap_context;
  4. use core::arch::{global_asm, naked_asm};
  5. use core::mem::{offset_of, size_of};
  6. use core::num::NonZero;
  7. use core::ptr::NonNull;
  8. use captured::{_captured_trap_entry, _captured_trap_return};
  9. use default::_default_trap_entry;
  10. use eonix_hal_traits::context::RawTaskContext;
  11. use eonix_hal_traits::trap::{IrqState as IrqStateTrait, TrapReturn};
  12. use riscv::asm::sfence_vma_all;
  13. use riscv::register::sstatus::{self, Sstatus};
  14. use riscv::register::stvec::{self, Stvec, TrapMode};
  15. use riscv::register::{scause, sepc, sscratch, stval};
  16. use sbi::SbiError;
  17. pub use trap_context::*;
  18. use super::config::platform::virt::*;
  19. impl TrapReturn for TrapContext {
  20. unsafe fn trap_return(&mut self) {
  21. let irq_states = disable_irqs_save();
  22. let old_stvec = stvec::read();
  23. stvec::write({
  24. let mut stvec_val = Stvec::from_bits(0);
  25. stvec_val.set_address(_captured_trap_entry as usize);
  26. stvec_val.set_trap_mode(TrapMode::Direct);
  27. stvec_val
  28. });
  29. let old_trap_ctx = sscratch::read();
  30. sscratch::write(&raw mut *self as usize);
  31. unsafe {
  32. _captured_trap_return(self);
  33. }
  34. sscratch::write(old_trap_ctx);
  35. stvec::write(old_stvec);
  36. irq_states.restore();
  37. }
  38. unsafe fn trap_return_noreturn(&mut self) -> ! {
  39. disable_irqs();
  40. unsafe {
  41. _captured_trap_return(self);
  42. }
  43. unreachable!("trap_return_noreturn should not return");
  44. }
  45. }
  46. fn setup_trap_handler(trap_entry_addr: usize) {
  47. let mut stvec_val = Stvec::from_bits(0);
  48. stvec_val.set_address(trap_entry_addr);
  49. stvec_val.set_trap_mode(TrapMode::Direct);
  50. unsafe {
  51. stvec::write(stvec_val);
  52. }
  53. }
  54. pub fn setup_trap() {
  55. setup_trap_handler(_default_trap_entry as usize);
  56. }
  57. #[derive(Debug, Clone, Copy, PartialEq, Eq)]
  58. pub struct IrqState(Sstatus);
  59. impl IrqState {
  60. #[inline]
  61. pub fn save() -> Self {
  62. IrqState(sstatus::read())
  63. }
  64. }
  65. impl IrqStateTrait for IrqState {
  66. fn restore(self) {
  67. let Self(state) = self;
  68. unsafe {
  69. sstatus::write(state);
  70. }
  71. }
  72. }
  73. #[inline]
  74. pub fn disable_irqs() {
  75. unsafe {
  76. sstatus::clear_sie();
  77. }
  78. }
  79. #[inline]
  80. pub fn enable_irqs() {
  81. unsafe {
  82. sstatus::set_sie();
  83. }
  84. }
  85. #[inline]
  86. pub fn disable_irqs_save() -> IrqState {
  87. let state = IrqState::save();
  88. disable_irqs();
  89. state
  90. }