123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394 |
- #[cfg(feature = "machine")]
- use riscv::register::{marchid, mimpid, mvendorid};
- use spec::binary::{HartMask, Physical, SbiRet, SharedPtr};
- /// RustSBI environment call handler.
- pub trait RustSBI {
- /// Handle supervisor environment call with given parameters and return the `SbiRet` result.
- fn handle_ecall(&self, extension: usize, function: usize, param: [usize; 6]) -> SbiRet;
- }
- impl<T: RustSBI> RustSBI for &T {
- #[inline(always)]
- fn handle_ecall(&self, extension: usize, function: usize, param: [usize; 6]) -> SbiRet {
- <T as RustSBI>::handle_ecall(self, extension, function, param)
- }
- }
- /// Machine environment information.
- ///
- /// This trait is useful to build an SBI environment when RustSBI is not run directly on RISC-V machine mode.
- pub trait EnvInfo {
- /// Vendor ID for the supervisor environment.
- ///
- /// Provides JEDEC manufacturer ID of the provider of the core.
- fn mvendorid(&self) -> usize;
- /// Architecture ID for the supervisor environment.
- ///
- /// Encodes the base micro-architecture of the hart.
- fn marchid(&self) -> usize;
- /// Implementation ID for the supervisor environment.
- ///
- /// Provides a unique encoding of the version of the processor implementation.
- fn mimpid(&self) -> usize;
- }
- impl<T: EnvInfo> EnvInfo for &T {
- #[inline(always)]
- fn mvendorid(&self) -> usize {
- <T as EnvInfo>::mvendorid(self)
- }
- #[inline(always)]
- fn marchid(&self) -> usize {
- <T as EnvInfo>::marchid(self)
- }
- #[inline(always)]
- fn mimpid(&self) -> usize {
- <T as EnvInfo>::mimpid(self)
- }
- }
- // Macro internal structures and functions.
- // DO NOT USE code here directly; use derive macro #[derive(RustSBI)] instead.
- #[cfg(feature = "machine")]
- #[doc(hidden)]
- #[inline(always)]
- pub fn _rustsbi_base_bare<U: _ExtensionProbe>(
- param: [usize; 6],
- function: usize,
- probe: U,
- ) -> SbiRet {
- let [param0] = [param[0]];
- let value = match function {
- spec::base::GET_SBI_SPEC_VERSION => (crate::SBI_SPEC_MAJOR << 24) | (crate::SBI_SPEC_MINOR),
- spec::base::GET_SBI_IMPL_ID => crate::IMPL_ID_RUSTSBI,
- spec::base::GET_SBI_IMPL_VERSION => crate::RUSTSBI_VERSION,
- spec::base::PROBE_EXTENSION => probe.probe_extension(param0),
- spec::base::GET_MVENDORID => mvendorid::read().map(|r| r.bits()).unwrap_or(0),
- spec::base::GET_MARCHID => marchid::read().map(|r| r.bits()).unwrap_or(0),
- spec::base::GET_MIMPID => mimpid::read().map(|r| r.bits()).unwrap_or(0),
- _ => return SbiRet::not_supported(),
- };
- SbiRet::success(value)
- }
- #[doc(hidden)]
- #[inline(always)]
- pub fn _rustsbi_base_env_info<T: EnvInfo, U: _ExtensionProbe>(
- param: [usize; 6],
- function: usize,
- env_info: &T,
- probe: U,
- ) -> SbiRet {
- let [param0] = [param[0]];
- let value = match function {
- spec::base::GET_SBI_SPEC_VERSION => (crate::SBI_SPEC_MAJOR << 24) | (crate::SBI_SPEC_MINOR),
- spec::base::GET_SBI_IMPL_ID => crate::IMPL_ID_RUSTSBI,
- spec::base::GET_SBI_IMPL_VERSION => crate::RUSTSBI_VERSION,
- spec::base::PROBE_EXTENSION => probe.probe_extension(param0),
- spec::base::GET_MVENDORID => env_info.mvendorid(),
- spec::base::GET_MARCHID => env_info.marchid(),
- spec::base::GET_MIMPID => env_info.mimpid(),
- _ => return SbiRet::not_supported(),
- };
- SbiRet::success(value)
- }
- // Probe not only standard SBI extensions, but also (reserving for) custom extensions.
- // For standard SBI extensions only, the macro would use `_StandardExtensionProbe`;
- // for implementation with custom SBI extension, a custom structure implementing this trait
- // would be used by macro.
- pub trait _ExtensionProbe {
- // Implementors are encouraged to add #[inline] hints on this function.
- fn probe_extension(&self, extension: usize) -> usize;
- }
- #[doc(hidden)]
- pub struct _StandardExtensionProbe {
- pub base: usize,
- pub fence: usize,
- pub timer: usize,
- pub ipi: usize,
- pub hsm: usize,
- pub reset: usize,
- pub pmu: usize,
- pub console: usize,
- pub susp: usize,
- pub cppc: usize,
- pub nacl: usize,
- pub sta: usize,
- // NOTE: don't forget to add to `fn probe_extension` in `impl _ExtensionProbe` as well
- }
- impl _ExtensionProbe for _StandardExtensionProbe {
- #[inline(always)]
- fn probe_extension(&self, extension: usize) -> usize {
- match extension {
- spec::base::EID_BASE => self.base,
- spec::time::EID_TIME => self.timer,
- spec::spi::EID_SPI => self.ipi,
- spec::rfnc::EID_RFNC => self.fence,
- spec::srst::EID_SRST => self.reset,
- spec::hsm::EID_HSM => self.hsm,
- spec::pmu::EID_PMU => self.pmu,
- spec::dbcn::EID_DBCN => self.console,
- spec::susp::EID_SUSP => self.susp,
- spec::cppc::EID_CPPC => self.cppc,
- spec::nacl::EID_NACL => self.nacl,
- spec::sta::EID_STA => self.sta,
- _ => spec::base::UNAVAILABLE_EXTENSION,
- }
- }
- }
- #[doc(hidden)]
- #[inline(always)]
- pub fn _rustsbi_fence<T: crate::Fence>(fence: &T, param: [usize; 6], function: usize) -> SbiRet {
- let [param0, param1, param2, param3, param4] =
- [param[0], param[1], param[2], param[3], param[4]];
- let hart_mask = HartMask::from_mask_base(param0, param1);
- match function {
- spec::rfnc::REMOTE_FENCE_I => fence.remote_fence_i(hart_mask),
- spec::rfnc::REMOTE_SFENCE_VMA => fence.remote_sfence_vma(hart_mask, param2, param3),
- spec::rfnc::REMOTE_SFENCE_VMA_ASID => {
- fence.remote_sfence_vma_asid(hart_mask, param2, param3, param4)
- }
- spec::rfnc::REMOTE_HFENCE_GVMA_VMID => {
- fence.remote_hfence_gvma_vmid(hart_mask, param2, param3, param4)
- }
- spec::rfnc::REMOTE_HFENCE_GVMA => fence.remote_hfence_gvma(hart_mask, param2, param3),
- spec::rfnc::REMOTE_HFENCE_VVMA_ASID => {
- fence.remote_hfence_vvma_asid(hart_mask, param2, param3, param4)
- }
- spec::rfnc::REMOTE_HFENCE_VVMA => fence.remote_hfence_vvma(hart_mask, param2, param3),
- _ => SbiRet::not_supported(),
- }
- }
- #[doc(hidden)]
- #[inline(always)]
- pub fn _rustsbi_timer<T: crate::Timer>(timer: &T, param: [usize; 6], function: usize) -> SbiRet {
- match () {
- #[cfg(target_pointer_width = "64")]
- () => {
- let [param0] = [param[0]];
- match function {
- spec::time::SET_TIMER => {
- timer.set_timer(param0 as _);
- SbiRet::success(0)
- }
- _ => SbiRet::not_supported(),
- }
- }
- #[cfg(target_pointer_width = "32")]
- () => {
- let [param0, param1] = [param[0], param[1]];
- match function {
- spec::time::SET_TIMER => {
- timer.set_timer(concat_u32(param1, param0));
- SbiRet::success(0)
- }
- _ => SbiRet::not_supported(),
- }
- }
- }
- }
- #[doc(hidden)]
- #[inline(always)]
- pub fn _rustsbi_ipi<T: crate::Ipi>(ipi: &T, param: [usize; 6], function: usize) -> SbiRet {
- let [param0, param1] = [param[0], param[1]];
- match function {
- spec::spi::SEND_IPI => ipi.send_ipi(HartMask::from_mask_base(param0, param1)),
- _ => SbiRet::not_supported(),
- }
- }
- #[doc(hidden)]
- #[inline(always)]
- pub fn _rustsbi_hsm<T: crate::Hsm>(hsm: &T, param: [usize; 6], function: usize) -> SbiRet {
- let [param0, param1, param2] = [param[0], param[1], param[2]];
- match function {
- spec::hsm::HART_START => hsm.hart_start(param0, param1, param2),
- spec::hsm::HART_STOP => hsm.hart_stop(),
- spec::hsm::HART_GET_STATUS => hsm.hart_get_status(param0),
- spec::hsm::HART_SUSPEND => {
- if let Ok(suspend_type) = u32::try_from(param0) {
- hsm.hart_suspend(suspend_type, param1, param2)
- } else {
- SbiRet::invalid_param()
- }
- }
- _ => SbiRet::not_supported(),
- }
- }
- #[doc(hidden)]
- #[inline(always)]
- pub fn _rustsbi_reset<T: crate::Reset>(reset: &T, param: [usize; 6], function: usize) -> SbiRet {
- let [param0, param1] = [param[0], param[1]];
- match function {
- spec::srst::SYSTEM_RESET => match (u32::try_from(param0), u32::try_from(param1)) {
- (Ok(reset_type), Ok(reset_reason)) => reset.system_reset(reset_type, reset_reason),
- (_, _) => SbiRet::invalid_param(),
- },
- _ => SbiRet::not_supported(),
- }
- }
- #[doc(hidden)]
- #[inline(always)]
- pub fn _rustsbi_pmu<T: crate::Pmu>(pmu: &T, param: [usize; 6], function: usize) -> SbiRet {
- match () {
- #[cfg(target_pointer_width = "64")]
- () => {
- let [param0, param1, param2, param3, param4] =
- [param[0], param[1], param[2], param[3], param[4]];
- match function {
- spec::pmu::NUM_COUNTERS => SbiRet::success(pmu.num_counters()),
- spec::pmu::COUNTER_GET_INFO => pmu.counter_get_info(param0),
- spec::pmu::COUNTER_CONFIG_MATCHING => {
- pmu.counter_config_matching(param0, param1, param2, param3, param4 as _)
- }
- spec::pmu::COUNTER_START => pmu.counter_start(param0, param1, param2, param3 as _),
- spec::pmu::COUNTER_STOP => pmu.counter_stop(param0, param1, param2),
- spec::pmu::COUNTER_FW_READ => pmu.counter_fw_read(param0),
- spec::pmu::COUNTER_FW_READ_HI => pmu.counter_fw_read_hi(param0),
- _ => SbiRet::not_supported(),
- }
- }
- #[cfg(target_pointer_width = "32")]
- () => {
- let [param0, param1, param2, param3, param4, param5] =
- [param[0], param[1], param[2], param[3], param[4], param[5]];
- match function {
- spec::pmu::NUM_COUNTERS => SbiRet::success(pmu.num_counters()),
- spec::pmu::COUNTER_GET_INFO => pmu.counter_get_info(param0),
- spec::pmu::COUNTER_CONFIG_MATCHING => pmu.counter_config_matching(
- param0,
- param1,
- param2,
- param3,
- concat_u32(param5, param4),
- ),
- spec::pmu::COUNTER_START => {
- pmu.counter_start(param0, param1, param2, concat_u32(param4, param3))
- }
- spec::pmu::COUNTER_STOP => pmu.counter_stop(param0, param1, param2),
- spec::pmu::COUNTER_FW_READ => pmu.counter_fw_read(param0),
- spec::pmu::COUNTER_FW_READ_HI => pmu.counter_fw_read_hi(param0),
- _ => SbiRet::not_supported(),
- }
- }
- }
- }
- #[doc(hidden)]
- #[inline(always)]
- pub fn _rustsbi_console<T: crate::Console>(
- console: &T,
- param: [usize; 6],
- function: usize,
- ) -> SbiRet {
- let [param0, param1, param2] = [param[0], param[1], param[2]];
- match function {
- spec::dbcn::CONSOLE_WRITE => {
- let bytes = Physical::new(param0, param1, param2);
- console.write(bytes)
- }
- spec::dbcn::CONSOLE_READ => {
- let bytes = Physical::new(param0, param1, param2);
- console.read(bytes)
- }
- spec::dbcn::CONSOLE_WRITE_BYTE => console.write_byte((param0 & 0xFF) as u8),
- _ => SbiRet::not_supported(),
- }
- }
- #[doc(hidden)]
- #[inline(always)]
- pub fn _rustsbi_susp<T: crate::Susp>(susp: &T, param: [usize; 6], function: usize) -> SbiRet {
- let [param0, param1, param2] = [param[0], param[1], param[2]];
- match function {
- spec::susp::SUSPEND => match u32::try_from(param0) {
- Ok(sleep_type) => susp.system_suspend(sleep_type, param1, param2),
- _ => SbiRet::invalid_param(),
- },
- _ => SbiRet::not_supported(),
- }
- }
- #[doc(hidden)]
- #[inline(always)]
- pub fn _rustsbi_cppc<T: crate::Cppc>(cppc: &T, param: [usize; 6], function: usize) -> SbiRet {
- match () {
- #[cfg(target_pointer_width = "64")]
- () => {
- let [param0, param1] = [param[0], param[1]];
- match function {
- spec::cppc::PROBE => match u32::try_from(param0) {
- Ok(reg_id) => cppc.probe(reg_id),
- _ => SbiRet::invalid_param(),
- },
- spec::cppc::READ => match u32::try_from(param0) {
- Ok(reg_id) => cppc.read(reg_id),
- _ => SbiRet::invalid_param(),
- },
- spec::cppc::READ_HI => match u32::try_from(param0) {
- Ok(reg_id) => cppc.read_hi(reg_id),
- _ => SbiRet::invalid_param(),
- },
- spec::cppc::WRITE => match u32::try_from(param0) {
- Ok(reg_id) => cppc.write(reg_id, param1 as _),
- _ => SbiRet::invalid_param(),
- },
- _ => SbiRet::not_supported(),
- }
- }
- #[cfg(target_pointer_width = "32")]
- () => {
- let [param0, param1, param2] = [param[0], param[1], param[2]];
- match function {
- spec::cppc::PROBE => cppc.probe(param0 as _),
- spec::cppc::READ => cppc.read(param0 as _),
- spec::cppc::READ_HI => cppc.read_hi(param0 as _),
- spec::cppc::WRITE => cppc.write(param0 as _, concat_u32(param2, param1)),
- _ => SbiRet::not_supported(),
- }
- }
- }
- }
- #[doc(hidden)]
- #[inline(always)]
- pub fn _rustsbi_nacl<T: crate::Nacl>(nacl: &T, param: [usize; 6], function: usize) -> SbiRet {
- let [param0, param1, param2] = [param[0], param[1], param[2]];
- match function {
- spec::nacl::PROBE_FEATURE => match u32::try_from(param0) {
- Ok(feature_id) => nacl.probe_feature(feature_id),
- _ => SbiRet::invalid_param(),
- },
- spec::nacl::SET_SHMEM => nacl.set_shmem(SharedPtr::new(param0, param1), param2),
- spec::nacl::SYNC_CSR => nacl.sync_csr(param0),
- spec::nacl::SYNC_HFENCE => nacl.sync_hfence(param0),
- spec::nacl::SYNC_SRET => nacl.sync_sret(),
- _ => SbiRet::not_supported(),
- }
- }
- #[doc(hidden)]
- #[inline(always)]
- pub fn _rustsbi_sta<T: crate::Sta>(sta: &T, param: [usize; 6], function: usize) -> SbiRet {
- let [param0, param1, param2] = [param[0], param[1], param[2]];
- match function {
- spec::sta::SET_SHMEM => sta.set_shmem(SharedPtr::new(param0, param1), param2),
- _ => SbiRet::not_supported(),
- }
- }
- #[cfg(target_pointer_width = "32")]
- #[inline]
- const fn concat_u32(h: usize, l: usize) -> u64 {
- ((h as u64) << 32) | (l as u64)
- }
|