Browse Source

lib: remove singleton based interface

use `RustSBI` structure instead
luojia65 2 years ago
parent
commit
bf629df334
21 changed files with 5 additions and 821 deletions
  1. 0 5
      .github/workflows/rust.yml
  2. 1 0
      CHANGELOG.md
  3. 0 5
      Cargo.toml
  4. 0 3
      README.md
  5. 0 15
      src/base.rs
  6. 0 27
      src/ecall/base.rs
  7. 0 20
      src/ecall/hsm.rs
  8. 0 83
      src/ecall/mod.rs
  9. 0 55
      src/ecall/pmu.rs
  10. 0 25
      src/ecall/rfnc.rs
  11. 0 12
      src/ecall/spi.rs
  12. 0 14
      src/ecall/srst.rs
  13. 0 36
      src/ecall/time.rs
  14. 0 56
      src/hsm.rs
  15. 0 29
      src/ipi.rs
  16. 2 35
      src/lib.rs
  17. 2 113
      src/pmu.rs
  18. 0 29
      src/reset.rs
  19. 0 105
      src/rfence.rs
  20. 0 31
      src/timer.rs
  21. 0 123
      src/util.rs

+ 0 - 5
.github/workflows/rust.yml

@@ -79,11 +79,6 @@ jobs:
         uses: Swatinem/rust-cache@v2
         with:
           key: ${{ matrix.TARGET }}
-      - name: Check (singleton)
-        uses: actions-rs/cargo@v1
-        with:
-          command: check
-          args: --features "singleton" --target ${{ matrix.TARGET }} --verbose
 
   tests:
     name: Run tests

+ 1 - 0
CHANGELOG.md

@@ -15,6 +15,7 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
 
 - `sbi_2_0` feature; RustSBI now supports SBI 2.0-rc1 by default
 - support for legacy SBI extensions
+- singleton based RustSBI interface; use struct `RustSBI` instead
 
 ## [0.3.2] - 2023-02-26
 

+ 0 - 5
Cargo.toml

@@ -26,11 +26,6 @@ default = ["machine"]
 # If you are developing a cross-architecture virtual machine, consider disabling this feature
 # to customize environment variables for RISC-V architecture like mvendorid, mimpid, etc.
 machine = ["dep:riscv"]
-# Build RustSBI singleton
-# This would enable `init_*` functions. It will take extra place on bss or data region
-# to take care of singleton reference locks.
-# Disable this feature to use instance based RustSBI environment.
-singleton = ["dep:riscv", "machine"]
 
 [package.metadata.docs.rs]
 default-target = "riscv64imac-unknown-none-elf"

+ 0 - 3
README.md

@@ -22,9 +22,6 @@ or consult vendors if they provide discrete RustSBI package support.
 
 To compile RustSBI library, you need at least stable Rust version of `rustc 1.65.0`.
 
-If you are using feature `singleton` to support singleton based interface, you are required to install
-nightly Rust compiler. You may need at least nightly Rust version of `rustc 1.59.0-nightly (c5ecc1570 2021-12-15)`.
-
 ## Build this project
 
 RustSBI is usually used as a library or dependency. If you wish to, you may build RustSBI library itself using the

+ 0 - 15
src/base.rs

@@ -1,15 +0,0 @@
-#[cfg(feature = "singleton")]
-#[inline]
-pub fn probe_extension(extension: usize) -> bool {
-    use sbi_spec::*;
-    match extension {
-        base::EID_BASE => true,
-        time::EID_TIME => crate::timer::probe_timer(),
-        spi::EID_SPI => crate::ipi::probe_ipi(),
-        rfnc::EID_RFNC => crate::rfence::probe_rfence(),
-        srst::EID_SRST => crate::reset::probe_reset(),
-        hsm::EID_HSM => crate::hsm::probe_hsm(),
-        pmu::EID_PMU => crate::pmu::probe_pmu(),
-        _ => false,
-    }
-}

+ 0 - 27
src/ecall/base.rs

