trap.rs 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. use crate::{context::RawTaskContext, fault::Fault};
  2. use core::marker::PhantomData;
  3. use eonix_mm::address::VAddr;
  4. /// A raw trap context.
  5. ///
  6. /// This should be implemented by the architecture-specific trap context
  7. /// and will be used in the HAL crates.
  8. #[doc(notable_trait)]
  9. pub trait RawTrapContext: Copy {
  10. type FIrq: FnOnce(fn(irqno: usize));
  11. type FTimer: FnOnce(fn());
  12. fn new() -> Self;
  13. fn trap_type(&self) -> TrapType<Self::FIrq, Self::FTimer>;
  14. fn get_program_counter(&self) -> usize;
  15. fn get_stack_pointer(&self) -> usize;
  16. fn set_program_counter(&mut self, pc: usize);
  17. fn set_stack_pointer(&mut self, sp: usize);
  18. fn is_interrupt_enabled(&self) -> bool;
  19. fn set_interrupt_enabled(&mut self, enabled: bool);
  20. fn is_user_mode(&self) -> bool;
  21. fn set_user_mode(&mut self, user: bool);
  22. fn set_user_return_value(&mut self, retval: usize);
  23. fn set_user_call_frame<E>(
  24. &mut self,
  25. pc: usize,
  26. sp: Option<usize>,
  27. ra: Option<usize>,
  28. args: &[usize],
  29. write_memory: impl Fn(VAddr, &[u8]) -> Result<(), E>,
  30. ) -> Result<(), E>;
  31. }
  32. #[doc(notable_trait)]
  33. pub trait TrapReturn {
  34. type TaskContext: RawTaskContext;
  35. /// Return to the context before the trap occurred.
  36. ///
  37. /// # Safety
  38. /// This function is unsafe because the caller MUST ensure that the
  39. /// context before the trap is valid, that is, that the stack pointer
  40. /// points to a valid stack frame and the program counter points to some
  41. /// valid instruction.
  42. unsafe fn trap_return(&mut self);
  43. }
  44. pub trait IrqState {
  45. /// Restore the IRQ state.
  46. fn restore(self);
  47. }
  48. /// The reason that caused the trap.
  49. pub enum TrapType<FIrq, FTimer>
  50. where
  51. FIrq: FnOnce(fn(irqno: usize)),
  52. FTimer: FnOnce(fn()),
  53. {
  54. Syscall { no: usize, args: [usize; 6] },
  55. Fault(Fault),
  56. Irq { callback: FIrq },
  57. Timer { callback: FTimer },
  58. }
  59. /// A marker type that indicates that the type is a raw trap context.
  60. ///
  61. /// # Usage
  62. ///
  63. /// Check whether a type implements `RawTrapContext` using a `PhantomData` field.
  64. ///
  65. /// The following code should fail to compile:
  66. ///
  67. /// ```compile_fail
  68. /// # use eonix_hal_traits::trap::IsRawTrapContext;
  69. /// struct NonRawTrapContext; // Does not implement `RawTrapContext`!
  70. ///
  71. /// // Compile-time error: `NonRawTrapContext` does not implement `RawTrapContext`.
  72. /// struct UserStruct(NonRawTrapContext, IsRawTrapContext<NonRawTrapContext>);
  73. /// ```
  74. ///
  75. /// While the following code should compile:
  76. ///
  77. /// ```no_run
  78. /// # use eonix_hal_traits::trap::IsRawTrapContext;
  79. /// struct RawTrapContextType;
  80. ///
  81. /// impl RawTrapContext for RawTrapContextType {
  82. /// // ...
  83. /// # fn new() -> Self { todo!() }
  84. /// # fn trap_type() -> TrapType { todo!() }
  85. /// # fn get_program_counter(&self) -> usize { todo!() }
  86. /// # fn get_stack_pointer(&self) -> usize { todo!() }
  87. /// # fn set_program_counter(&mut self, _: usize) { todo!() }
  88. /// # fn set_stack_pointer(&mut self, _: usize) { todo!() }
  89. /// # fn is_interrupt_enabled(&self) -> bool { todo!() }
  90. /// # fn set_interrupt_enabled(&mut self, _: bool) { todo!() }
  91. /// # fn is_user_mode(&self) -> bool { todo!() }
  92. /// # fn set_user_mode(&mut self, _: bool) { todo!() }
  93. /// # fn set_user_return_value(&mut self, _: usize) { todo!() }
  94. /// }
  95. ///
  96. /// struct UserStruct(RawTrapContextType, IsRawTrapContext<RawTrapContextType>);
  97. /// ```
  98. pub struct IsRawTrapContext<T>(PhantomData<T>)
  99. where
  100. T: RawTrapContext;