Quellcode durchsuchen

Use Rustfmt to reformat code

luojia65 vor 2 Jahren
Ursprung
Commit
e4f841ce72
17 geänderte Dateien mit 405 neuen und 281 gelöschten Zeilen
  1. 3 0
      rustfmt.toml
  2. 12 6
      src/ecall.rs
  3. 3 2
      src/ecall/hsm.rs
  4. 1 1
      src/ecall/ipi.rs
  5. 1 1
      src/ecall/legacy.rs
  6. 41 23
      src/ecall/pmu.rs
  7. 64 18
      src/ecall/rfence.rs
  8. 4 4
      src/hart_mask.rs
  9. 51 51
      src/hsm.rs
  10. 3 3
      src/ipi.rs
  11. 4 4
      src/legacy_stdio.rs
  12. 34 31
      src/lib.rs
  13. 86 77
      src/pmu.rs
  14. 25 20
      src/reset.rs
  15. 60 27
      src/rfence.rs
  16. 1 1
      src/timer.rs
  17. 12 12
      src/util.rs

+ 3 - 0
rustfmt.toml

@@ -0,0 +1,3 @@
+# Use rustfmt to format code
+
+# Empty file.

+ 12 - 6
src/ecall.rs

@@ -5,10 +5,10 @@ mod base;
 mod hsm;
 mod ipi;
 mod legacy;
+mod pmu;
+mod rfence;
 mod srst;
 mod timer;
-mod rfence;
-mod pmu;
 
 pub const EXTENSION_BASE: usize = 0x10;
 pub const EXTENSION_TIMER: usize = 0x54494D45;