@@ -1,27 +0,0 @@
-use sbi_spec::binary::SbiRet;
-
-#[inline]
-pub(super) fn handle_ecall(function: usize, param0: usize) -> SbiRet {
-    use crate::base::*;
-    use crate::{IMPL_ID_RUSTSBI, RUSTSBI_VERSION, SBI_SPEC_MAJOR, SBI_SPEC_MINOR};
-    use riscv::register::{marchid, mimpid, mvendorid};
-    use sbi_spec::base::*;
-
-    let value = match function {
-        GET_SBI_SPEC_VERSION => (SBI_SPEC_MAJOR << 24) | (SBI_SPEC_MINOR),
-        GET_SBI_IMPL_ID => IMPL_ID_RUSTSBI,
-        GET_SBI_IMPL_VERSION => RUSTSBI_VERSION,
-        PROBE_EXTENSION => {
-            if probe_extension(param0) {
-                UNAVAILABLE_EXTENSION.wrapping_add(1)
-            } else {
-                UNAVAILABLE_EXTENSION
-            }
-        }
-        GET_MVENDORID => mvendorid::read().map(|r| r.bits()).unwrap_or(0),
-        GET_MARCHID => marchid::read().map(|r| r.bits()).unwrap_or(0),
-        GET_MIMPID => mimpid::read().map(|r| r.bits()).unwrap_or(0),
-        _ => return SbiRet::not_supported(),
-    };
-    SbiRet::success(value)
-}

+ 0 - 20
src/ecall/hsm.rs

@@ -1,20 +0,0 @@
-use sbi_spec::binary::SbiRet;
-
-#[inline]
-pub(super) fn handle_ecall(function: usize, param0: usize, param1: usize, param2: usize) -> SbiRet {
-    use crate::hsm::*;
-    use sbi_spec::hsm::*;
-    match function {
-        HART_START => hart_start(param0, param1, param2),
-        HART_STOP => hart_stop(),
-        HART_GET_STATUS => hart_get_status(param0),
-        HART_SUSPEND => {
-            if let Ok(suspend_type) = u32::try_from(param0) {
-                hart_suspend(suspend_type, param1, param2)
-            } else {
-                SbiRet::invalid_param()
-            }
-        }
-        _ => SbiRet::not_supported(),
-    }
-}

+ 0 - 83
src/ecall/mod.rs

@@ -1,83 +0,0 @@
-//! 这个模块将会处理所有的 SBI 调用陷入,你应该在中断处理函数里调用 `handle_ecall`
-
-// §4
-mod base;
-// §6
-mod time;
-// §7
-mod spi;
-// §8
-mod rfnc;
-// §9
-mod hsm;
-// §10
-mod srst;
-// §11
-mod pmu;
-
-use sbi_spec::{self as spec, binary::SbiRet};
-
-/// Supervisor environment call handler function
-///
-/// This function is used by platform runtime to handle environment call `ecall` instruction.
-///
-/// You should call this function in your runtime's exception handler.
-/// If the incoming exception is caused by supervisor `ecall`,
-/// call this function with parameters extracted from trap frame.
-/// After this function returns, store the return value into `a0` and `a1` parameters.
-///
-/// # Example
-///
-/// A typical usage:
-///
-/// ```no_run
-/// # use riscv::register::{mepc, mcause::{self, Trap, Exception}};
-/// # struct TrapFrame { a0: usize, a1: usize, a2: usize, a3: usize,
-/// # a4: usize, a5: usize, a6: usize, a7: usize }
-/// extern "C" fn rust_handle_exception(ctx: &mut TrapFrame) {
-///     if mcause::read().cause() == Trap::Exception(Exception::SupervisorEnvCall) {
-///         let params = [ctx.a0, ctx.a1, ctx.a2, ctx.a3, ctx.a4, ctx.a5];
-///         let ans = rustsbi::ecall(ctx.a7, ctx.a6, params);
-///         ctx.a0 = ans.error;
-///         ctx.a1 = ans.value;
-///         mepc::write(mepc::read().wrapping_add(4));
-///     }
-///     // other conditions..
-/// }
-/// ```
-///
-/// Do not forget to advance `mepc` by 4 after an ecall is handled.
-/// This skips the `ecall` instruction itself which is 4-byte long in all conditions.
-#[inline]
-pub fn handle_ecall(extension: usize, function: usize, param: [usize; 6]) -> SbiRet {
-    match extension {
-        spec::rfnc::EID_RFNC => {
-            rfnc::handle_ecall(function, param[0], param[1], param[2], param[3], param[4])
-        }
-        spec::time::EID_TIME => match () {
-            #[cfg(target_pointer_width = "64")]
-            () => time::handle_ecall(function, param[0]),
-            #[cfg(target_pointer_width = "32")]
-            () => time::handle_ecall(function, param[0], param[1]),
-        },
-        spec::spi::EID_SPI => spi::handle_ecall(function, param[0], param[1]),
-        spec::base::EID_BASE => base::handle_ecall(function, param[0]),
-        spec::hsm::EID_HSM => hsm::handle_ecall(function, param[0], param[1], param[2]),
-        spec::srst::EID_SRST => srst::handle_ecall(function, param[0], param[1]),
-        spec::pmu::EID_PMU => match () {
-            #[cfg(target_pointer_width = "64")]
-            () => pmu::handle_ecall(function, param[0], param[1], param[2], param[3], param[4]),
-            #[cfg(target_pointer_width = "32")]
-            () => pmu::handle_ecall(
-                function, param[0], param[1], param[2], param[3], param[4], param[5],
-            ),
-        },
-        _ => 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)
-}

