trap_stack.rs 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. use core::mem::forget;
  2. use fast_trap::FreeTrapStack;
  3. use crate::hsm::HartContext;
  4. use crate::trap::fast_handler;
  5. use crate::hart_id;
  6. const LEN_STACK_PER_HART: usize = 16 * 1024;
  7. pub const NUM_HART_MAX: usize = 8;
  8. /// 栈空间。
  9. #[link_section = ".bss.uninit"]
  10. pub(crate) static mut ROOT_STACK: [Stack; NUM_HART_MAX] = [Stack::ZERO; NUM_HART_MAX];
  11. /// 定位每个 hart 的栈。
  12. #[naked]
  13. pub(crate) unsafe extern "C" fn locate() {
  14. core::arch::asm!(
  15. " la sp, {stack}
  16. li t0, {per_hart_stack_size}
  17. csrr t1, mhartid
  18. addi t1, t1, 1
  19. 1: add sp, sp, t0
  20. addi t1, t1, -1
  21. bnez t1, 1b
  22. call t1, {move_stack}
  23. ret
  24. ",
  25. per_hart_stack_size = const LEN_STACK_PER_HART,
  26. stack = sym ROOT_STACK,
  27. move_stack = sym fast_trap::reuse_stack_for_trap,
  28. options(noreturn),
  29. )
  30. }
  31. /// 预备陷入栈。
  32. pub(crate) fn prepare_for_trap() {
  33. unsafe { ROOT_STACK.get_unchecked_mut(hart_id()).load_as_stack() };
  34. }
  35. /// 类型化栈。
  36. ///
  37. /// 每个硬件线程拥有一个满足这样条件的内存块。
  38. /// 这个内存块的底部放着硬件线程状态 [`HartContext`],顶部用于陷入处理,中间是这个硬件线程的栈空间。
  39. /// 不需要 M 态线程,每个硬件线程只有这一个栈。
  40. #[repr(C, align(128))]
  41. pub(crate) struct Stack([u8; LEN_STACK_PER_HART]);
  42. impl Stack {
  43. /// 零初始化以避免加载。
  44. const ZERO: Self = Self([0; LEN_STACK_PER_HART]);
  45. /// 从栈上取出硬件线程状态。
  46. #[inline]
  47. pub fn hart_context(&mut self) -> &mut HartContext {
  48. unsafe { &mut *self.0.as_mut_ptr().cast() }
  49. }
  50. fn load_as_stack(&'static mut self) {
  51. let hart = self.hart_context();
  52. let context_ptr = hart.context_ptr();
  53. hart.init();
  54. let range = self.0.as_ptr_range();
  55. forget(
  56. FreeTrapStack::new(
  57. range.start as usize..range.end as usize,
  58. |_| {},
  59. context_ptr,
  60. fast_handler,
  61. )
  62. .unwrap()
  63. .load(),
  64. );
  65. }
  66. }