@@ -66,7 +66,9 @@ const LEGACY_SHUTDOWN: usize = 0x08;
 #[inline]
 pub fn handle_ecall(extension: usize, function: usize, param: [usize; 6]) -> SbiRet {
     match extension {
-        EXTENSION_RFENCE => rfence::handle_ecall_rfence(function, param[0], param[1], param[2], param[3], param[4]),
+        EXTENSION_RFENCE => {
+            rfence::handle_ecall_rfence(function, param[0], param[1], param[2], param[3], param[4])
+        }
         EXTENSION_TIMER => match () {
             #[cfg(target_pointer_width = "64")]
             () => timer::handle_ecall_timer_64(function, param[0]),
@@ -79,9 +81,13 @@ pub fn handle_ecall(extension: usize, function: usize, param: [usize; 6]) -> Sbi
         EXTENSION_SRST => srst::handle_ecall_srst(function, param[0], param[1]),
         EXTENSION_PMU => match () {
             #[cfg(target_pointer_width = "64")]
-            () => pmu::handle_ecall_pmu_64(function, param[0], param[1], param[2], param[3], param[4]),
+            () => {
+                pmu::handle_ecall_pmu_64(function, param[0], param[1], param[2], param[3], param[4])
+            }
             #[cfg(target_pointer_width = "32")]
-            () => pmu::handle_ecall_pmu_32(function, param[0], param[1], param[2], param[3], param[4], param[5]),
+            () => pmu::handle_ecall_pmu_32(
+                function, param[0], param[1], param[2], param[3], param[4], param[5],
+            ),
         },
         LEGACY_SET_TIMER => match () {
             #[cfg(target_pointer_width = "64")]
@@ -150,7 +156,7 @@ impl SbiRet {
             value: 0,
         }
     }
-    /// SBI call failed for invalid mask start address, not a valid physical address parameter, 
+    /// SBI call failed for invalid mask start address, not a valid physical address parameter,
     /// or the target address is prohibited by PMP to run in supervisor mode.
     pub fn invalid_address() -> SbiRet {
         SbiRet {

+ 3 - 2
src/ecall/hsm.rs

@@ -34,8 +34,9 @@ fn hart_get_status(hartid: usize) -> SbiRet {
 
 #[inline]
 fn hart_suspend(suspend_type: usize, resume_addr: usize, opaque: usize) -> SbiRet {
-    if suspend_type > u32::MAX as usize { // valid suspend type should be a `u32` typed value
-        return SbiRet::invalid_param()
+    if suspend_type > u32::MAX as usize {
+        // valid suspend type should be a `u32` typed value
+        return SbiRet::invalid_param();
     }
     crate::hsm::hart_suspend(suspend_type as u32, resume_addr, opaque)
 }

+ 1 - 1
src/ecall/ipi.rs

@@ -17,7 +17,7 @@ fn send_ipi(hart_mask: usize, hart_mask_base: usize) -> SbiRet {
     let max_hart_id = if let Some(id) = max_hart_id() {
         id
     } else {
-        return SbiRet::not_supported()
+        return SbiRet::not_supported();
     };
     let hart_mask = unsafe { HartMask::from_addr(hart_mask, hart_mask_base, max_hart_id) };
     send_ipi_many(hart_mask)

+ 1 - 1
src/ecall/legacy.rs

@@ -23,7 +23,7 @@ pub fn send_ipi(hart_mask_addr: usize) -> SbiRet {
     let max_hart_id = if let Some(id) = max_hart_id() {
         id
     } else {
-        return SbiRet::not_supported()
+        return SbiRet::not_supported();
     };
     // note(unsafe): if any load fault, should be handled by user or supervisor
     // base hart should be 0 on legacy

+ 41 - 23
src/ecall/pmu.rs

@@ -11,11 +11,20 @@ const FUNCTION_PMU_COUNTER_FW_READ: usize = 0x5;
 
 #[inline]
 #[cfg(target_pointer_width = "64")]
-pub fn handle_ecall_pmu_64(function: usize, param0: usize, param1: usize, param2: usize, param3: usize, param4: usize) -> SbiRet {
+pub fn handle_ecall_pmu_64(
+    function: usize,
+    param0: usize,
+    param1: usize,
+    param2: usize,
+    param3: usize,
+    param4: usize,
+) -> SbiRet {
     match function {
         FUNCTION_PMU_NUM_COUNTERS => pmu::num_counters(),
         FUNCTION_PMU_COUNTER_GET_INFO => pmu::counter_get_info(param0),
-        FUNCTION_PMU_COUNTER_CONFIG_MATCHING => counter_config_matching_64(param0, param1, param2, param3, param4),
+        FUNCTION_PMU_COUNTER_CONFIG_MATCHING => {
+            counter_config_matching_64(param0, param1, param2, param3, param4)
+        }
         FUNCTION_PMU_COUNTER_START => counter_start_64(param0, param1, param2, param3),
         FUNCTION_PMU_COUNTER_STOP => pmu::counter_stop(param0, param1, param2),
         FUNCTION_PMU_COUNTER_FW_READ => pmu::counter_fw_read(param0),
@@ -25,11 +34,21 @@ pub fn handle_ecall_pmu_64(function: usize, param0: usize, param1: usize, param2
 
 #[inline]
 #[cfg(target_pointer_width = "32")]
-pub fn handle_ecall_pmu_32(function: usize, param0: usize, param1: usize, param2: usize, param3: usize, param4: usize, param5: usize) -> SbiRet {
+pub fn handle_ecall_pmu_32(
+    function: usize,
+    param0: usize,
+    param1: usize,
+    param2: usize,
+    param3: usize,
+    param4: usize,
+    param5: usize,
+) -> SbiRet {
     match function {
         FUNCTION_PMU_NUM_COUNTERS => pmu::num_counters(),
         FUNCTION_PMU_COUNTER_GET_INFO => pmu::counter_get_info(param0),
-        FUNCTION_PMU_COUNTER_CONFIG_MATCHING => counter_config_matching_32(param0, param1, param2, param3, param4, param5),
+        FUNCTION_PMU_COUNTER_CONFIG_MATCHING => {
+            counter_config_matching_32(param0, param1, param2, param3, param4, param5)
+        }
         FUNCTION_PMU_COUNTER_START => counter_start_32(param0, param1, param2, param3, param4),
         FUNCTION_PMU_COUNTER_STOP => pmu::counter_stop(param0, param1, param2),
         FUNCTION_PMU_COUNTER_FW_READ => pmu::counter_fw_read(param0),
@@ -38,26 +57,25 @@ pub fn handle_ecall_pmu_32(function: usize, param0: usize, param1: usize, param2
 }
 
 #[cfg(target_pointer_width = "64")]
-#[inline] 
+#[inline]
 fn counter_config_matching_64(
     counter_idx_base: usize,
     counter_idx_mask: usize,
     config_flags: usize,
     event_idx: usize,
-    event_data: usize
+    event_data: usize,
 ) -> SbiRet {
     pmu::counter_config_matching(
         counter_idx_base,
         counter_idx_mask,
         config_flags,
         event_idx,
-        event_data as u64
+        event_data as u64,
     )
 }
 
-
 #[cfg(target_pointer_width = "32")]
-#[inline] 
+#[inline]
 fn counter_config_matching_32(
     counter_idx_base: usize,
     counter_idx_mask: usize,
@@ -72,40 +90,40 @@ fn counter_config_matching_32(
         counter_idx_mask,
         config_flags,
         event_idx,
-        event_data
+        event_data,
     )
 }
 
 #[cfg(target_pointer_width = "64")]
-#[inline] 
+#[inline]
 fn counter_start_64(
-    counter_idx_base: usize, 
-    counter_idx_mask: usize, 
-    start_flags: usize, 
-    initial_value: usize
+    counter_idx_base: usize,
+    counter_idx_mask: usize,
+    start_flags: usize,
+    initial_value: usize,
 ) -> SbiRet {
     pmu::counter_start(
-        counter_idx_base, 
+        counter_idx_base,
         counter_idx_mask,
         start_flags,
-        initial_value as u64
+        initial_value as u64,
     )
 }
 
 #[cfg(target_pointer_width = "32")]
-#[inline] 
+#[inline]
 fn counter_start_32(
-    counter_idx_base: usize, 
-    counter_idx_mask: usize, 
-    start_flags: usize, 
+    counter_idx_base: usize,
+    counter_idx_mask: usize,
+    start_flags: usize,
     initial_value_lo: usize,
     initial_value_hi: usize,
 ) -> SbiRet {
     let initial_value = (initial_value_lo as u64) + ((initial_value_hi as u64) << 32);
     pmu::counter_start(
-        counter_idx_base, 
+        counter_idx_base,
         counter_idx_mask,
         start_flags,
-        initial_value
+        initial_value,
     )
 }

+ 64 - 18
src/ecall/rfence.rs

@@ -1,7 +1,7 @@
 use super::SbiRet;
-use crate::rfence;
 use crate::hart_mask::HartMask;
 use crate::ipi::max_hart_id;
+use crate::rfence;
 
 const FUNCTION_RFENCE_REMOTE_FENCE_I: usize = 0x0;
 const FUNCTION_RFENCE_REMOTE_SFENCE_VMA: usize = 0x1;
@@ -12,14 +12,27 @@ const FUNCTION_RFENCE_REMOTE_HFENCE_VVMA_ASID: usize = 0x5;
 const FUNCTION_RFENCE_REMOTE_HFENCE_VVMA: usize = 0x6;
 
 #[inline]
-pub fn handle_ecall_rfence(function: usize, param0: usize, param1: usize, param2: usize, param3: usize, param4: usize) -> SbiRet {
+pub fn handle_ecall_rfence(
+    function: usize,
+    param0: usize,
+    param1: usize,
+    param2: usize,
+    param3: usize,
+    param4: usize,
+) -> SbiRet {
     match function {
         FUNCTION_RFENCE_REMOTE_FENCE_I => remote_fence_i(param0, param1),
         FUNCTION_RFENCE_REMOTE_SFENCE_VMA => remote_sfence_vma(param0, param1, param2, param3),
-        FUNCTION_RFENCE_REMOTE_SFENCE_VMA_ASID => remote_sfence_vma_asid(param0, param1, param2, param3, param4),
-        FUNCTION_RFENCE_REMOTE_HFENCE_GVMA_VMID => remote_hfence_gvma_vmid(param0, param1, param2, param3, param4),
+        FUNCTION_RFENCE_REMOTE_SFENCE_VMA_ASID => {
+            remote_sfence_vma_asid(param0, param1, param2, param3, param4)
+        }
+        FUNCTION_RFENCE_REMOTE_HFENCE_GVMA_VMID => {
+            remote_hfence_gvma_vmid(param0, param1, param2, param3, param4)
+        }
         FUNCTION_RFENCE_REMOTE_HFENCE_GVMA => remote_hfence_gvma(param0, param1, param2, param3),
-        FUNCTION_RFENCE_REMOTE_HFENCE_VVMA_ASID => remote_hfence_vvma_asid(param0, param1, param2, param3, param4),
+        FUNCTION_RFENCE_REMOTE_HFENCE_VVMA_ASID => {
+            remote_hfence_vvma_asid(param0, param1, param2, param3, param4)
+        }
         FUNCTION_RFENCE_REMOTE_HFENCE_VVMA => remote_hfence_vvma(param0, param1, param2, param3),
         _ => SbiRet::not_supported(),
     }
@@ -35,73 +48,106 @@ fn remote_fence_i(hart_mask: usize, hart_mask_base: usize) -> SbiRet {
     let max_hart_id = if let Some(id) = max_hart_id() {
         id
     } else {
-        return SbiRet::not_supported()
+        return SbiRet::not_supported();
     };
     let hart_mask = unsafe { HartMask::from_addr(hart_mask, hart_mask_base, max_hart_id) };
     rfence::remote_fence_i(hart_mask)
 }
 
 #[inline]
-fn remote_sfence_vma(hart_mask: usize, hart_mask_base: usize, start_addr: usize, size: usize) -> SbiRet {
+fn remote_sfence_vma(
+    hart_mask: usize,
+    hart_mask_base: usize,
+    start_addr: usize,
+    size: usize,
+) -> SbiRet {
     let max_hart_id = if let Some(id) = max_hart_id() {
         id
     } else {
-        return SbiRet::not_supported()
+        return SbiRet::not_supported();
     };
     let hart_mask = unsafe { HartMask::from_addr(hart_mask, hart_mask_base, max_hart_id) };
     rfence::remote_sfence_vma(hart_mask, start_addr, size)
 }
 
 #[inline]
-fn remote_sfence_vma_asid(hart_mask: usize, hart_mask_base: usize, start_addr: usize, size: usize, asid: usize) -> SbiRet {
+fn remote_sfence_vma_asid(
+    hart_mask: usize,
+    hart_mask_base: usize,
+    start_addr: usize,
+    size: usize,
+    asid: usize,
+) -> SbiRet {
     let max_hart_id = if let Some(id) = max_hart_id() {
         id
     } else {
-        return SbiRet::not_supported()
+        return SbiRet::not_supported();
     };
     let hart_mask = unsafe { HartMask::from_addr(hart_mask, hart_mask_base, max_hart_id) };
     rfence::remote_sfence_vma_asid(hart_mask, start_addr, size, asid)
 }
 
 #[inline]
-fn remote_hfence_gvma_vmid(hart_mask: usize, hart_mask_base: usize, start_addr: usize, size: usize, vmid: usize) -> SbiRet {
+fn remote_hfence_gvma_vmid(
+    hart_mask: usize,
+    hart_mask_base: usize,
+    start_addr: usize,
+    size: usize,
+    vmid: usize,
+) -> SbiRet {
     let max_hart_id = if let Some(id) = max_hart_id() {
         id
     } else {
-        return SbiRet::not_supported()
+        return SbiRet::not_supported();
     };
     let hart_mask = unsafe { HartMask::from_addr(hart_mask, hart_mask_base, max_hart_id) };
     rfence::remote_hfence_gvma_vmid(hart_mask, start_addr, size, vmid)
 }
 
 #[inline]
-fn remote_hfence_gvma(hart_mask: usize, hart_mask_base: usize, start_addr: usize, size: usize) -> SbiRet {
+fn remote_hfence_gvma(
+    hart_mask: usize,
+    hart_mask_base: usize,
+    start_addr: usize,
+    size: usize,
+) -> SbiRet {
     let max_hart_id = if let Some(id) = max_hart_id() {
         id
     } else {
-        return SbiRet::not_supported()
+        return SbiRet::not_supported();
     };
     let hart_mask = unsafe { HartMask::from_addr(hart_mask, hart_mask_base, max_hart_id) };
     rfence::remote_hfence_gvma(hart_mask, start_addr, size)
 }
 
 #[inline]
-fn remote_hfence_vvma_asid(hart_mask: usize, hart_mask_base: usize, start_addr: usize, size: usize, asid: usize) -> SbiRet {
+fn remote_hfence_vvma_asid(
+    hart_mask: usize,
+    hart_mask_base: usize,
+    start_addr: usize,
+    size: usize,
+    asid: usize,
+) -> SbiRet {
     let max_hart_id = if let Some(id) = max_hart_id() {
         id
     } else {
-        return SbiRet::not_supported()
+        return SbiRet::not_supported();
     };
     let hart_mask = unsafe { HartMask::from_addr(hart_mask, hart_mask_base, max_hart_id) };
     rfence::remote_hfence_vvma_asid(hart_mask, start_addr, size, asid)
 }
 
 #[inline]
-fn remote_hfence_vvma(hart_mask: usize, hart_mask_base: usize, start_addr: usize, size: usize) -> SbiRet {
+fn remote_hfence_vvma(
+    hart_mask: usize,
+    hart_mask_base: usize,
+    start_addr: usize,
+    size: usize,
+) -> SbiRet {
     let max_hart_id = if let Some(id) = max_hart_id() {
         id
     } else {
-        return SbiRet::not_supported()
+        return SbiRet::not_supported();
     };
     let hart_mask = unsafe { HartMask::from_addr(hart_mask, hart_mask_base, max_hart_id) };
     rfence::remote_hfence_vvma(hart_mask, start_addr, size)

+ 4 - 4
src/hart_mask.rs

@@ -13,7 +13,7 @@ impl HartMask {
     ///
     /// # Parameters
     ///
-    /// - The `vaddr` is a scalar bit-vector containing hartids. 
+    /// - The `vaddr` is a scalar bit-vector containing hartids.
     ///   Should return address from supervisor level.
     /// - The `base` is the starting hartid from which bit-vector must be computed.
     ///   If `base` equals `usize::MAX`, that means `vaddr` is ignored and all available harts must be considered.
@@ -66,7 +66,7 @@ unsafe fn get_vaddr_usize(vaddr_ptr: *const usize) -> usize {
                 csrw    mstatus, {tmp}
             ", ans = lateout(reg) ans, vmem = in(reg) vaddr_ptr, tmp = out(reg) _);
             ans
-        },
+        }
         #[cfg(target_arch = "riscv64")]
         () => {
             let mut ans: usize;
@@ -77,7 +77,7 @@ unsafe fn get_vaddr_usize(vaddr_ptr: *const usize) -> usize {
                 csrw    mstatus, {tmp}
             ", ans = lateout(reg) ans, vmem = in(reg) vaddr_ptr, tmp = out(reg) _);
             ans
-        },
+        }
         #[cfg(target_arch = "riscv128")]
         () => {
             let mut ans: usize;
@@ -88,7 +88,7 @@ unsafe fn get_vaddr_usize(vaddr_ptr: *const usize) -> usize {
                 csrw    mstatus, {tmp}
             ", ans = lateout(reg) ans, vmem = in(reg) vaddr_ptr, tmp = out(reg) _);
             ans
-        },
+        }
         #[cfg(not(any(target_arch = "riscv32", target_arch = "riscv64")))]
         () => {
             drop(vaddr_ptr);

+ 51 - 51
src/hsm.rs

@@ -2,34 +2,34 @@ use crate::ecall::SbiRet;
 
 /// Hart State Management Extension
 ///
-/// The Hart State Management (HSM) Extension introduces a set hart states and a set of functions 
+/// The Hart State Management (HSM) Extension introduces a set hart states and a set of functions
 /// which allow the supervisor-mode software to request a hart state change.
 ///
 /// # Hart states
-/// 
+///
 /// The possible hart states along with a unique State ID are as follows:
 ///
-/// | State ID | State Name | Description 
+/// | State ID | State Name | Description
 /// |:---------|:-----------|:------------
-/// | 0 | STARTED | The hart is physically powered-up and executing normally. 
-/// | 1 | STOPPED | The hart is not executing in supervisor-mode or any lower privilege mode. It is probably powered-down by the SBI implementation if the underlying platform has a mechanism to physically power-down harts. 
-/// | 2 | START_PENDING | Some other hart has requested to start (or power-up) the hart from the **STOPPED** state and the SBI implementation is still working to get the hart in the **STARTED** state. 
-/// | 3 | STOP_PENDING | The hart has requested to stop (or power-down) itself from the STARTED state and the SBI implementation is still working to get the hart in the **STOPPED** state. 
-/// | 4 | SUSPENDED | This hart is in a platform specific suspend (or low power) state. 
-/// | 5 | SUSPEND_PENDING | The hart has requestd to put itself in a platform specific low power state from the **STARTED** state and the SBI implementation is still working to get the hart in the platform specific **SUSPENDED** state. 
-/// | 6 | RESUME_PENDING | An interrupt or platform specific hardware event has caused the hart to resume normal execution from the **SUSPENDED** state and the SBI implementation is still working to get the hart in the **STARTED** state. 
+/// | 0 | STARTED | The hart is physically powered-up and executing normally.
+/// | 1 | STOPPED | The hart is not executing in supervisor-mode or any lower privilege mode. It is probably powered-down by the SBI implementation if the underlying platform has a mechanism to physically power-down harts.
+/// | 2 | START_PENDING | Some other hart has requested to start (or power-up) the hart from the **STOPPED** state and the SBI implementation is still working to get the hart in the **STARTED** state.
+/// | 3 | STOP_PENDING | The hart has requested to stop (or power-down) itself from the STARTED state and the SBI implementation is still working to get the hart in the **STOPPED** state.
+/// | 4 | SUSPENDED | This hart is in a platform specific suspend (or low power) state.
+/// | 5 | SUSPEND_PENDING | The hart has requestd to put itself in a platform specific low power state from the **STARTED** state and the SBI implementation is still working to get the hart in the platform specific **SUSPENDED** state.
+/// | 6 | RESUME_PENDING | An interrupt or platform specific hardware event has caused the hart to resume normal execution from the **SUSPENDED** state and the SBI implementation is still working to get the hart in the **STARTED** state.
 ///
 /// At any point in time, a hart should be in one of the above mentioned hart states.
 ///
 /// # Topology hart groups
-/// 
-/// A platform can have multiple harts grouped into a hierarchical topology groups (namely cores, clusters, nodes, etc) 
+///
+/// A platform can have multiple harts grouped into a hierarchical topology groups (namely cores, clusters, nodes, etc)
 /// with separate platform specific low-power states for each hierarchical group.
-/// These platform specific low-power states of hierarchial topology groups can be represented as platform specific suspend states of a hart. 
+/// These platform specific low-power states of hierarchial topology groups can be represented as platform specific suspend states of a hart.
 /// A SBI implementation can utilize the suspend states of higher topology groups using one of the following approaches:
-/// 
+///
 /// 1. *Platform-coordinated:* In this approach, when a hart becomes idle the supervisor-mode power-managment software
-///   will request deepest suspend state for the hart and higher topology groups. 
+///   will request deepest suspend state for the hart and higher topology groups.
 ///   A SBI implementation should choose a suspend state at higher topology group which is:
 /// - Not deeper than the specified suspend state
 /// - Wake-up latency is not higher than the wake-up latency of the specified suspend state
@@ -40,23 +40,23 @@ use crate::ecall::SbiRet;
 ///   A SBI implementation should:
 /// - Never choose a suspend state for higher topology group different from the specified suspend state
 /// - Always prefer most recent suspend state requested for higher topology group
-/// 
+///
 /// Ref: [Section 8, RISC-V Supervisor Binary Interface Specification](https://github.com/riscv-non-isa/riscv-sbi-doc/blob/master/riscv-sbi.adoc#8-hart-state-management-extension-eid-0x48534d-hsm)
 pub trait Hsm: Send {
     /// Request the SBI implementation to start executing the given hart at specified address in supervisor-mode.
     ///
-    /// This call is asynchronous — more specifically, the `sbi_hart_start()` may return before target hart 
-    /// starts executing as long as the SBI implemenation is capable of ensuring the return code is accurate. 
-    /// 
-    /// It is recommended that if the SBI implementation is a platform runtime firmware executing in machine-mode (M-mode) 
+    /// This call is asynchronous — more specifically, the `sbi_hart_start()` may return before target hart
+    /// starts executing as long as the SBI implemenation is capable of ensuring the return code is accurate.
+    ///
+    /// It is recommended that if the SBI implementation is a platform runtime firmware executing in machine-mode (M-mode)
     /// then it MUST configure PMP and other the M-mode state before executing in supervisor-mode.
     ///
     /// # Parameters
-    /// 
+    ///
     /// - The `hartid` parameter specifies the target hart which is to be started.
     /// - The `start_addr` parameter points to a runtime-specified physical address, where the hart can start executing in supervisor-mode.
     /// - The `opaque` parameter is a `usize` value which will be set in the `a1` register when the hart starts executing at `start_addr`.
-    /// 
+    ///
     /// # Behavior
     ///
     /// The target hart jumps to supervisor-mode at address specified by `start_addr` with following values in specific registers.
@@ -67,41 +67,41 @@ pub trait Hsm: Send {
     /// | `sstatus.SIE` | 0
     /// | a0            | hartid
     /// | a1            | `opaque` parameter
-    /// 
+    ///
     /// # Return value
     ///
     /// The possible return error codes returned in `SbiRet.error` are shown in the table below:
     ///
-    /// | Return code               | Description 
+    /// | Return code               | Description
     /// |:--------------------------|:----------------------------------------------
     /// | SBI_SUCCESS               | Hart was previously in stopped state. It will start executing from `start_addr`.
     /// | SBI_ERR_INVALID_ADDRESS   | `start_addr` is not valid possibly due to following reasons: 1. It is not a valid physical address. 2. The address is prohibited by PMP to run in supervisor mode.
-    /// | SBI_ERR_INVALID_PARAM     | `hartid` is not a valid hartid as corresponding hart cannot started in supervisor mode. 
+    /// | SBI_ERR_INVALID_PARAM     | `hartid` is not a valid hartid as corresponding hart cannot started in supervisor mode.
     /// | SBI_ERR_ALREADY_AVAILABLE | The given hartid is already started.
     /// | SBI_ERR_FAILED            | The start request failed for unknown reasons.
     fn hart_start(&self, hartid: usize, start_addr: usize, opaque: usize) -> SbiRet;
-    /// Request the SBI implementation to stop executing the calling hart in supervisor-mode 
-    /// and return it’s ownership to the SBI implementation. 
+    /// Request the SBI implementation to stop executing the calling hart in supervisor-mode
+    /// and return it’s ownership to the SBI implementation.
     ///
-    /// This call is not expected to return under normal conditions. 
+    /// This call is not expected to return under normal conditions.
     /// The `sbi_hart_stop()` must be called with the supervisor-mode interrupts disabled.
     ///
     /// # Return value
-    /// 
+    ///
     /// The possible return error codes returned in `SbiRet.error` are shown in the table below:
     ///
-    /// | Error code  | Description 
+    /// | Error code  | Description
     /// |:------------|:------------
-    /// | SBI_ERR_FAILED | Failed to stop execution of the current hart 
+    /// | SBI_ERR_FAILED | Failed to stop execution of the current hart
     fn hart_stop(&self, hartid: usize) -> SbiRet;
     /// Get the current status (or HSM state id) of the given hart.
     ///
     /// The harts may transition HSM states at any time due to any concurrent `sbi_hart_start()`
-    /// or `sbi_hart_stop()` calls, the return value from this function may not represent the actual state 
+    /// or `sbi_hart_stop()` calls, the return value from this function may not represent the actual state
     /// of the hart at the time of return value verification.
-    /// 
+    ///
     /// # Parameters
-    /// 
+    ///
     /// The `hartid` parameter specifies the target hart which status is required.
     ///
     /// # Return value
@@ -114,34 +114,34 @@ pub trait Hsm: Send {
     /// | STOPPED       |   1   | Hart Stopped
     /// | START_PENDING |   2   | Hart start request pending
     /// | STOP_PENDING  |   3   | Hart stop request pending
-    /// 
+    ///
     /// The possible return error codes returned in `SbiRet.error` are shown in the table below:
     ///
-    /// | Error code  | Description 
+    /// | Error code  | Description
     /// |:------------|:------------
     /// | SBI_ERR_INVALID_PARAM | The given `hartid` is not valid
     fn hart_get_status(&self, hartid: usize) -> SbiRet;
     /// Request the SBI implementation to put the calling hart in a platform specfic suspend (or low power) state
-    /// specified by the `suspend_type` parameter. 
-    /// 
+    /// specified by the `suspend_type` parameter.
+    ///
     /// The hart will automatically come out of suspended state and resume normal execution
     /// when it recieves an interrupt or platform specific hardware event.
-    /// 
+    ///
     /// # Suspend behavior
-    /// 
+    ///
     /// The platform specific suspend states for a hart can be either retentive or non-rententive in nature.
     ///
     /// A retentive suspend state will preserve hart register and CSR values for all privilege modes,
     /// whereas a non-retentive suspend state will not preserve hart register and CSR values.
     ///
     /// # Resuming
-    /// 
-    /// Resuming from a retentive suspend state is straight forward and the supervisor-mode software 
+    ///
+    /// Resuming from a retentive suspend state is straight forward and the supervisor-mode software
     /// will see SBI suspend call return without any failures.
-    /// 
-    /// Resuming from a non-retentive suspend state is relatively more involved and requires software 
-    /// to restore various hart registers and CSRs for all privilege modes. 
-    /// Upon resuming from non-retentive suspend state, the hart will jump to supervisor-mode at address 
+    ///
+    /// Resuming from a non-retentive suspend state is relatively more involved and requires software
+    /// to restore various hart registers and CSRs for all privilege modes.
+    /// Upon resuming from non-retentive suspend state, the hart will jump to supervisor-mode at address
     /// specified by `resume_addr` with specific registers values described in the table below:
     ///
     /// | Register Name | Register Value
@@ -168,15 +168,15 @@ pub trait Hsm: Send {
     /// The `resume_addr` parameter points to a runtime-specified physical address,
     /// where the hart can resume execution in supervisor-mode after a non-retentive
     /// suspend.
-    /// 
+    ///
     /// The `opaque` parameter is a XLEN-bit value which will be set in the `a1`
     /// register when the hart resumes exectution at `resume_addr` after a
     /// non-retentive suspend.
-    /// 
+    ///
     /// # Return value
-    /// 
+    ///
     /// The possible return error codes returned in `SbiRet.error` are shown in the table below:
-    /// 
+    ///
     /// | Error code              | Description
     /// |:------------------------|:------------
     /// | SBI_SUCCESS             | Hart has suspended and resumed back successfully from a retentive suspend state.
@@ -190,8 +190,8 @@ pub trait Hsm: Send {
     }
 }
 
-use alloc::boxed::Box;
 use crate::util::OnceFatBox;
+use alloc::boxed::Box;
 
 static HSM: OnceFatBox<dyn Hsm + Sync + 'static> = OnceFatBox::new();
 

+ 3 - 3
src/ipi.rs

@@ -1,5 +1,5 @@
-use crate::hart_mask::HartMask;
 use crate::ecall::SbiRet;
+use crate::hart_mask::HartMask;
 use crate::util::OnceFatBox;
 use alloc::boxed::Box;
 
@@ -12,7 +12,7 @@ pub trait Ipi: Send {
     /// Interprocessor interrupts manifest at the receiving harts as the supervisor software interrupts.
     ///
     /// # Return value
-    /// 
+    ///
     /// Should return error code `SBI_SUCCESS` if IPI was sent to all the targeted harts successfully.
     fn send_ipi_many(&self, hart_mask: HartMask) -> SbiRet;
 }
@@ -40,7 +40,7 @@ pub(crate) fn send_ipi_many(hart_mask: HartMask) -> SbiRet {
     }
 }
 
-pub(crate) fn max_hart_id() -> Option<usize> { 
+pub(crate) fn max_hart_id() -> Option<usize> {
     if let Some(ipi) = IPI.get() {
         Some(ipi.max_hart_id())
     } else {

+ 4 - 4
src/legacy_stdio.rs

@@ -93,9 +93,9 @@ pub fn legacy_stdio_getchar() -> usize {
     if let Some(stdio) = LEGACY_STDIO.lock().as_mut() {
         stdio.getchar() as usize
     } else {
-        // According to RISC-V SBI spec 0.3.1-rc1, Section 4.3, this function returns -1 
+        // According to RISC-V SBI spec 0.3.1-rc1, Section 4.3, this function returns -1
         // when fails to read from debug console. Thank you @duskmoon314
-        usize::from_ne_bytes(isize::to_ne_bytes(-1)) 
+        usize::from_ne_bytes(isize::to_ne_bytes(-1))
     }
 }
 
@@ -122,7 +122,7 @@ pub fn _print(args: fmt::Arguments) {
 
 /// Prints to the legacy debug console.
 ///
-/// This is only supported when there exists legacy extension; 
+/// This is only supported when there exists legacy extension;
 /// otherwise platform caller should use an early kernel input/output device
 /// declared in platform specific hardware.
 #[macro_export(local_inner_macros)]
@@ -134,7 +134,7 @@ macro_rules! print {
 
 /// Prints to the legacy debug console, with a newline.
 ///
-/// This is only supported when there exists legacy extension; 
+/// This is only supported when there exists legacy extension;
 /// otherwise platform caller should use an early kernel input/output device
 /// declared in platform specific hardware.
 #[macro_export(local_inner_macros)]

+ 34 - 31
src/lib.rs

@@ -1,11 +1,11 @@
 //! A minimal RISC-V's SBI implementation library in Rust.
-//! 
+//!
 //! # What is RISC-V SBI?
 //!
-//! RISC-V SBI is short for RISC-V Supervisor Binary Interface. SBI acts as a bootloader environment to your operating system kernel. 
+//! RISC-V SBI is short for RISC-V Supervisor Binary Interface. SBI acts as a bootloader environment to your operating system kernel.
 //! A SBI implementation will bootstrap your kernel, and provide an environment when your kernel is running.
 //!
-//! More generally, The SBI allows supervisor-mode (S-mode or VS-mode) software to be portable across 
+//! More generally, The SBI allows supervisor-mode (S-mode or VS-mode) software to be portable across
 //! all RISC-V implementations by defining an abstraction for platform (or hypervisor) specific functionality.
 //!
 //! # How to use RustSBI in your supervisor software
@@ -20,25 +20,25 @@
 //! SBI calls are similar to operating systems' `syscall`s. RISC-V SBI defined many SBI modules,
 //! and in each module there are different functions, you should pick a function before calling.
 //! Then, you should prepare some parameters, whose definition are not the same among functions.
-//! 
+//!
 //! Now you have a module number, a function number, and a few SBI call parameters.
 //! You invoke a special `ecall` instruction on supervisor level, and it will trap into machine level
-//! SBI implementation. It will handle your `ecall`, similar to your kernel handling system calls 
-//! from user level. 
+//! SBI implementation. It will handle your `ecall`, similar to your kernel handling system calls
+//! from user level.
 //!
 //! SBI functions return two values other than one. First value will be an error number,
-//! it will tell if SBI call have succeeded, or which error have occurred. 
+//! it will tell if SBI call have succeeded, or which error have occurred.
 //! Second value is the real return value, its meaning is different according to which function you calls.
 //!
 //! ## Call SBI in different programming languages
 //!
-//! Making SBI calls are similar to making system calls. 
-//! 
-//! Module number is required to put on register `a7`, function number on `a6`. 
+//! Making SBI calls are similar to making system calls.
+//!
+//! Module number is required to put on register `a7`, function number on `a6`.
 //! Parameters should be placed from `a0` to `a5`, first into `a0`, second into `a1`, etc.
 //! Unused parameters can be set to any value or leave untouched.
 //!
-//! After registers are ready, invoke an instruction called `ecall`. 
+//! After registers are ready, invoke an instruction called `ecall`.
 //! Then, the return value is placed into `a0` and `a1` registers.
 //! The error value could be read from `a0`, and return value is placed into `a1`.
 //!
@@ -51,7 +51,7 @@
 //!     match () {
 //!         #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
 //!         () => unsafe { asm!(
-//!             "ecall", 
+//!             "ecall",
 //!             in("a0") arg0, in("a1") arg1,
 //!             in("a6") function, in("a7") extension,
 //!             lateout("a0") error, lateout("a1") value,
@@ -71,7 +71,7 @@
 //! }
 //! ```
 //!
-//! Complex SBI functions may fail. In this example we only take the value, but in complete designs 
+//! Complex SBI functions may fail. In this example we only take the value, but in complete designs
 //! we should handle the `error` value returned from SbiRet.
 //!
 //! You may use other languages to call SBI environment. In C programming language, we can call like this:
@@ -90,7 +90,7 @@
 //!         : "memory") \
 //!     {a0, a1}; \
 //! })
-//! 
+//!
 //! #define SBI_CALL_0(module, funct) SBI_CALL(module, funct, 0, 0, 0, 0)
 //!
 //! static inline sbiret get_spec_version() {
@@ -108,11 +108,11 @@
 //! but it will be considered not useful and takes up lots of flash room for other users.
 //!
 //! The RustSBI team provides reference implementation for several platforms, but they are for evaluation
-//! and should not be used in production. 
+//! and should not be used in production.
 //! RustSBI itself cannot decide for all arbitrary users, so developers are encouraged to write their own
 //! SBI implementation, other than use reference implementation directly when in production.
 //!
-//! Also, RustSBI is not designed to include all platforms available in official repository. 
+//! Also, RustSBI is not designed to include all platforms available in official repository.
 //! For an actual platform users may consult board or SoC manufacturer other than RustSBI repository itself.
 //!
 //! The reason to that is that if some repository includes all platforms it support,
@@ -123,15 +123,15 @@
 //!
 //! # Notes for RustSBI developers
 //!
-//! This library adapts to embedded Rust's `embedded-hal` crate to provide basic SBI features. 
+//! This library adapts to embedded Rust's `embedded-hal` crate to provide basic SBI features.
 //! When building for own platform, implement traits in this library and pass them to the functions
 //! begin with `init`. After that, you may call `rustsbi::ecall` in your own exception handler
 //! which would dispatch parameters from supervisor to the traits to execute SBI functions.
 //!
 //! The library also implements useful functions which may help with platform specific binaries.
-//! The `enter_privileged` maybe used to enter the operating system after the initialization 
+//! The `enter_privileged` maybe used to enter the operating system after the initialization
 //! process is finished. The `LOGO` should be printed if necessary when the binary is initializing.
-//! 
+//!
 //! Note that this crate is a library which contains common building blocks in SBI implementation.
 //! It is not intended to be used directly; users should build own platforms with this library.
 //! RustSBI provides implementations on common platforms in separate platform crates.
@@ -151,12 +151,12 @@ mod hart_mask;
 mod hsm;
 mod ipi;
 mod logo;
+mod pmu;
 mod privileged;
 #[doc(hidden)]
 pub mod reset;
-mod timer;
 mod rfence;
-mod pmu;
+mod timer;
 
 mod util;
 
@@ -167,12 +167,15 @@ const SBI_SPEC_MINOR: usize = 3;
 // Ref: https://github.com/riscv-non-isa/riscv-sbi-doc/pull/61
 const IMPL_ID_RUSTSBI: usize = 4;
 // Read from env!("CARGO_PKG_VERSION")
-const RUSTSBI_VERSION_MAJOR: usize = (env!("CARGO_PKG_VERSION_MAJOR").as_bytes()[0] - b'0') as usize;
-const RUSTSBI_VERSION_MINOR: usize = (env!("CARGO_PKG_VERSION_MINOR").as_bytes()[0] - b'0') as usize;
-const RUSTSBI_VERSION_PATCH: usize = (env!("CARGO_PKG_VERSION_PATCH").as_bytes()[0] - b'0') as usize;
-const RUSTSBI_VERSION: usize = {
-   (RUSTSBI_VERSION_MAJOR << 16) + (RUSTSBI_VERSION_MINOR << 8) + RUSTSBI_VERSION_PATCH
-};
+const RUSTSBI_VERSION_MAJOR: usize =
+    (env!("CARGO_PKG_VERSION_MAJOR").as_bytes()[0] - b'0') as usize;
+const RUSTSBI_VERSION_MINOR: usize =
+    (env!("CARGO_PKG_VERSION_MINOR").as_bytes()[0] - b'0') as usize;
+const RUSTSBI_VERSION_PATCH: usize =
+    (env!("CARGO_PKG_VERSION_PATCH").as_bytes()[0] - b'0') as usize;
+#[rustfmt::skip]
+const RUSTSBI_VERSION: usize =
+    (RUSTSBI_VERSION_MAJOR << 16) + (RUSTSBI_VERSION_MINOR << 8) + RUSTSBI_VERSION_PATCH;
 /// RustSBI version as a string.
 pub const VERSION: &'static str = env!("CARGO_PKG_VERSION");
 
@@ -181,11 +184,11 @@ pub use ecall::SbiRet;
 pub use hart_mask::HartMask;
 pub use hsm::{init_hsm, Hsm};
 pub use ipi::{init_ipi, Ipi};
+#[doc(hidden)]
+pub use legacy_stdio::{legacy_stdio_getchar, legacy_stdio_putchar};
 pub use logo::LOGO;
+pub use pmu::{init_pmu, Pmu};
 pub use privileged::enter_privileged;
 pub use reset::{init_reset, Reset};
-pub use timer::{init_timer, Timer};
 pub use rfence::{init_rfence as init_remote_fence, Rfence as Fence};
-pub use pmu::{init_pmu, Pmu};
-#[doc(hidden)]
-pub use legacy_stdio::{legacy_stdio_getchar, legacy_stdio_putchar};
+pub use timer::{init_timer, Timer};

+ 86 - 77
src/pmu.rs

@@ -4,31 +4,31 @@ use alloc::boxed::Box;
 
 /// Performance Monitoring Unit Extension
 ///
-/// The RISC-V hardware performance counters such as `mcycle`, `minstret`, and `mhpmcounterX` CSRs 
-/// are accessible as read-only from supervisor-mode using `cycle`, `instret`, and `hpmcounterX` CSRs. 
-/// The SBI performance monitoring unit (PMU) extension is an interface for supervisor-mode to configure 
-/// and use the RISC-V hardware performance counters with assistance from the machine-mode (or hypervisor-mode). 
-/// These hardware performance counters can only be started, stopped, or configured from machine-mode 
-/// using `mcountinhibit` and `mhpmeventX` CSRs. 
-/// Due to this, a machine-mode SBI implementation may choose to disallow SBI PMU extension 
+/// The RISC-V hardware performance counters such as `mcycle`, `minstret`, and `mhpmcounterX` CSRs
+/// are accessible as read-only from supervisor-mode using `cycle`, `instret`, and `hpmcounterX` CSRs.
+/// The SBI performance monitoring unit (PMU) extension is an interface for supervisor-mode to configure
+/// and use the RISC-V hardware performance counters with assistance from the machine-mode (or hypervisor-mode).
+/// These hardware performance counters can only be started, stopped, or configured from machine-mode
+/// using `mcountinhibit` and `mhpmeventX` CSRs.
+/// Due to this, a machine-mode SBI implementation may choose to disallow SBI PMU extension
 /// if `mcountinhibit` CSR is not implemented by the RISC-V platform.
-/// 
-/// A RISC-V platform generally supports monitoring of various hardware events using a limited number 
-/// of hardware performance counters which are up to 64 bits wide. 
-/// In addition, a SBI implementation can also provide firmware performance counters which can monitor firmware events 
-/// such as number of misaligned load/store instructions, number of RFENCEs, number of IPIs, etc. 
+///
+/// A RISC-V platform generally supports monitoring of various hardware events using a limited number
+/// of hardware performance counters which are up to 64 bits wide.
+/// In addition, a SBI implementation can also provide firmware performance counters which can monitor firmware events
+/// such as number of misaligned load/store instructions, number of RFENCEs, number of IPIs, etc.
 /// The firmware counters are always 64 bits wide.
-/// 
+///
 /// The SBI PMU extension provides:
-/// 
+///
 /// 1. An interface for supervisor-mode software to discover and configure per-HART hardware/firmware counters
 /// 2. A typical perf compatible interface for hardware/firmware performance counters and events
 /// 3. Full access to microarchitecture’s raw event encodings
-/// 
-/// To define SBI PMU extension calls, we first define important entities `counter_idx`, `event_idx`, and `event_data`. 
-/// The `counter_idx` is a logical number assigned to each hardware/firmware counter. 
-/// The `event_idx `represents a hardware (or firmware) event whereas 
-/// the `event_data` is 64 bits wide and represents additional configuration (or parameters) for 
+///
+/// To define SBI PMU extension calls, we first define important entities `counter_idx`, `event_idx`, and `event_data`.
+/// The `counter_idx` is a logical number assigned to each hardware/firmware counter.
+/// The `event_idx `represents a hardware (or firmware) event whereas
+/// the `event_data` is 64 bits wide and represents additional configuration (or parameters) for
 /// a hardware (or firmware) event.
 ///
 /// The event_idx is a 20 bits wide number encoded as follows:
@@ -39,10 +39,10 @@ use alloc::boxed::Box;
 /// ```
 pub trait Pmu: Send {
     /// Returns the number of counters (both hardware and firmware).
-    /// 
+    ///
     /// The value is returned in `SbiRet.value`; this call always returns SBI_SUCCESS in `SbiRet.error`.
     fn num_counters(&self) -> usize;
-    /// Get details about the specified counter such as underlying CSR number, width of the counter, 
+    /// Get details about the specified counter such as underlying CSR number, width of the counter,
     /// type of counter hardware/firmware, etc.
     ///
     /// The `counter_info` returned by this SBI call is encoded as follows:
@@ -60,24 +60,24 @@ pub trait Pmu: Send {
     /// Returns the `counter_info` described above in `SbiRet.value`.
     ///
     /// The possible return error codes returned in `SbiRet.error` are shown in the table below:    
-    /// 
-    /// | Return code             | Description 
+    ///
+    /// | Return code             | Description
     /// |:------------------------|:----------------------------------------------
     /// | SBI_SUCCESS             | `counter_info` read successfully.
     /// | SBI_ERR_INVALID_PARAM   | `counter_idx` points to an invalid counter.
     fn counter_get_info(&self, counter_idx: usize) -> SbiRet;
-    /// Find and configure a counter from a set of counters which is not started (or enabled) 
-    /// and can monitor the specified event. 
-    /// 
+    /// Find and configure a counter from a set of counters which is not started (or enabled)
+    /// and can monitor the specified event.
+    ///
     /// # Parameters
     ///
     /// The `counter_idx_base` and `counter_idx_mask` parameters represent the set of counters,
-    /// whereas the `event_idx` represent the event to be monitored 
+    /// whereas the `event_idx` represent the event to be monitored
     /// and `event_data` represents any additional event configuration.
     ///
-    /// The `config_flags` parameter represent additional counter configuration and filter flags. 
+    /// The `config_flags` parameter represent additional counter configuration and filter flags.
     /// The bit definitions of the `config_flags` parameter are shown in the table below:
-    /// 
+    ///
     /// | Flag Name                    | Bits       | Description
     /// |:-----------------------------|:-----------|:------------
     /// | SBI_PMU_CFG_FLAG_SKIP_MATCH  | 0:0        | Skip the counter matching
@@ -92,22 +92,22 @@ pub trait Pmu: Send {
     ///
     /// *NOTE:* When *SBI_PMU_CFG_FLAG_SKIP_MATCH* is set in `config_flags`, the
     /// SBI implementation will unconditionally select the first counter from the
-    /// set of counters specified by the `counter_idx_base` and `counter_idx_mask`. 
-    /// 
+    /// set of counters specified by the `counter_idx_base` and `counter_idx_mask`.
+    ///
     /// *NOTE:* The *SBI_PMU_CFG_FLAG_AUTO_START* flag in `config_flags` has no
     /// impact on the counter value.    
-    /// 
+    ///
     /// *NOTE:* The `config_flags[3:7]` bits are event filtering hints so these
     /// can be ignored or overridden by the SBI implementation for security concerns
     /// or due to lack of event filtering support in the underlying RISC-V platform.
-    /// 
+    ///
     /// # Return value
-    /// 
+    ///
     /// Returns the `counter_idx` in `sbiret.value` upon success.
-    /// 
+    ///
     /// In case of failure, the possible error codes returned in `sbiret.error` are shown in the table below:    
-    /// 
-    /// | Return code           | Description 
+    ///
+    /// | Return code           | Description
     /// |:----------------------|:----------------------------------------------
     /// | SBI_SUCCESS           | counter found and configured successfully.
     /// | SBI_ERR_INVALID_PARAM | set of counters has an invalid counter.
@@ -118,75 +118,80 @@ pub trait Pmu: Send {
         counter_idx_mask: usize,
         config_flags: usize,
         event_idx: usize,
-        event_data: u64
+        event_data: u64,
     ) -> SbiRet;
-    /// Start or enable a set of counters on the calling HART with the specified initial value. 
+    /// Start or enable a set of counters on the calling HART with the specified initial value.
     ///
     /// # Parameters
-    /// 
+    ///
     /// The `counter_idx_base` and `counter_idx_mask` parameters represent the set of counters.
     /// whereas the `initial_value` parameter specifies the initial value of the counter.
     ///
     /// The bit definitions of the `start_flags` parameter are shown in the table below:
-    /// 
+    ///
     /// | Flag Name                    | Bits       | Description
     /// |:-----------------------------|:-----------|:------------
     /// | SBI_PMU_START_SET_INIT_VALUE | 0:0        | Set the value of counters based on the `initial_value` parameter.
     /// | *RESERVED*                   | 1:(XLEN-1) | All non-zero values are reserved for future use.
     ///
-    /// *NOTE*: When `SBI_PMU_START_SET_INIT_VALUE` is not set in `start_flags`, the counter value will 
+    /// *NOTE*: When `SBI_PMU_START_SET_INIT_VALUE` is not set in `start_flags`, the counter value will
     /// not be modified and event counting will start from current counter value.
-    /// 
+    ///
     /// # Return value
     ///
     /// The possible return error codes returned in `SbiRet.error` are shown in the table below:    
-    /// 
-    /// | Return code             | Description 
+    ///
+    /// | Return code             | Description
     /// |:------------------------|:----------------------------------------------
     /// | SBI_SUCCESS             | counter started successfully.
     /// | SBI_ERR_INVALID_PARAM   | some of the counters specified in parameters are invalid.
     /// | SBI_ERR_ALREADY_STARTED | some of the counters specified in parameters are already started.
     fn counter_start(
-        &self, 
-        counter_idx_base: usize, 
-        counter_idx_mask: usize, 
-        start_flags: usize, 
-        initial_value: u64
+        &self,
+        counter_idx_base: usize,
+        counter_idx_mask: usize,
+        start_flags: usize,
+        initial_value: u64,
     ) -> SbiRet;
-    /// Stop or disable a set of counters on the calling HART. 
+    /// Stop or disable a set of counters on the calling HART.
     ///
     /// # Parameters
-    /// 
-    /// The `counter_idx_base` and `counter_idx_mask` parameters represent the set of counters. 
+    ///
+    /// The `counter_idx_base` and `counter_idx_mask` parameters represent the set of counters.
     /// The bit definitions of the `stop_flags` parameter are shown in the table below:
-    /// 
+    ///
     /// | Flag Name               | Bits       | Description
     /// |:------------------------|:-----------|:------------
     /// | SBI_PMU_STOP_FLAG_RESET | 0:0        | Reset the counter to event mapping.
     /// | *RESERVED*              | 1:(XLEN-1) | All non-zero values are reserved for future use.
-    /// 
+    ///
     /// # Return value
     ///
     /// The possible return error codes returned in `SbiRet.error` are shown in the table below:    
-    /// 
-    /// | Return code             | Description 
+    ///
+    /// | Return code             | Description
     /// |:------------------------|:----------------------------------------------
     /// | SBI_SUCCESS             | counter stopped successfully.
     /// | SBI_ERR_INVALID_PARAM   | some of the counters specified in parameters are invalid.
     /// | SBI_ERR_ALREADY_STOPPED | some of the counters specified in parameters are already stopped.
-    fn counter_stop(&self, counter_idx_base: usize, counter_idx_mask: usize, stop_flags: usize) -> SbiRet;
+    fn counter_stop(
+        &self,
+        counter_idx_base: usize,
+        counter_idx_mask: usize,
+        stop_flags: usize,
+    ) -> SbiRet;
     /// Provide the current value of a firmware counter in `SbiRet.value`.
     ///
     /// # Parameters
-    /// 
+    ///
     /// This function should be only used to read a firmware counter. It will return an error
     /// when user provides a hardware counter in `counter_idx` parameter.
     ///
     /// # Return value
     ///
     /// The possible return error codes returned in `SbiRet.error` are shown in the table below:    
-    /// 
-    /// | Return code             | Description 
+    ///
+    /// | Return code             | Description
     /// |:------------------------|:----------------------------------------------
     /// | SBI_SUCCESS             | firmware counter read successfully.
     /// | SBI_ERR_INVALID_PARAM   | `counter_idx` points to a hardware counter or an invalid counter.
@@ -210,17 +215,17 @@ pub(crate) fn probe_pmu() -> bool {
     PMU.get().is_some()
 }
 
-#[inline] 
+#[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 
+        // Returns the number of counters (both hardware and firmware) in sbiret.value
         // and always returns SBI_SUCCESS in sbiret.error.
         return SbiRet::ok(obj.num_counters());
     }
     SbiRet::not_supported()
 }
 
-#[inline] 
+#[inline]
 pub(crate) fn counter_get_info(counter_idx: usize) -> SbiRet {
     if let Some(obj) = PMU.get() {
         return obj.counter_get_info(counter_idx);
@@ -228,13 +233,13 @@ pub(crate) fn counter_get_info(counter_idx: usize) -> SbiRet {
     SbiRet::not_supported()
 }
 
-#[inline] 
+#[inline]
 pub(crate) fn counter_config_matching(
     counter_idx_base: usize,
     counter_idx_mask: usize,
     config_flags: usize,
     event_idx: usize,
-    event_data: u64
+    event_data: u64,
 ) -> SbiRet {
     if let Some(obj) = PMU.get() {
         return obj.counter_config_matching(
@@ -242,39 +247,43 @@ pub(crate) fn counter_config_matching(
             counter_idx_mask,
             config_flags,
             event_idx,
-            event_data
+            event_data,
         );
     }
     SbiRet::not_supported()
 }
 
-#[inline] 
+#[inline]
 pub(crate) fn counter_start(
-    counter_idx_base: usize, 
-    counter_idx_mask: usize, 
-    start_flags: usize, 
-    initial_value: u64
+    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_base,
             counter_idx_mask,
             start_flags,
-            initial_value
+            initial_value,
         );
     }
     SbiRet::not_supported()
 }
 
-#[inline] 
-pub(crate) fn counter_stop(counter_idx_base: usize, counter_idx_mask: usize, stop_flags: usize) -> SbiRet {
+#[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()
 }
 
-#[inline] 
+#[inline]
 pub(crate) fn counter_fw_read(counter_idx: usize) -> SbiRet {
     if let Some(obj) = PMU.get() {
         return obj.counter_fw_read(counter_idx);

+ 25 - 20
src/reset.rs

@@ -1,36 +1,36 @@
-use alloc::boxed::Box;
-use crate::util::OnceFatBox;
 use crate::ecall::SbiRet;
+use crate::util::OnceFatBox;
+use alloc::boxed::Box;
 
 /// System Reset Extension
 ///
 /// Provides a function that allow the supervisor software to request system-level reboot or shutdown.
-/// 
-/// The term "system" refers to the world-view of supervisor software and the underlying SBI implementation 
+///
+/// The term "system" refers to the world-view of supervisor software and the underlying SBI implementation
 /// could be machine mode firmware or hypervisor.
 ///
 /// Ref: [Section 9, RISC-V Supervisor Binary Interface Specification](https://github.com/riscv-non-isa/riscv-sbi-doc/blob/master/riscv-sbi.adoc#9-system-reset-extension-eid-0x53525354-srst)
 pub trait Reset: Send {
-    /// Reset the system based on provided `reset_type` and `reset_reason`. 
+    /// Reset the system based on provided `reset_type` and `reset_reason`.
     ///
     /// This is a synchronous call and does not return if it succeeds.
     ///
     /// # Warm reboot and cold reboot
-    /// 
-    /// When supervisor software is running natively, the SBI implementation is machine mode firmware. 
-    /// In this case, shutdown is equivalent to physical power down of the entire system and 
-    /// cold reboot is equivalent to physical power cycle of the entire system. Further, warm reboot 
-    /// is equivalent to a power cycle of main processor and parts of the system but not the entire system. 
-    /// 
-    /// For example, on a server class system with a BMC (board management controller), 
+    ///
+    /// When supervisor software is running natively, the SBI implementation is machine mode firmware.
+    /// In this case, shutdown is equivalent to physical power down of the entire system and
+    /// cold reboot is equivalent to physical power cycle of the entire system. Further, warm reboot
+    /// is equivalent to a power cycle of main processor and parts of the system but not the entire system.
+    ///
+    /// For example, on a server class system with a BMC (board management controller),
     /// a warm reboot will not power cycle the BMC whereas a cold reboot will definitely power cycle the BMC.
     ///
-    /// When supervisor software is running inside a virtual machine, the SBI implementation is a hypervisor. 
-    /// The shutdown, cold reboot and warm reboot will behave functionally the same as the native case but might 
+    /// When supervisor software is running inside a virtual machine, the SBI implementation is a hypervisor.
+    /// The shutdown, cold reboot and warm reboot will behave functionally the same as the native case but might
     /// not result in any physical power changes.
     ///
     /// # Return value
-    /// 
+    ///
     /// The possible return error codes returned in `SbiRet.error` are shown in the table below:
     ///
     /// | Error code            | Description
@@ -53,16 +53,21 @@ pub trait Reset: Send {
 
 static RESET: OnceFatBox<dyn Reset + Sync + 'static> = OnceFatBox::new();
 
-#[doc(hidden)] #[allow(unused)]
+#[doc(hidden)]
+#[allow(unused)]
 pub const RESET_TYPE_SHUTDOWN: usize = 0x0000_0000;
-#[doc(hidden)] #[allow(unused)]
+#[doc(hidden)]
+#[allow(unused)]
 pub const RESET_TYPE_COLD_REBOOT: usize = 0x0000_0001;
-#[doc(hidden)] #[allow(unused)]
+#[doc(hidden)]
+#[allow(unused)]
 pub const RESET_TYPE_WARM_REBOOT: usize = 0x0000_0002;
 
-#[doc(hidden)] #[allow(unused)]
+#[doc(hidden)]
+#[allow(unused)]
 pub const RESET_REASON_NO_REASON: usize = 0x0000_0000;
-#[doc(hidden)] #[allow(unused)]
+#[doc(hidden)]
+#[allow(unused)]
 pub const RESET_REASON_SYSTEM_FAILURE: usize = 0x0000_0001;
 
 #[doc(hidden)] // use through a macro

+ 60 - 27
src/rfence.rs

@@ -1,7 +1,7 @@
-use crate::hart_mask::HartMask;
 use crate::ecall::SbiRet;
-use alloc::boxed::Box;
+use crate::hart_mask::HartMask;
 use crate::util::OnceFatBox;
+use alloc::boxed::Box;
 
 /// Remote fence support
 ///
@@ -19,58 +19,70 @@ pub trait Rfence: Send {
     ///
     /// Returns `SBI_SUCCESS` when remote fence was sent to all the targeted harts successfully.
     fn remote_fence_i(&self, hart_mask: HartMask) -> SbiRet;
-    /// Instructs the remote harts to execute one or more `SFENCE.VMA` instructions, 
+    /// Instructs the remote harts to execute one or more `SFENCE.VMA` instructions,
     /// covering the range of virtual addresses between start and size.
-    /// 
+    ///
     /// # Return value
     ///
     /// The possible return error codes returned in `SbiRet.error` are shown in the table below:
     ///
-    /// | Return code               | Description 
+    /// | Return code               | Description
     /// |:--------------------------|:----------------------------------------------
     /// | 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(&self, hart_mask: HartMask, start_addr: usize, size: usize) -> SbiRet;
-    /// Instruct the remote harts to execute one or more `SFENCE.VMA` instructions, 
+    /// 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`.
     ///
     /// # Return value
     ///
     /// The possible return error codes returned in `SbiRet.error` are shown in the table below:
     ///
-    /// | Return code               | Description 
+    /// | Return code               | Description
     /// |:--------------------------|:----------------------------------------------
     /// | 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(&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`. 
-    /// 
+    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`.
+    ///
     /// This function call is only valid for harts implementing hypervisor extension.
     ///
     /// # Return value
     ///
     /// The possible return error codes returned in `SbiRet.error` are shown in the table below:
     ///
-    /// | Return code               | Description 
+    /// | Return code               | Description
     /// |:--------------------------|:----------------------------------------------
     /// | 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(&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()
     }
-    /// Instruct the remote harts to execute one or more `HFENCE.GVMA` instructions, 
+    /// Instruct the remote harts to execute one or more `HFENCE.GVMA` instructions,
     /// covering the range of guest physical addresses between start and size for all the guests.
-    /// 
+    ///
     /// This function call is only valid for harts implementing hypervisor extension.
     ///
     /// # Return value
     ///
     /// The possible return error codes returned in `SbiRet.error` are shown in the table below:
     ///
-    /// | Return code               | Description 
+    /// | Return code               | Description
     /// |:--------------------------|:----------------------------------------------
     /// | 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.
@@ -79,8 +91,8 @@ pub trait Rfence: Send {
         drop((hart_mask, start_addr, size));
         SbiRet::not_supported()
     }
-    /// Instruct the remote harts to execute one or more `HFENCE.VVMA` instructions, 
-    /// covering the range of guest virtual addresses between start and size for the given `ASID` and current `VMID` (in `hgatp` CSR) 
+    /// Instruct the remote harts to execute one or more `HFENCE.VVMA` instructions,
+    /// covering the range of guest virtual addresses between start and size for the given `ASID` and current `VMID` (in `hgatp` CSR)
     /// of calling hart.
     ///  
     /// This function call is only valid for harts implementing hypervisor extension.
@@ -89,18 +101,24 @@ pub trait Rfence: Send {
     ///
     /// The possible return error codes returned in `SbiRet.error` are shown in the table below:
     ///
-    /// | Return code               | Description 
+    /// | Return code               | Description
     /// |:--------------------------|:----------------------------------------------
     /// | 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(&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()
     }
-    /// Instruct the remote harts to execute one or more `HFENCE.VVMA` instructions, 
-    /// covering the range of guest virtual addresses between start and size for current `VMID` (in `hgatp` CSR) 
-    /// of calling hart. 
+    /// Instruct the remote harts to execute one or more `HFENCE.VVMA` instructions,
+    /// covering the range of guest virtual addresses between start and size for current `VMID` (in `hgatp` CSR)
+    /// of calling hart.
     ///
     /// This function call is only valid for harts implementing hypervisor extension.
     ///
@@ -108,7 +126,7 @@ pub trait Rfence: Send {
     ///
     /// The possible return error codes returned in `SbiRet.error` are shown in the table below:
     ///
-    /// | Return code               | Description 
+    /// | Return code               | Description
     /// |:--------------------------|:----------------------------------------------
     /// | 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.
@@ -150,7 +168,12 @@ 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 {
+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 {
@@ -158,7 +181,12 @@ 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 {
+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 {
@@ -174,7 +202,12 @@ 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 {
+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 {

+ 1 - 1
src/timer.rs

@@ -1,5 +1,5 @@
-use alloc::boxed::Box;
 use crate::util::OnceFatBox;
+use alloc::boxed::Box;
 
 /// Timer programmer support
 pub trait Timer: Send {

+ 12 - 12
src/util.rs

@@ -2,14 +2,14 @@
 
 // Ref: once_cell
 
+use alloc::boxed::Box;
 use core::{
-    fmt::{self, Debug}, 
-    marker::PhantomData, 
-    mem::MaybeUninit, 
-    ptr::{self, Pointee}, 
-    sync::atomic::{AtomicPtr, Ordering}
+    fmt::{self, Debug},
+    marker::PhantomData,
+    mem::MaybeUninit,
+    ptr::{self, Pointee},
+    sync::atomic::{AtomicPtr, Ordering},
 };
-use alloc::boxed::Box;
 
 /// A thread-safe fat pointer cell which can be written to only once.
 pub struct OnceFatBox<T: ?Sized> {
@@ -35,9 +35,9 @@ impl<T: ?Sized> Drop for OnceFatBox<T> {
     }
 }
 
-impl<T: ?Sized + Debug> Debug for OnceFatBox<T> 
-where 
-    <T as Pointee>::Metadata: Debug 
+impl<T: ?Sized + Debug> Debug for OnceFatBox<T>
+where
+    <T as Pointee>::Metadata: Debug,
 {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.debug_struct("OnceFatBox")
@@ -50,10 +50,10 @@ where
 impl<T: ?Sized> OnceFatBox<T> {
     /// Creates a new empty cell.
     pub const fn new() -> OnceFatBox<T> {
-        OnceFatBox { 
-            thin_ptr: AtomicPtr::new(ptr::null_mut()), 
+        OnceFatBox {
+            thin_ptr: AtomicPtr::new(ptr::null_mut()),
             meta: MaybeUninit::uninit(), // value meaning ignored when thin_ptr is null
-            _marker: PhantomData 
+            _marker: PhantomData,
         }
     }