+ 0 - 55
src/ecall/pmu.rs

@@ -1,55 +0,0 @@
-use sbi_spec::binary::SbiRet;
-
-#[cfg(target_pointer_width = "64")]
-#[inline]
-pub fn handle_ecall(
-    function: usize,
-    param0: usize,
-    param1: usize,
-    param2: usize,
-    param3: usize,
-    param4: usize,
-) -> SbiRet {
-    use crate::pmu::*;
-    use sbi_spec::pmu::*;
-    match function {
-        PMU_NUM_COUNTERS => num_counters(),
-        PMU_COUNTER_GET_INFO => counter_get_info(param0),
-        PMU_COUNTER_CONFIG_MATCHING => {
-            counter_config_matching(param0, param1, param2, param3, param4 as _)
-        }
-        PMU_COUNTER_START => counter_start(param0, param1, param2, param3 as _),
-        PMU_COUNTER_STOP => counter_stop(param0, param1, param2),
-        PMU_COUNTER_FW_READ => counter_fw_read(param0),
-        PMU_COUNTER_FW_READ_HI => counter_fw_read_hi(param0),
-        _ => SbiRet::not_supported(),
-    }
-}
-
-#[cfg(target_pointer_width = "32")]
-#[inline]
-pub fn handle_ecall(
-    function: usize,
-    param0: usize,
-    param1: usize,
-    param2: usize,
-    param3: usize,
-    param4: usize,
-    param5: usize,
-) -> SbiRet {
-    use super::concat_u32;
-    use crate::pmu::*;
-    use sbi_spec::pmu::*;
-    match function {
-        PMU_NUM_COUNTERS => num_counters(),
-        PMU_COUNTER_GET_INFO => counter_get_info(param0),
-        PMU_COUNTER_CONFIG_MATCHING => {
-            counter_config_matching(param0, param1, param2, param3, concat_u32(param5, param4))
-        }
-        PMU_COUNTER_START => counter_start(param0, param1, param2, concat_u32(param4, param3)),
-        PMU_COUNTER_STOP => counter_stop(param0, param1, param2),
-        PMU_COUNTER_FW_READ => counter_fw_read(param0),
-        PMU_COUNTER_FW_READ_HI => counter_fw_read_hi(param0),
-        _ => SbiRet::not_supported(),
-    }
-}

+ 0 - 25
src/ecall/rfnc.rs

@@ -1,25 +0,0 @@
-use sbi_spec::binary::SbiRet;
-
-#[inline]
-pub fn handle_ecall(
-    function: usize,
-    param0: usize,
-    param1: usize,
-    param2: usize,
-    param3: usize,
-    param4: usize,
-) -> SbiRet {
-    use crate::rfence::*;
-    use sbi_spec::rfnc::*;
-    let hart_mask = crate::HartMask::from_mask_base(param0, param1);
-    match function {
-        REMOTE_FENCE_I => remote_fence_i(hart_mask),
-        REMOTE_SFENCE_VMA => remote_sfence_vma(hart_mask, param2, param3),
-        REMOTE_SFENCE_VMA_ASID => remote_sfence_vma_asid(hart_mask, param2, param3, param4),
-        REMOTE_HFENCE_GVMA_VMID => remote_hfence_gvma_vmid(hart_mask, param2, param3, param4),
-        REMOTE_HFENCE_GVMA => remote_hfence_gvma(hart_mask, param2, param3),
-        REMOTE_HFENCE_VVMA_ASID => remote_hfence_vvma_asid(hart_mask, param2, param3, param4),
-        REMOTE_HFENCE_VVMA => remote_hfence_vvma(hart_mask, param2, param3),
-        _ => SbiRet::not_supported(),
-    }
-}

