|
@@ -1,5 +1,7 @@
|
|
|
use crate::hart_mask::HartMask;
|
|
|
use crate::ecall::SbiRet;
|
|
|
+use alloc::boxed::Box;
|
|
|
+use crate::util::OnceFatBox;
|
|
|
|
|
|
/// Remote fence support
|
|
|
///
|
|
@@ -16,7 +18,7 @@ pub trait Rfence: Send {
|
|
|
/// # Return value
|
|
|
///
|
|
|
/// Returns `SBI_SUCCESS` when remote fence was sent to all the targeted harts successfully.
|
|
|
- fn remote_fence_i(&mut self, hart_mask: HartMask) -> SbiRet;
|
|
|
+ fn remote_fence_i(&self, hart_mask: HartMask) -> SbiRet;
|
|
|
/// Instructs the remote harts to execute one or more `SFENCE.VMA` instructions,
|
|
|
/// covering the range of virtual addresses between start and size.
|
|
|
///
|
|
@@ -28,7 +30,7 @@ pub trait Rfence: Send {
|
|
|
/// |:--------------------------|:----------------------------------------------
|
|
|
/// | SBI_SUCCESS | Remote fence was sent to all the targeted harts successfully.
|
|
|
/// | SBI_ERR_INVALID_ADDRESS | `start_addr` or `size` is not valid.
|
|
|
- fn remote_sfence_vma(&mut self, hart_mask: HartMask, start_addr: usize, size: usize) -> SbiRet;
|
|
|
+ fn remote_sfence_vma(&self, hart_mask: HartMask, start_addr: usize, size: usize) -> SbiRet;
|
|
|
/// Instruct the remote harts to execute one or more `SFENCE.VMA` instructions,
|
|
|
/// covering the range of virtual addresses between start and size. This covers only the given `ASID`.
|
|
|
///
|
|
@@ -40,7 +42,7 @@ pub trait Rfence: Send {
|
|
|
/// |:--------------------------|:----------------------------------------------
|
|
|
/// | SBI_SUCCESS | Remote fence was sent to all the targeted harts successfully.
|
|
|
/// | SBI_ERR_INVALID_ADDRESS | `start_addr` or `size` is not valid.
|
|
|
- fn remote_sfence_vma_asid(&mut self, hart_mask: HartMask, start_addr: usize, size: usize, asid: usize) -> SbiRet;
|
|
|
+ fn remote_sfence_vma_asid(&self, hart_mask: HartMask, start_addr: usize, size: usize, asid: usize) -> SbiRet;
|
|
|
/// Instruct the remote harts to execute one or more `HFENCE.GVMA` instructions,
|
|
|
/// covering the range of guest physical addresses between start and size only for the given `VMID`.
|
|
|
///
|
|
@@ -55,7 +57,7 @@ pub trait Rfence: Send {
|
|
|
/// | SBI_SUCCESS | Remote fence was sent to all the targeted harts successfully.
|
|
|
/// | 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.
|
|
|
/// | SBI_ERR_INVALID_ADDRESS | `start_addr` or `size` is not valid.
|
|
|
- fn remote_hfence_gvma_vmid(&mut self, hart_mask: HartMask, start_addr: usize, size: usize, vmid: usize) -> SbiRet {
|
|
|
+ fn remote_hfence_gvma_vmid(&self, hart_mask: HartMask, start_addr: usize, size: usize, vmid: usize) -> SbiRet {
|
|
|
drop((hart_mask, start_addr, size, vmid));
|
|
|
SbiRet::not_supported()
|
|
|
}
|
|
@@ -73,7 +75,7 @@ pub trait Rfence: Send {
|
|
|
/// | SBI_SUCCESS | Remote fence was sent to all the targeted harts successfully.
|
|
|
/// | 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.
|
|
|
/// | SBI_ERR_INVALID_ADDRESS | `start_addr` or `size` is not valid.
|
|
|
- fn remote_hfence_gvma(&mut self, hart_mask: HartMask, start_addr: usize, size: usize) -> SbiRet {
|
|
|
+ fn remote_hfence_gvma(&self, hart_mask: HartMask, start_addr: usize, size: usize) -> SbiRet {
|
|
|
drop((hart_mask, start_addr, size));
|
|
|
SbiRet::not_supported()
|
|
|
}
|
|
@@ -92,7 +94,7 @@ pub trait Rfence: Send {
|
|
|
/// | SBI_SUCCESS | Remote fence was sent to all the targeted harts successfully.
|
|
|
/// | 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.
|
|
|
/// | SBI_ERR_INVALID_ADDRESS | `start_addr` or `size` is not valid.
|
|
|
- fn remote_hfence_vvma_asid(&mut self, hart_mask: HartMask, start_addr: usize, size: usize, asid: usize) -> SbiRet {
|
|
|
+ fn remote_hfence_vvma_asid(&self, hart_mask: HartMask, start_addr: usize, size: usize, asid: usize) -> SbiRet {
|
|
|
drop((hart_mask, start_addr, size, asid));
|
|
|
SbiRet::not_supported()
|
|
|
}
|
|
@@ -111,31 +113,29 @@ pub trait Rfence: Send {
|
|
|
/// | SBI_SUCCESS | Remote fence was sent to all the targeted harts successfully.
|
|
|
/// | 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.
|
|
|
/// | SBI_ERR_INVALID_ADDRESS | `start_addr` or `size` is not valid.
|
|
|
- fn remote_hfence_vvma(&mut self, hart_mask: HartMask, start_addr: usize, size: usize) -> SbiRet {
|
|
|
+ fn remote_hfence_vvma(&self, hart_mask: HartMask, start_addr: usize, size: usize) -> SbiRet {
|
|
|
drop((hart_mask, start_addr, size));
|
|
|
SbiRet::not_supported()
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-use alloc::boxed::Box;
|
|
|
-use spin::Mutex;
|
|
|
-
|
|
|
-lazy_static::lazy_static! {
|
|
|
- static ref RFENCE: Mutex<Option<Box<dyn Rfence>>> = Mutex::new(None);
|
|
|
-}
|
|
|
+static RFENCE: OnceFatBox<dyn Rfence + Sync + 'static> = OnceFatBox::new();
|
|
|
|
|
|
#[doc(hidden)] // use through a macro
|
|
|
-pub fn init_rfence<T: Rfence + Send + 'static>(rfence: T) {
|
|
|
- *RFENCE.lock() = Some(Box::new(rfence));
|
|
|
+pub fn init_rfence<T: Rfence + Sync + 'static>(rfence: T) {
|
|
|
+ let result = RFENCE.set(Box::new(rfence));
|
|
|
+ if result.is_err() {
|
|
|
+ panic!("load sbi module when already loaded")
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
#[inline]
|
|
|
pub(crate) fn probe_rfence() -> bool {
|
|
|
- RFENCE.lock().as_ref().is_some()
|
|
|
+ RFENCE.get().is_some()
|
|
|
}
|
|
|
|
|
|
pub(crate) fn remote_fence_i(hart_mask: HartMask) -> SbiRet {
|
|
|
- if let Some(rfence) = RFENCE.lock().as_mut() {
|
|
|
+ if let Some(rfence) = RFENCE.get() {
|
|
|
rfence.remote_fence_i(hart_mask)
|
|
|
} else {
|
|
|
SbiRet::not_supported()
|
|
@@ -143,7 +143,7 @@ pub(crate) fn remote_fence_i(hart_mask: HartMask) -> SbiRet {
|
|
|
}
|
|
|
|
|
|
pub(crate) fn remote_sfence_vma(hart_mask: HartMask, start_addr: usize, size: usize) -> SbiRet {
|
|
|
- if let Some(rfence) = RFENCE.lock().as_mut() {
|
|
|
+ if let Some(rfence) = RFENCE.get() {
|
|
|
rfence.remote_sfence_vma(hart_mask, start_addr, size)
|
|
|
} else {
|
|
|
SbiRet::not_supported()
|
|
@@ -151,7 +151,7 @@ pub(crate) fn remote_sfence_vma(hart_mask: HartMask, start_addr: usize, size: us
|
|
|
}
|
|
|
|
|
|
pub(crate) fn remote_sfence_vma_asid(hart_mask: HartMask, start_addr: usize, size: usize, asid: usize) -> SbiRet {
|
|
|
- if let Some(rfence) = RFENCE.lock().as_mut() {
|
|
|
+ if let Some(rfence) = RFENCE.get() {
|
|
|
rfence.remote_sfence_vma_asid(hart_mask, start_addr, size, asid)
|
|
|
} else {
|
|
|
SbiRet::not_supported()
|
|
@@ -159,7 +159,7 @@ pub(crate) fn remote_sfence_vma_asid(hart_mask: HartMask, start_addr: usize, siz
|
|
|
}
|
|
|
|
|
|
pub(crate) fn remote_hfence_gvma_vmid(hart_mask: HartMask, start_addr: usize, size: usize, vmid: usize) -> SbiRet {
|
|
|
- if let Some(rfence) = RFENCE.lock().as_mut() {
|
|
|
+ if let Some(rfence) = RFENCE.get() {
|
|
|
rfence.remote_hfence_gvma_vmid(hart_mask, start_addr, size, vmid)
|
|
|
} else {
|
|
|
SbiRet::not_supported()
|
|
@@ -167,7 +167,7 @@ pub(crate) fn remote_hfence_gvma_vmid(hart_mask: HartMask, start_addr: usize, si
|
|
|
}
|
|
|
|
|
|
pub(crate) fn remote_hfence_gvma(hart_mask: HartMask, start_addr: usize, size: usize) -> SbiRet {
|
|
|
- if let Some(rfence) = RFENCE.lock().as_mut() {
|
|
|
+ if let Some(rfence) = RFENCE.get() {
|
|
|
rfence.remote_hfence_gvma(hart_mask, start_addr, size)
|
|
|
} else {
|
|
|
SbiRet::not_supported()
|
|
@@ -175,7 +175,7 @@ pub(crate) fn remote_hfence_gvma(hart_mask: HartMask, start_addr: usize, size: u
|
|
|
}
|
|
|
|
|
|
pub(crate) fn remote_hfence_vvma_asid(hart_mask: HartMask, start_addr: usize, size: usize, asid: usize) -> SbiRet {
|
|
|
- if let Some(rfence) = RFENCE.lock().as_mut() {
|
|
|
+ if let Some(rfence) = RFENCE.get() {
|
|
|
rfence.remote_hfence_vvma_asid(hart_mask, start_addr, size, asid)
|
|
|
} else {
|
|
|
SbiRet::not_supported()
|
|
@@ -183,7 +183,7 @@ pub(crate) fn remote_hfence_vvma_asid(hart_mask: HartMask, start_addr: usize, si
|
|
|
}
|
|
|
|
|
|
pub(crate) fn remote_hfence_vvma(hart_mask: HartMask, start_addr: usize, size: usize) -> SbiRet {
|
|
|
- if let Some(rfence) = RFENCE.lock().as_mut() {
|
|
|
+ if let Some(rfence) = RFENCE.get() {
|
|
|
rfence.remote_hfence_vvma(hart_mask, start_addr, size)
|
|
|
} else {
|
|
|
SbiRet::not_supported()
|