Browse Source

pmu: counter_fw_read_hi function in SBI 2.0-rc1

Bump RISC-V SBI specification version to 2.0-rc.1
luojia65 2 years ago
parent
commit
5afed45bbd
7 changed files with 58 additions and 3 deletions
  1. 4 0
      CHANGELOG.md
  2. 1 1
      Cargo.toml
  3. 1 1
      README.md
  4. 2 0
      src/ecall/pmu.rs
  5. 6 0
      src/instance.rs
  6. 2 1
      src/lib.rs
  7. 42 0
      src/pmu.rs

+ 4 - 0
CHANGELOG.md

@@ -7,8 +7,12 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
 
 ## Unreleased
 
+Bump RISC-V SBI specification version to 2.0-rc1.
+
 ### Added
 
+- pmu: counter_fw_read_hi function in SBI 2.0-rc1
+
 ### Modified
 
 ### Removed

+ 1 - 1
Cargo.toml

@@ -16,7 +16,7 @@ categories = ["os", "embedded", "hardware-support", "no-std"]
 edition = "2021"
 
 [dependencies]
-sbi-spec = "0.0.4"
+sbi-spec = "0.0.5-rc.2"
 riscv = { version = "0.10.1", optional = true }
 
 [features]

+ 1 - 1
README.md

@@ -51,7 +51,7 @@ in `riscv` dependency crate or RustSBI library itself.
 
 - Feature rich and extensible operating system runtime
 - Empower support, compatibility for machines, hypervisors and emulators
-- Support to and develop with RISC-V SBI specification v1.0.0 ratified
+- Support to and develop with RISC-V SBI specification v2.0-rc1
 - Written in Rust, builds under stable Rust
 - Capable to develop with other firmware ecosystem projects
 - Adapted for operating system kernel models on your choice

+ 2 - 0
src/ecall/pmu.rs

@@ -21,6 +21,7 @@ pub fn handle_ecall(
         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(),
     }
 }
@@ -48,6 +49,7 @@ pub fn handle_ecall(
         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(),
     }
 }

+ 6 - 0
src/instance.rs

@@ -236,6 +236,7 @@ impl<T: Timer, I: Ipi, R: Fence, H: Hsm, S: Reset, P: Pmu> RustSBI<T, I, R, H, S
                         }
                         spec::pmu::PMU_COUNTER_STOP => pmu.counter_stop(param0, param1, param2),
                         spec::pmu::PMU_COUNTER_FW_READ => pmu.counter_fw_read(param0),
+                        spec::pmu::PMU_COUNTER_FW_READ_HI => pmu.counter_fw_read(param0),
                         _ => SbiRet::not_supported(),
                     }
                 }
@@ -261,6 +262,7 @@ impl<T: Timer, I: Ipi, R: Fence, H: Hsm, S: Reset, P: Pmu> RustSBI<T, I, R, H, S
                         }
                         spec::pmu::PMU_COUNTER_STOP => pmu.counter_stop(param0, param1, param2),
                         spec::pmu::PMU_COUNTER_FW_READ => pmu.counter_fw_read(param0),
+                        spec::pmu::PMU_COUNTER_FW_READ_HI => pmu.counter_fw_read(param0),
                         _ => SbiRet::not_supported(),
                     }
                 }
@@ -552,4 +554,8 @@ impl Pmu for Infallible {
     fn counter_fw_read(&self, _: usize) -> SbiRet {
         unreachable!()
     }
+
+    fn counter_fw_read_hi(&self, _: usize) -> SbiRet {
+        unreachable!()
+    }
 }

+ 2 - 1
src/lib.rs

@@ -569,7 +569,8 @@ pub const LOGO: &str = r".______       __    __      _______.___________.  _____
 |  |\  \----.|  `--'  |.----)   |      |  |  .----)   |   |  |_)  ||  |
 | _| `._____| \______/ |_______/       |__|  |_______/    |______/ |__|";
 
-const SBI_SPEC_MAJOR: usize = 1;
+// RustSBI supports RISC-V SBI specification 2.0-rc1
+const SBI_SPEC_MAJOR: usize = 2;
 const SBI_SPEC_MINOR: usize = 0;
 
 /// RustSBI implementation ID: 4

+ 42 - 0
src/pmu.rs

@@ -180,6 +180,9 @@ pub trait Pmu: Send + Sync {
     ) -> SbiRet;
     /// Provide the current value of a firmware counter in `SbiRet.value`.
     ///
+    /// On RV32 systems, the `SbiRet.value` will only contain the lower 32 bits of the current
+    /// firmware counter value.
+    ///
     /// # Parameters
     ///
     /// This function should be only used to read a firmware counter. It will return an error
@@ -194,6 +197,32 @@ pub trait Pmu: Send + Sync {
     /// | `SbiRet::success()`       | firmware counter read successfully.
     /// | `SbiRet::invalid_param()` | `counter_idx` points to a hardware counter or an invalid counter.
     fn counter_fw_read(&self, counter_idx: usize) -> SbiRet;
+    /// Provide the upper 32 bits of the current firmware counter value in `SbiRet.value`.
+    ///
+    /// This function always returns zero in `SbiRet.value` for RV64 (or higher) systems.
+    ///
+    /// # Return value
+    ///
+    /// The possible return error codes returned in `SbiRet.error` are shown in the table below:
+    ///
+    /// | Return code               | Description
+    /// |:--------------------------|:----------------------------------------------
+    /// | `SbiRet::success()`       | firmware counter read successfully.
+    /// | `SbiRet::invalid_param()` | `counter_idx` points to a hardware counter or an invalid counter.
+    fn counter_fw_read_hi(&self, counter_idx: usize) -> SbiRet {
+        match () {
+            #[cfg(not(target_pointer_width = "32"))]
+            () => {
+                drop(counter_idx);
+                SbiRet::success(0)
+            }
+            #[cfg(target_pointer_width = "32")]
+            () => {
+                drop(counter_idx);
+                SbiRet::not_supported()
+            }
+        }
+    }
 }
 
 impl<T: Pmu> Pmu for &T {
@@ -252,6 +281,10 @@ impl<T: Pmu> Pmu for &T {
     fn counter_fw_read(&self, counter_idx: usize) -> SbiRet {
         T::counter_fw_read(self, counter_idx)
     }
+    #[inline]
+    fn counter_fw_read_hi(&self, counter_idx: usize) -> SbiRet {
+        T::counter_fw_read_hi(self, counter_idx)
+    }
 }
 
 #[cfg(feature = "singleton")]
@@ -355,3 +388,12 @@ pub(crate) fn counter_fw_read(counter_idx: usize) -> SbiRet {
     }
     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()
+}