+ 0 - 12
src/ecall/spi.rs

@@ -1,12 +0,0 @@
-use sbi_spec::binary::SbiRet;
-
-#[inline]
-pub(super) fn handle_ecall(function: usize, param0: usize, param1: usize) -> SbiRet {
-    use crate::hart_mask::HartMask;
-    use crate::ipi::*;
-    use sbi_spec::spi::*;
-    match function {
-        SEND_IPI => send_ipi(HartMask::from_mask_base(param0, param1)),
-        _ => SbiRet::not_supported(),
-    }
-}

+ 0 - 14
src/ecall/srst.rs

@@ -1,14 +0,0 @@
-use sbi_spec::binary::SbiRet;
-
-#[inline]
-pub(super) fn handle_ecall(function: usize, param0: usize, param1: usize) -> SbiRet {
-    use crate::reset::*;
-    use sbi_spec::srst::*;
-    match function {
-        SYSTEM_RESET => match (u32::try_from(param0), u32::try_from(param1)) {
-            (Ok(reset_type), Ok(reset_reason)) => system_reset(reset_type, reset_reason),
-            (_, _) => SbiRet::invalid_param(),
-        },
-        _ => SbiRet::not_supported(),
-    }
-}

+ 0 - 36
src/ecall/time.rs

@@ -1,36 +0,0 @@
-use sbi_spec::binary::SbiRet;
-
-#[cfg(target_pointer_width = "64")]
-#[inline]
-pub(super) fn handle_ecall(function: usize, param0: usize) -> SbiRet {
-    use crate::timer::*;
-    use sbi_spec::time::*;
-    match function {
-        SET_TIMER => {
-            if set_timer(param0 as _) {
-                SbiRet::success(0)
-            } else {
-                SbiRet::not_supported()
-            }
-        }
-        _ => SbiRet::not_supported(),
-    }
-}
-
-#[cfg(target_pointer_width = "32")]
-#[inline]
-pub(super) fn handle_ecall(function: usize, param0: usize, param1: usize) -> SbiRet {
-    use super::concat_u32;
-    use crate::timer::*;
-    use sbi_spec::time::*;
-    match function {
-        SET_TIMER => {
-            if set_timer(concat_u32(param1, param0)) {
-                SbiRet::success(0)
-            } else {
-                SbiRet::not_supported()
-            }
-        }
-        _ => SbiRet::not_supported(),
-    }
-}

+ 0 - 56
src/hsm.rs

@@ -216,59 +216,3 @@ impl<T: Hsm> Hsm for &T {
         T::hart_suspend(self, suspend_type, resume_addr, opaque)
     }
 }
-
-#[cfg(feature = "singleton")]
-use crate::util::AmoOnceRef;
-
-#[cfg(feature = "singleton")]
-static HSM: AmoOnceRef<dyn Hsm> = AmoOnceRef::new();
-
-#[cfg(feature = "singleton")]
-/// Init HSM module
-pub fn init_hsm(hsm: &'static dyn Hsm) {
-    if !HSM.try_call_once(hsm) {
-        panic!("load sbi module when already loaded")
-    }
-}
-
-#[cfg(feature = "singleton")]
-#[inline]
-pub(crate) fn probe_hsm() -> bool {
-    HSM.get().is_some()
-}
-
-#[cfg(feature = "singleton")]
-#[inline]
-pub(crate) fn hart_start(hartid: usize, start_addr: usize, opaque: usize) -> SbiRet {
-    if let Some(obj) = HSM.get() {
-        return obj.hart_start(hartid, start_addr, opaque);
-    }
-    SbiRet::not_supported()
-}
-
-#[cfg(feature = "singleton")]
-#[inline]
-pub(crate) fn hart_stop() -> SbiRet {
-    if let Some(obj) = HSM.get() {
-        return obj.hart_stop();
-    }
-    SbiRet::not_supported()
-}
-
-#[cfg(feature = "singleton")]
-#[inline]
-pub(crate) fn hart_get_status(hartid: usize) -> SbiRet {
-    if let Some(obj) = HSM.get() {
-        return obj.hart_get_status(hartid);
-    }
-    SbiRet::not_supported()
-}
-
-#[cfg(feature = "singleton")]
-#[inline]
-pub(crate) fn hart_suspend(suspend_type: u32, resume_addr: usize, opaque: usize) -> SbiRet {
-    if let Some(obj) = HSM.get() {
-        return obj.hart_suspend(suspend_type, resume_addr, opaque);
-    }
-    SbiRet::not_supported()
-}

