rfence.rs 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. use crate::ecall::SbiRet;
  2. use crate::hart_mask::HartMask;
  3. use crate::util::OnceFatBox;
  4. use alloc::boxed::Box;
  5. /// Remote fence support
  6. ///
  7. /// The remote fence function acts as a full TLB flush if
  8. /// - `start_addr` and `size` are both 0, or
  9. /// - `size` is equal to `usize::MAX`.
  10. pub trait Rfence: Send {
  11. /// Instructs remote harts to execute `FENCE.I` instruction.
  12. ///
  13. /// # Return value
  14. ///
  15. /// Returns `SBI_SUCCESS` when remote fence was sent to all the targeted harts successfully.
  16. fn remote_fence_i(&self, hart_mask: HartMask) -> SbiRet;
  17. /// Instructs the remote harts to execute one or more `SFENCE.VMA` instructions,
  18. /// covering the range of virtual addresses between `start_addr` and `size`.
  19. ///
  20. /// # Return value
  21. ///
  22. /// The possible return error codes returned in `SbiRet.error` are shown in the table below:
  23. ///
  24. /// | Return code | Description
  25. /// |:--------------------------|:----------------------------------------------
  26. /// | SBI_SUCCESS | Remote fence was sent to all the targeted harts successfully.
  27. /// | SBI_ERR_INVALID_ADDRESS | `start_addr` or `size` is not valid.
  28. fn remote_sfence_vma(&self, hart_mask: HartMask, start_addr: usize, size: usize) -> SbiRet;
  29. /// Instruct the remote harts to execute one or more `SFENCE.VMA` instructions,
  30. /// covering the range of virtual addresses between `start_addr` and `size`.
  31. /// This covers only the given address space by `asid`.
  32. ///
  33. /// # Return value
  34. ///
  35. /// The possible return error codes returned in `SbiRet.error` are shown in the table below:
  36. ///
  37. /// | Return code | Description
  38. /// |:--------------------------|:----------------------------------------------
  39. /// | SBI_SUCCESS | Remote fence was sent to all the targeted harts successfully.
  40. /// | SBI_ERR_INVALID_ADDRESS | `start_addr` or `size` is not valid.
  41. fn remote_sfence_vma_asid(
  42. &self,
  43. hart_mask: HartMask,
  44. start_addr: usize,
  45. size: usize,
  46. asid: usize,
  47. ) -> SbiRet;
  48. /// Instruct the remote harts to execute one or more `HFENCE.GVMA` instructions,
  49. /// covering the range of guest physical addresses between `start_addr` and `size`
  50. /// only for the given virtual machine by `vmid`.
  51. ///
  52. /// This function call is only valid for harts implementing hypervisor extension.
  53. ///
  54. /// # Return value
  55. ///
  56. /// The possible return error codes returned in `SbiRet.error` are shown in the table below:
  57. ///
  58. /// | Return code | Description
  59. /// |:--------------------------|:----------------------------------------------
  60. /// | SBI_SUCCESS | Remote fence was sent to all the targeted harts successfully.
  61. /// | SBI_ERR_NOT_SUPPORTED | This function is not supported as it is not implemented or one of the target hart doesn’t support hypervisor extension.
  62. /// | SBI_ERR_INVALID_ADDRESS | `start_addr` or `size` is not valid.
  63. fn remote_hfence_gvma_vmid(
  64. &self,
  65. hart_mask: HartMask,
  66. start_addr: usize,
  67. size: usize,
  68. vmid: usize,
  69. ) -> SbiRet {
  70. drop((hart_mask, start_addr, size, vmid));
  71. SbiRet::not_supported()
  72. }
  73. /// Instruct the remote harts to execute one or more `HFENCE.GVMA` instructions,
  74. /// covering the range of guest physical addresses between `start_addr` and `size`
  75. /// for all the guests.
  76. ///
  77. /// This function call is only valid for harts implementing hypervisor extension.
  78. ///
  79. /// # Return value
  80. ///
  81. /// The possible return error codes returned in `SbiRet.error` are shown in the table below:
  82. ///
  83. /// | Return code | Description
  84. /// |:--------------------------|:----------------------------------------------
  85. /// | SBI_SUCCESS | Remote fence was sent to all the targeted harts successfully.
  86. /// | SBI_ERR_NOT_SUPPORTED | This function is not supported as it is not implemented or one of the target hart does not support hypervisor extension.
  87. /// | SBI_ERR_INVALID_ADDRESS | `start_addr` or `size` is not valid.
  88. fn remote_hfence_gvma(&self, hart_mask: HartMask, start_addr: usize, size: usize) -> SbiRet {
  89. drop((hart_mask, start_addr, size));
  90. SbiRet::not_supported()
  91. }
  92. /// Instruct the remote harts to execute one or more `HFENCE.VVMA` instructions,
  93. /// covering the range of guest virtual addresses between `start_addr` and `size` for the given
  94. /// address space by `asid` and current virtual machine (by `vmid` in `hgatp` CSR)
  95. /// of calling hart.
  96. ///
  97. /// This function call is only valid for harts implementing hypervisor extension.
  98. ///
  99. /// # Return value
  100. ///
  101. /// The possible return error codes returned in `SbiRet.error` are shown in the table below:
  102. ///
  103. /// | Return code | Description
  104. /// |:--------------------------|:----------------------------------------------
  105. /// | SBI_SUCCESS | Remote fence was sent to all the targeted harts successfully.
  106. /// | SBI_ERR_NOT_SUPPORTED | This function is not supported as it is not implemented or one of the target hart does not support hypervisor extension.
  107. /// | SBI_ERR_INVALID_ADDRESS | `start_addr` or `size` is not valid.
  108. fn remote_hfence_vvma_asid(
  109. &self,
  110. hart_mask: HartMask,
  111. start_addr: usize,
  112. size: usize,
  113. asid: usize,
  114. ) -> SbiRet {
  115. drop((hart_mask, start_addr, size, asid));
  116. SbiRet::not_supported()
  117. }
  118. /// Instruct the remote harts to execute one or more `HFENCE.VVMA` instructions,
  119. /// covering the range of guest virtual addresses between `start_addr` and `size`
  120. /// for current virtual machine (by `vmid` in `hgatp` CSR) of calling hart.
  121. ///
  122. /// This function call is only valid for harts implementing hypervisor extension.
  123. ///
  124. /// # Return value
  125. ///
  126. /// The possible return error codes returned in `SbiRet.error` are shown in the table below:
  127. ///
  128. /// | Return code | Description
  129. /// |:--------------------------|:----------------------------------------------
  130. /// | SBI_SUCCESS | Remote fence was sent to all the targeted harts successfully.
  131. /// | SBI_ERR_NOT_SUPPORTED | This function is not supported as it is not implemented or one of the target hart doesn’t support hypervisor extension.
  132. /// | SBI_ERR_INVALID_ADDRESS | `start_addr` or `size` is not valid.
  133. fn remote_hfence_vvma(&self, hart_mask: HartMask, start_addr: usize, size: usize) -> SbiRet {
  134. drop((hart_mask, start_addr, size));
  135. SbiRet::not_supported()
  136. }
  137. }
  138. static RFENCE: OnceFatBox<dyn Rfence + Sync + 'static> = OnceFatBox::new();
  139. #[doc(hidden)] // use through a macro
  140. pub fn init_rfence<T: Rfence + Sync + 'static>(rfence: T) {
  141. let result = RFENCE.set(Box::new(rfence));
  142. if result.is_err() {
  143. panic!("load sbi module when already loaded")
  144. }
  145. }
  146. #[inline]
  147. pub(crate) fn probe_rfence() -> bool {
  148. RFENCE.get().is_some()
  149. }
  150. pub(crate) fn remote_fence_i(hart_mask: HartMask) -> SbiRet {
  151. if let Some(rfence) = RFENCE.get() {
  152. rfence.remote_fence_i(hart_mask)
  153. } else {
  154. SbiRet::not_supported()
  155. }
  156. }
  157. pub(crate) fn remote_sfence_vma(hart_mask: HartMask, start_addr: usize, size: usize) -> SbiRet {
  158. if let Some(rfence) = RFENCE.get() {
  159. rfence.remote_sfence_vma(hart_mask, start_addr, size)
  160. } else {
  161. SbiRet::not_supported()
  162. }
  163. }
  164. pub(crate) fn remote_sfence_vma_asid(
  165. hart_mask: HartMask,
  166. start_addr: usize,
  167. size: usize,
  168. asid: usize,
  169. ) -> SbiRet {
  170. if let Some(rfence) = RFENCE.get() {
  171. rfence.remote_sfence_vma_asid(hart_mask, start_addr, size, asid)
  172. } else {
  173. SbiRet::not_supported()
  174. }
  175. }
  176. pub(crate) fn remote_hfence_gvma_vmid(
  177. hart_mask: HartMask,
  178. start_addr: usize,
  179. size: usize,
  180. vmid: usize,
  181. ) -> SbiRet {
  182. if let Some(rfence) = RFENCE.get() {
  183. rfence.remote_hfence_gvma_vmid(hart_mask, start_addr, size, vmid)
  184. } else {
  185. SbiRet::not_supported()
  186. }
  187. }
  188. pub(crate) fn remote_hfence_gvma(hart_mask: HartMask, start_addr: usize, size: usize) -> SbiRet {
  189. if let Some(rfence) = RFENCE.get() {
  190. rfence.remote_hfence_gvma(hart_mask, start_addr, size)
  191. } else {
  192. SbiRet::not_supported()
  193. }
  194. }
  195. pub(crate) fn remote_hfence_vvma_asid(
  196. hart_mask: HartMask,
  197. start_addr: usize,
  198. size: usize,
  199. asid: usize,
  200. ) -> SbiRet {
  201. if let Some(rfence) = RFENCE.get() {
  202. rfence.remote_hfence_vvma_asid(hart_mask, start_addr, size, asid)
  203. } else {
  204. SbiRet::not_supported()
  205. }
  206. }
  207. pub(crate) fn remote_hfence_vvma(hart_mask: HartMask, start_addr: usize, size: usize) -> SbiRet {
  208. if let Some(rfence) = RFENCE.get() {
  209. rfence.remote_hfence_vvma(hart_mask, start_addr, size)
  210. } else {
  211. SbiRet::not_supported()
  212. }
  213. }