thread.rs 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. /// 线程上下文。
  2. #[repr(C)]
  3. pub struct Thread {
  4. sctx: usize,
  5. x: [usize; 31],
  6. sepc: usize,
  7. }
  8. #[allow(unused)]
  9. impl Thread {
  10. /// 创建空白上下文。
  11. #[inline]
  12. pub const fn new(sepc: usize) -> Self {
  13. Self {
  14. sctx: 0,
  15. x: [0; 31],
  16. sepc,
  17. }
  18. }
  19. /// 读取通用寄存器。
  20. #[inline]
  21. pub fn x(&self, n: usize) -> usize {
  22. self.x[n - 1]
  23. }
  24. /// 修改通用寄存器。
  25. #[inline]
  26. pub fn x_mut(&mut self, n: usize) -> &mut usize {
  27. &mut self.x[n - 1]
  28. }
  29. /// 读取参数寄存器。
  30. #[inline]
  31. pub fn a(&self, n: usize) -> usize {
  32. self.x(n + 10)
  33. }
  34. /// 修改参数寄存器。
  35. #[inline]
  36. pub fn a_mut(&mut self, n: usize) -> &mut usize {
  37. self.x_mut(n + 10)
  38. }
  39. /// 读取栈指针。
  40. #[inline]
  41. pub fn sp(&self) -> usize {
  42. self.x(2)
  43. }
  44. /// 修改栈指针。
  45. #[inline]
  46. pub fn sp_mut(&mut self) -> &mut usize {
  47. self.x_mut(2)
  48. }
  49. /// 将 pc 移至下一条指令。
  50. ///
  51. /// # Notice
  52. ///
  53. /// 假设这一条指令不是压缩版本。
  54. #[inline]
  55. pub fn move_next(&mut self) {
  56. self.sepc = self.sepc.wrapping_add(4);
  57. }
  58. /// 执行此线程,并返回 `sstatus`。
  59. ///
  60. /// # Safety
  61. ///
  62. /// 将修改 `sscratch`、`sepc`、`sstatus` 和 `stvec`。
  63. #[inline]
  64. pub unsafe fn execute(&mut self) -> usize {
  65. unsafe {
  66. // 设置线程仍在 S 态并打开中断
  67. let mut sstatus: usize;
  68. core::arch::asm!("csrr {}, sstatus", out(reg) sstatus);
  69. const PREVILEGE_BIT: usize = 1 << 8;
  70. const INTERRUPT_BIT: usize = 1 << 5;
  71. sstatus |= PREVILEGE_BIT | INTERRUPT_BIT;
  72. // 执行线程
  73. // TODO support RV32 instruction set
  74. core::arch::asm!(
  75. " csrw sscratch, {sscratch}
  76. csrw sepc , {sepc}
  77. csrw sstatus , {sstatus}
  78. addi sp, sp, -8
  79. sd ra, (sp)
  80. call {execute_naked}
  81. ld ra, (sp)
  82. addi sp, sp, 8
  83. csrr {sepc} , sepc
  84. csrr {sstatus}, sstatus
  85. ",
  86. sscratch = in(reg) self,
  87. sepc = inlateout(reg) self.sepc,
  88. sstatus = inlateout(reg) sstatus,
  89. execute_naked = sym execute_naked,
  90. );
  91. sstatus
  92. }
  93. }
  94. }
  95. /// 线程切换核心部分。
  96. ///
  97. /// 通用寄存器压栈,然后从预存在 `sscratch` 里的上下文指针恢复线程通用寄存器。
  98. ///
  99. /// # Safety
  100. ///
  101. /// 裸函数。
  102. #[naked]
  103. unsafe extern "C" fn execute_naked() {
  104. unsafe {
  105. core::arch::naked_asm!(
  106. r" .altmacro
  107. .macro SAVE n
  108. sd x\n, \n*8(sp)
  109. .endm
  110. .macro SAVE_ALL
  111. sd x1, 1*8(sp)
  112. .set n, 3
  113. .rept 29
  114. SAVE %n
  115. .set n, n+1
  116. .endr
  117. .endm
  118. .macro LOAD n
  119. ld x\n, \n*8(sp)
  120. .endm
  121. .macro LOAD_ALL
  122. ld x1, 1*8(sp)
  123. .set n, 3
  124. .rept 29
  125. LOAD %n
  126. .set n, n+1
  127. .endr
  128. .endm
  129. ",
  130. // 位置无关加载
  131. " .option push
  132. .option nopic
  133. ",
  134. // 保存调度上下文
  135. " addi sp, sp, -32*8
  136. SAVE_ALL
  137. ",
  138. // 设置陷入入口
  139. " la t0, 2f
  140. csrw stvec, t0
  141. ",
  142. // 保存调度上下文地址并切换上下文
  143. " csrr t0, sscratch
  144. sd sp, (t0)
  145. mv sp, t0
  146. ",
  147. // 恢复线程上下文
  148. " LOAD_ALL
  149. ld sp, 2*8(sp)
  150. ",
  151. // 执行线程
  152. " sret",
  153. // 陷入
  154. " .align 2",
  155. // 切换上下文
  156. "2: csrrw sp, sscratch, sp",
  157. // 保存线程上下文
  158. " SAVE_ALL
  159. csrrw t0, sscratch, sp
  160. sd t0, 2*8(sp)
  161. ",
  162. // 切换上下文
  163. " ld sp, (sp)",
  164. // 恢复调度上下文
  165. " LOAD_ALL
  166. addi sp, sp, 32*8
  167. ",
  168. // 返回调度
  169. " ret",
  170. " .option pop",
  171. )
  172. }
  173. }