+ 0 - 29
src/ipi.rs

@@ -1,9 +1,6 @@
 use crate::hart_mask::HartMask;
 use sbi_spec::binary::SbiRet;
 
-#[cfg(feature = "singleton")]
-use crate::util::AmoOnceRef;
-
 /// Inter-processor interrupt support
 pub trait Ipi: Send + Sync {
     /// Send an inter-processor interrupt to all the harts defined in `hart_mask`.
@@ -22,29 +19,3 @@ impl<T: Ipi> Ipi for &T {
         T::send_ipi(self, hart_mask)
     }
 }
-
-#[cfg(feature = "singleton")]
-static IPI: AmoOnceRef<dyn Ipi> = AmoOnceRef::new();
-
-/// Init singleton IPI module
-#[cfg(feature = "singleton")]
-pub fn init_ipi(ipi: &'static dyn Ipi) {
-    if !IPI.try_call_once(ipi) {
-        panic!("load sbi module when already loaded")
-    }
-}
-
-#[cfg(feature = "singleton")]
-#[inline]
-pub(crate) fn probe_ipi() -> bool {
-    IPI.get().is_some()
-}
-
-#[cfg(feature = "singleton")]
-#[inline]
-pub(crate) fn send_ipi(hart_mask: HartMask) -> SbiRet {
-    if let Some(ipi) = IPI.get() {
-        return ipi.send_ipi(hart_mask);
-    }
-    SbiRet::not_supported()
-}

+ 2 - 35
src/lib.rs

@@ -162,6 +162,7 @@
 //! # struct MyPlatHsm;
 //! # struct MyBoardPower;
 //! # struct MyPlatPmu;
+//! # struct MyPlatDbcn;
 //! use rustsbi::RustSBI;
 //!
 //! # struct SupervisorContext;
@@ -169,7 +170,7 @@
 //! struct Executor {
 //!     ctx: SupervisorContext,
 //!     /* other environment variables ... */
-//!     sbi: RustSBI<Clint, Clint, MyPlatRfnc, MyPlatHsm, MyBoardPower, MyPlatPmu>,
+//!     sbi: RustSBI<Clint, Clint, MyPlatRfnc, MyPlatHsm, MyBoardPower, MyPlatPmu, MyPlatDbcn>,
 //!     /* custom_1: CustomSBI<...> */
 //! }
 //!
@@ -342,26 +343,6 @@
 //! train memory for later stages. In such situation, RustSBI implementation should be linked or concated
 //! to the second stage bootloader, and the first stage could be a standalone binary package bundled with it.
 //!
-//! ## Discrete RustSBI package by singleton based interface
-//!
-//! *Note: Using singleton based RustSBI interface is discouraged in newer designs, for it requires
-//! nightly Rust and global static memory. It takes extra bss and data storage to build a global singleton
-//! interface. New designs should follow the [instance based interface](#discrete-rustsbi-package-on-bare-metal-risc-v-hardware)
-//! to build discrete RustSBI packages.*
-//!
-//! Other than instance based interface, some users may find it convenient by using
-//! global singleton semantics. To use it users should enable the `singleton` feature by:
-//!
-//! ```toml
-//! [dependencies]
-//! rustsbi = { version = "0.4.0", features = ["singleton"] }
-//! ```
-//!
-//! RustSBI library will disable all instance based interfaces but provide `init_*`
-//! functions to allow initialize global RustSBI singleton instance.
-//! By enabling this feature, RustSBI uses unstable Rust features to create a universal
-//! lock structure by using atomic `amo` instructions other than `lr`/`sc`.
-//!
 //! # Hypervisor and emulator development with RustSBI
 //!
 //! RustSBI crate supports to develop RISC-V emulators, and both Type-1 and Type-2 hypervisors.
@@ -516,12 +497,8 @@
 //! system calls or use the signal trap method to detect any RISC-V core features.
 
 #![no_std]
-#![cfg_attr(feature = "singleton", feature(ptr_metadata))]
 
-mod base;
 mod console;
-#[cfg(feature = "singleton")]
-mod ecall;
 mod hart_mask;
 mod hsm;
 mod instance;
@@ -531,8 +508,6 @@ mod pmu;
 mod reset;
 mod rfence;
 mod timer;
