mod.rs 2.6 KB

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