hsm.rs 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. use core::{
  2. cell::UnsafeCell,
  3. hint::spin_loop,
  4. sync::atomic::{AtomicUsize, Ordering},
  5. };
  6. use rustsbi::{spec::hsm::hart_state, SbiRet};
  7. use riscv::register::mstatus::MPP;
  8. use crate::NextStage;
  9. use crate::trap_stack::ROOT_STACK;
  10. use crate::riscv_spec::current_hartid;
  11. use crate::clint;
  12. const HART_STATE_START_PENDING_EXT: usize = usize::MAX;
  13. type HsmState = AtomicUsize;
  14. pub(crate) struct HsmCell<T> {
  15. status: HsmState,
  16. inner: UnsafeCell<Option<T>>,
  17. }
  18. impl<T> HsmCell<T> {
  19. /// 创建一个新的共享对象。
  20. pub const fn new() -> Self {
  21. Self {
  22. status: HsmState::new(hart_state::STOPPED),
  23. inner: UnsafeCell::new(None),
  24. }
  25. }
  26. /// 从当前硬件线程的状态中获取线程间共享对象。
  27. ///
  28. /// # Safety
  29. ///
  30. /// 用户需要确保对象属于当前硬件线程。
  31. #[inline]
  32. pub unsafe fn local(&self) -> LocalHsmCell<'_, T> {
  33. LocalHsmCell(self)
  34. }
  35. /// 取出共享对象。
  36. #[inline]
  37. pub fn remote(&self) -> RemoteHsmCell<'_, T> {
  38. RemoteHsmCell(self)
  39. }
  40. }
  41. /// 当前硬件线程的共享对象。
  42. pub struct LocalHsmCell<'a, T>(&'a HsmCell<T>);
  43. /// 任意硬件线程的共享对象。
  44. pub struct RemoteHsmCell<'a, T>(&'a HsmCell<T>);
  45. unsafe impl<T: Send> Sync for HsmCell<T> {}
  46. unsafe impl<T: Send> Send for HsmCell<T> {}
  47. impl<T> LocalHsmCell<'_, T> {
  48. /// 从启动挂起状态的硬件线程取出共享数据,并将其状态设置为启动,如果成功返回取出的数据,否则返回当前状态。
  49. #[inline]
  50. pub fn start(&self) -> Result<T, usize> {
  51. loop {
  52. match self.0.status.compare_exchange(
  53. hart_state::START_PENDING,
  54. hart_state::STARTED,
  55. Ordering::AcqRel,
  56. Ordering::Relaxed,
  57. ) {
  58. Ok(_) => break Ok(unsafe { (*self.0.inner.get()).take().unwrap() }),
  59. Err(HART_STATE_START_PENDING_EXT) => spin_loop(),
  60. Err(s) => break Err(s),
  61. }
  62. }
  63. }
  64. /// 关闭。
  65. #[allow(unused)]
  66. #[inline]
  67. pub fn stop(&self) {
  68. self.0.status.store(hart_state::STOPPED, Ordering::Release)
  69. }
  70. /// 关闭。
  71. #[allow(unused)]
  72. #[inline]
  73. pub fn suspend(&self) {
  74. self.0
  75. .status
  76. .store(hart_state::SUSPENDED, Ordering::Relaxed)
  77. }
  78. /// 关闭。
  79. #[allow(unused)]
  80. #[inline]
  81. pub fn resume(&self) {
  82. self.0.status.store(hart_state::STARTED, Ordering::Relaxed)
  83. }
  84. }
  85. impl<T : core::fmt::Debug> RemoteHsmCell<'_, T> {
  86. /// 向关闭状态的硬件线程传入共享数据,并将其状态设置为启动挂起,返回是否放入成功。
  87. #[inline]
  88. pub fn start(&self, t: T) -> bool {
  89. if self
  90. .0
  91. .status
  92. .compare_exchange(
  93. hart_state::STOPPED,
  94. HART_STATE_START_PENDING_EXT,
  95. Ordering::Acquire,
  96. Ordering::Relaxed,
  97. )
  98. .is_ok()
  99. {
  100. unsafe { *self.0.inner.get() = Some(t) };
  101. self.0
  102. .status
  103. .store(hart_state::START_PENDING, Ordering::Release);
  104. true
  105. } else {
  106. false
  107. }
  108. }
  109. /// 取出当前状态。
  110. #[allow(unused)]
  111. #[inline]
  112. pub fn sbi_get_status(&self) -> usize {
  113. match self.0.status.load(Ordering::Relaxed) {
  114. HART_STATE_START_PENDING_EXT => hart_state::START_PENDING,
  115. normal => normal,
  116. }
  117. }
  118. /// 判断这个 HART 能否接收 IPI。
  119. #[allow(unused)]
  120. #[inline]
  121. pub fn allow_ipi(&self) -> bool {
  122. matches!(
  123. self.0.status.load(Ordering::Relaxed),
  124. hart_state::STARTED | hart_state::SUSPENDED
  125. )
  126. }
  127. }
  128. /// 获取此 hart 的 local hsm 对象。
  129. pub(crate) fn local_hsm() -> LocalHsmCell<'static, NextStage> {
  130. unsafe {
  131. ROOT_STACK
  132. .get_unchecked_mut(current_hartid())
  133. .hart_context()
  134. .hsm
  135. .local()
  136. }
  137. }
  138. /// 获取此 hart 的 remote hsm 对象。
  139. pub(crate) fn local_remote_hsm() -> RemoteHsmCell<'static, NextStage> {
  140. unsafe {
  141. ROOT_STACK
  142. .get_unchecked_mut(current_hartid())
  143. .hart_context()
  144. .hsm
  145. .remote()
  146. }
  147. }
  148. /// 获取任意 hart 的 remote hsm 对象。
  149. #[allow(unused)]
  150. pub(crate) fn remote_hsm(hart_id: usize) -> Option<RemoteHsmCell<'static, NextStage>> {
  151. unsafe {
  152. ROOT_STACK
  153. .get_mut(hart_id)
  154. .map(|x| x.hart_context().hsm.remote())
  155. }
  156. }
  157. /// HSM
  158. pub(crate) struct Hsm;
  159. impl rustsbi::Hsm for Hsm {
  160. fn hart_start(&self, hartid: usize, start_addr: usize, opaque: usize) -> SbiRet {
  161. match remote_hsm(hartid) {
  162. Some(remote) => {
  163. if remote.start(NextStage { start_addr, opaque, next_mode: MPP::Supervisor }) {
  164. clint::set_msip(hartid);
  165. SbiRet::success(0)
  166. } else {
  167. SbiRet::already_started()
  168. }
  169. }
  170. None => SbiRet::invalid_param(),
  171. }
  172. }
  173. #[inline]
  174. fn hart_stop(&self) -> SbiRet {
  175. local_hsm().stop();
  176. clint::clear_msip();
  177. unsafe { riscv::register::mie::clear_msoft(); }
  178. riscv::asm::wfi();
  179. SbiRet::success(0)
  180. }
  181. #[inline]
  182. fn hart_get_status(&self, hartid: usize) -> SbiRet {
  183. match remote_hsm(hartid) {
  184. Some(remote) => SbiRet::success(remote.sbi_get_status()),
  185. None => SbiRet::invalid_param(),
  186. }
  187. }
  188. fn hart_suspend(&self, suspend_type: u32, _resume_addr: usize, _opaque: usize) -> SbiRet {
  189. use rustsbi::spec::hsm::suspend_type::{NON_RETENTIVE, RETENTIVE};
  190. if matches!(suspend_type, NON_RETENTIVE | RETENTIVE) {
  191. local_hsm().suspend();
  192. clint::clear_msip();
  193. unsafe { riscv::register::mie::set_msoft(); }
  194. riscv::asm::wfi();
  195. local_hsm().resume();
  196. SbiRet::success(0)
  197. } else {
  198. SbiRet::not_supported()
  199. }
  200. }
  201. }