-#[cfg(feature = "singleton")]
-mod util;
 
 /// The RustSBI logo without blank lines on the beginning
 pub const LOGO: &str = r".______       __    __      _______.___________.  _______..______   __
@@ -562,8 +537,6 @@ pub const VERSION: &str = env!("CARGO_PKG_VERSION");
 
 pub extern crate sbi_spec as spec;
 pub use console::Console;
-#[cfg(feature = "singleton")]
-pub use ecall::handle_ecall as ecall;
 pub use hart_mask::HartMask;
 pub use hsm::Hsm;
 pub use instance::{Builder, RustSBI};
@@ -576,9 +549,3 @@ pub use timer::Timer;
 
 #[cfg(not(feature = "machine"))]
 pub use instance::MachineInfo;
-
-#[cfg(feature = "singleton")]
-pub use {
-    hsm::init_hsm, ipi::init_ipi, pmu::init_pmu, reset::init_reset,
-    rfence::init_rfence as init_remote_fence, timer::init_timer,
-};

+ 2 - 113
src/pmu.rs

@@ -213,12 +213,12 @@ pub trait Pmu: Send + Sync {
         match () {
             #[cfg(not(target_pointer_width = "32"))]
             () => {
-                drop(counter_idx);
+                let _ = counter_idx;
                 SbiRet::success(0)
             }
             #[cfg(target_pointer_width = "32")]
             () => {
-                drop(counter_idx);
+                let _ = counter_idx;
                 SbiRet::not_supported()
             }
         }
@@ -286,114 +286,3 @@ impl<T: Pmu> Pmu for &T {
         T::counter_fw_read_hi(self, counter_idx)
     }
 }
-
-#[cfg(feature = "singleton")]
-use crate::util::AmoOnceRef;
-
-#[cfg(feature = "singleton")]
-static PMU: AmoOnceRef<dyn Pmu> = AmoOnceRef::new();
-
-#[cfg(feature = "singleton")]
-/// Init PMU module
-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() {
-        // Returns the number of counters (both hardware and firmware) in sbiret.value
-        // and always returns `SbiRet::success()`.
-        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()
-}
-
-#[cfg(feature = "singleton")]
-#[inline]
-pub(crate) fn counter_fw_read_hi(counter_idx: usize) -> SbiRet {
-    if let Some(obj) = PMU.get() {
-        return obj.counter_fw_read_hi(counter_idx);
-    }
-    SbiRet::not_supported()
-}

+ 0 - 29
src/reset.rs

@@ -45,32 +45,3 @@ impl<T: Reset> Reset for &T {
         T::system_reset(self, reset_type, reset_reason)
     }
 }
-
-#[cfg(feature = "singleton")]
-use crate::util::AmoOnceRef;
-
-#[cfg(feature = "singleton")]
-static RESET: AmoOnceRef<dyn Reset> = AmoOnceRef::new();
-
-#[cfg(feature = "singleton")]
-/// Init SRST module
-pub fn init_reset(reset: &'static dyn Reset) {
-    if !RESET.try_call_once(reset) {
-        panic!("load sbi module when already loaded")
-    }
-}
-
-#[cfg(feature = "singleton")]
-#[inline]
-pub(crate) fn probe_reset() -> bool {
-    RESET.get().is_some()
-}
-
-#[cfg(feature = "singleton")]
-#[inline]
-pub(crate) fn system_reset(reset_type: u32, reset_reason: u32) -> SbiRet {
-    if let Some(obj) = RESET.get() {
-        return obj.system_reset(reset_type, reset_reason);
-    }
-    SbiRet::not_supported()
-}

+ 0 - 105
src/rfence.rs

@@ -183,108 +183,3 @@ impl<T: Rfence> Rfence for &T {
         T::remote_hfence_vvma(self, hart_mask, start_addr, size)
     }
 }
