use sbi_spec::binary::SbiRet;
pub trait Pmu: Send + Sync {
fn num_counters(&self) -> usize;
fn counter_get_info(&self, counter_idx: usize) -> SbiRet;
fn counter_config_matching(
&self,
counter_idx_base: usize,
counter_idx_mask: usize,
config_flags: usize,
event_idx: usize,
event_data: u64,
) -> SbiRet;
fn counter_start(
&self,
counter_idx_base: usize,
counter_idx_mask: usize,
start_flags: usize,
initial_value: u64,
) -> SbiRet;
fn counter_stop(
&self,
counter_idx_base: usize,
counter_idx_mask: usize,
stop_flags: usize,
) -> SbiRet;
fn counter_fw_read(&self, counter_idx: usize) -> SbiRet;
}
impl<T: Pmu> Pmu for &T {
#[inline]
fn num_counters(&self) -> usize {
T::num_counters(self)
}
#[inline]
fn counter_get_info(&self, counter_idx: usize) -> SbiRet {
T::counter_get_info(self, counter_idx)
}
#[inline]
fn counter_config_matching(
&self,
counter_idx_base: usize,
counter_idx_mask: usize,
config_flags: usize,
event_idx: usize,
event_data: u64,
) -> SbiRet {
T::counter_config_matching(
self,
counter_idx_base,
counter_idx_mask,
config_flags,
event_idx,
event_data,
)
}
#[inline]
fn counter_start(
&self,
counter_idx_base: usize,
counter_idx_mask: usize,
start_flags: usize,
initial_value: u64,
) -> SbiRet {
T::counter_start(
self,
counter_idx_base,
counter_idx_mask,
start_flags,
initial_value,
)
}
#[inline]
fn counter_stop(
&self,
counter_idx_base: usize,
counter_idx_mask: usize,
stop_flags: usize,
) -> SbiRet {
T::counter_stop(self, counter_idx_base, counter_idx_mask, stop_flags)
}
#[inline]
fn counter_fw_read(&self, counter_idx: usize) -> SbiRet {
T::counter_fw_read(self, counter_idx)
}
}
#[cfg(feature = "singleton")]
use crate::util::AmoOnceRef;
#[cfg(feature = "singleton")]
static PMU: AmoOnceRef<dyn Pmu> = AmoOnceRef::new();
#[cfg(feature = "singleton")]
pub fn init_pmu(pmu: &'static dyn Pmu) {
if !PMU.try_call_once(pmu) {
panic!("load sbi module when already loaded")
}
}
#[cfg(feature = "singleton")]
#[inline]
pub(crate) fn probe_pmu() -> bool {
PMU.get().is_some()
}
#[cfg(feature = "singleton")]
#[inline]
pub(crate) fn num_counters() -> SbiRet {
if let Some(obj) = PMU.get() {
return SbiRet::success(obj.num_counters());
}
SbiRet::not_supported()
}
#[cfg(feature = "singleton")]
#[inline]
pub(crate) fn counter_get_info(counter_idx: usize) -> SbiRet {
if let Some(obj) = PMU.get() {
return obj.counter_get_info(counter_idx);
}
SbiRet::not_supported()
}
#[cfg(feature = "singleton")]
#[inline]
pub(crate) fn counter_config_matching(
counter_idx_base: usize,
counter_idx_mask: usize,
config_flags: usize,
event_idx: usize,
event_data: u64,
) -> SbiRet {
if let Some(obj) = PMU.get() {
return obj.counter_config_matching(
counter_idx_base,
counter_idx_mask,
config_flags,
event_idx,
event_data,
);
}
SbiRet::not_supported()
}
#[cfg(feature = "singleton")]
#[inline]
pub(crate) fn counter_start(
counter_idx_base: usize,
counter_idx_mask: usize,
start_flags: usize,
initial_value: u64,
) -> SbiRet {
if let Some(obj) = PMU.get() {
return obj.counter_start(
counter_idx_base,
counter_idx_mask,
start_flags,
initial_value,
);
}
SbiRet::not_supported()
}
#[cfg(feature = "singleton")]
#[inline]
pub(crate) fn counter_stop(
counter_idx_base: usize,
counter_idx_mask: usize,
stop_flags: usize,
) -> SbiRet {
if let Some(obj) = PMU.get() {
return obj.counter_stop(counter_idx_base, counter_idx_mask, stop_flags);
}
SbiRet::not_supported()
}
#[cfg(feature = "singleton")]
#[inline]
pub(crate) fn counter_fw_read(counter_idx: usize) -> SbiRet {
if let Some(obj) = PMU.get() {
return obj.counter_fw_read(counter_idx);
}
SbiRet::not_supported()
}