-
-#[cfg(feature = "singleton")]
-use crate::util::AmoOnceRef;
-
-#[cfg(feature = "singleton")]
-static RFENCE: AmoOnceRef<dyn Rfence> = AmoOnceRef::new();
-
-#[cfg(feature = "singleton")]
-/// Init RFENCE module
-pub fn init_rfence(rfence: &'static dyn Rfence) {
-    if !RFENCE.try_call_once(rfence) {
-        panic!("load sbi module when already loaded")
-    }
-}
-
-#[cfg(feature = "singleton")]
-#[inline]
-pub(crate) fn probe_rfence() -> bool {
-    RFENCE.get().is_some()
-}
-
-#[cfg(feature = "singleton")]
-#[inline]
-pub(crate) fn remote_fence_i(hart_mask: HartMask) -> SbiRet {
-    if let Some(rfence) = RFENCE.get() {
-        rfence.remote_fence_i(hart_mask)
-    } else {
-        SbiRet::not_supported()
-    }
-}
-
-#[cfg(feature = "singleton")]
-#[inline]
-pub(crate) fn remote_sfence_vma(hart_mask: HartMask, start_addr: usize, size: usize) -> SbiRet {
-    if let Some(rfence) = RFENCE.get() {
-        rfence.remote_sfence_vma(hart_mask, start_addr, size)
-    } else {
-        SbiRet::not_supported()
-    }
-}
-
-#[cfg(feature = "singleton")]
-#[inline]
-pub(crate) fn remote_sfence_vma_asid(
-    hart_mask: HartMask,
-    start_addr: usize,
-    size: usize,
-    asid: usize,
-) -> SbiRet {
-    if let Some(rfence) = RFENCE.get() {
-        rfence.remote_sfence_vma_asid(hart_mask, start_addr, size, asid)
-    } else {
-        SbiRet::not_supported()
-    }
-}
-
-#[cfg(feature = "singleton")]
-#[inline]
-pub(crate) fn remote_hfence_gvma_vmid(
-    hart_mask: HartMask,
-    start_addr: usize,
-    size: usize,
-    vmid: usize,
-) -> SbiRet {
-    if let Some(rfence) = RFENCE.get() {
-        rfence.remote_hfence_gvma_vmid(hart_mask, start_addr, size, vmid)
-    } else {
-        SbiRet::not_supported()
-    }
-}
-
-#[cfg(feature = "singleton")]
-#[inline]
-pub(crate) fn remote_hfence_gvma(hart_mask: HartMask, start_addr: usize, size: usize) -> SbiRet {
-    if let Some(rfence) = RFENCE.get() {
-        rfence.remote_hfence_gvma(hart_mask, start_addr, size)
-    } else {
-        SbiRet::not_supported()
-    }
-}
-
-#[cfg(feature = "singleton")]
-#[inline]
-pub(crate) fn remote_hfence_vvma_asid(
-    hart_mask: HartMask,
-    start_addr: usize,
-    size: usize,
-    asid: usize,
-) -> SbiRet {
-    if let Some(rfence) = RFENCE.get() {
-        rfence.remote_hfence_vvma_asid(hart_mask, start_addr, size, asid)
-    } else {
-        SbiRet::not_supported()
-    }
-}
-
-#[cfg(feature = "singleton")]
-#[inline]
-pub(crate) fn remote_hfence_vvma(hart_mask: HartMask, start_addr: usize, size: usize) -> SbiRet {
-    if let Some(rfence) = RFENCE.get() {
-        rfence.remote_hfence_vvma(hart_mask, start_addr, size)
-    } else {
-        SbiRet::not_supported()
-    }
-}

+ 0 - 31
src/timer.rs

@@ -1,6 +1,3 @@
-#[cfg(feature = "singleton")]
-use crate::util::AmoOnceRef;
-
 /// Timer programmer support
 pub trait Timer: Send + Sync {
     /// Programs the clock for next event after `stime_value` time.
@@ -19,31 +16,3 @@ impl<T: Timer> Timer for &T {
         T::set_timer(self, stime_value)
     }
 }
-
-#[cfg(feature = "singleton")]
-static TIMER: AmoOnceRef<dyn Timer> = AmoOnceRef::new();
-
-#[cfg(feature = "singleton")]
-/// Init TIMER module
-pub fn init_timer(timer: &'static dyn Timer) {
-    if !TIMER.try_call_once(timer) {
-        panic!("load sbi module when already loaded")
-    }
-}
-
-#[cfg(feature = "singleton")]
-#[inline]
-pub(crate) fn probe_timer() -> bool {
-    TIMER.get().is_some()
-}
-
-#[cfg(feature = "singleton")]
-#[inline]
-pub(crate) fn set_timer(time_value: u64) -> bool {
-    if let Some(timer) = TIMER.get() {
-        timer.set_timer(time_value);
-        true
-    } else {
-        false
-    }
-}

+ 0 - 123
src/util.rs

@@ -1,123 +0,0 @@
-//! useful structures
-
-use core::{arch::asm, cell::UnsafeCell, marker::PhantomData, mem::MaybeUninit, ptr::Pointee};
-
-/// 只使用 AMO 指令的一次初始化引用存储。
-pub struct AmoOnceRef<'a, T: ?Sized> {
-    /// As atomic bool, to check if it is the first time to set `ptr`.
-    lock: UnsafeCell<u32>,
-    ptr: UnsafeCell<*const ()>,
-    meta: UnsafeCell<MaybeUninit<<T as Pointee>::Metadata>>,
-    _lifetime: PhantomData<&'a ()>,
-}
-
-/// 如果 AmoOncePtr 保存的引用是静态的,自然可以随意移动。
-unsafe impl<T: ?Sized> Send for AmoOnceRef<'static, T> {}
-
-/// AmoOncePtr 不提供锁。
-unsafe impl<T: ?Sized + Sync> Sync for AmoOnceRef<'static, T> {}
-
-impl<'a, T: ?Sized> AmoOnceRef<'a, T> {
-    #[inline]
-    pub const fn new() -> Self {
-        Self {
-            lock: UnsafeCell::new(0),
-            ptr: UnsafeCell::new(core::ptr::null()),
-            meta: UnsafeCell::new(MaybeUninit::uninit()),
-            _lifetime: PhantomData,
-        }
-    }
-
-    pub fn try_call_once(&self, r#ref: &'a T) -> bool {
-        let ptr = r#ref as *const T;
-        let locked: u32;
-        unsafe {
-            asm!(
-                "
-                lw           {locked}, ({lock})
-                bnez         {locked}, 1f
-                amoswap.w.aq {locked}, {one}, ({lock})
-                1: ",
-                lock   =  in(reg) self.lock.get(),
-                one    =  in(reg) 1,
-                locked = out(reg) locked,
-            );
-        }
-        if locked == 0 {
-            // 取得锁,初始化对象
-            unsafe {
-                // amo rl 保证先初始化 meta 后设置指针
-                (*self.meta.get()) = MaybeUninit::new(core::ptr::metadata(ptr));
-                #[cfg(target_pointer_width = "32")]
-                asm!(
-                    "amoswap.w.rl zero, {src}, ({dst})",
-                    src = in(reg) ptr as *const (),
-                    dst = in(reg) self.ptr.get(),
-                );
-                #[cfg(target_pointer_width = "64")]
-                asm!(
-                    "amoswap.d.rl zero, {src}, ({dst})",
-                    src = in(reg) ptr as *const (),
-                    dst = in(reg) self.ptr.get(),
-                );
-            }
-
-            true
-        } else {
-            // 未取得锁,对象已被初始化过
-            false
-        }
-    }
-
-    #[allow(unused)]
-    pub fn call_once(&self, r#ref: &'static T) -> Result<&T, &T> {
-        if self.try_call_once(r#ref) {
-            Ok(r#ref)
-        } else {
-            Err(self.wait())
-        }
-    }
-
-    pub fn wait(&self) -> &T {
-        loop {
-            // 反复读直到非空。
-            let ptr = unsafe { *self.ptr.get() };
-            if !ptr.is_null() {
-                return unsafe { self.build_ref_unchecked(ptr) };
-            }
-        }
-    }
-
-    pub fn get(&self) -> Option<&T> {
-        let ptr: *const ();
-        unsafe {
-            // 先获取指针。如果指针非空,元数据一定存在。
-            // FIXME AMO 设的值是否一定对 LD 可见?如果确定就不需要 AMO 读了。
-            #[cfg(target_pointer_width = "32")]
-            asm!(" lw          {dst}, ({src})
-                   bnez        {dst}, 1f
-                   amoadd.w.aq {dst}, zero, ({src})
-                1: ",
-                src =  in(reg) self.ptr.get(),
-                dst = out(reg) ptr,
-            );
-            #[cfg(target_pointer_width = "64")]
-            asm!(" ld          {dst}, ({src})
-                   bnez        {dst}, 1f
-                   amoadd.d.aq {dst}, zero, ({src})
-                1: ",
-                src =  in(reg) self.ptr.get(),
-                dst = out(reg) ptr,
-            );
-        }
-        if !ptr.is_null() {
-            Some(unsafe { self.build_ref_unchecked(ptr) })
-        } else {
-            None
-        }
-    }
-
-    unsafe fn build_ref_unchecked(&self, ptr: *const ()) -> &T {
-        &*core::ptr::from_raw_parts(ptr, (*self.meta.get()).assume_init())
-    }
-}