Ver código fonte

lib: remove feature sbi_2_0

RustSBI now supports SBI 2.0-rc1 by default
luojia65 2 anos atrás
pai
commit
9cd1e6d8ad
6 arquivos alterados com 247 adições e 524 exclusões
  1. 6 36
      .github/workflows/rust.yml
  2. 1 5
      Cargo.toml
  3. 0 2
      src/ecall/pmu.rs
  4. 238 471
      src/instance.rs
  5. 1 7
      src/lib.rs
  6. 1 3
      src/pmu.rs

+ 6 - 36
.github/workflows/rust.yml

@@ -49,26 +49,16 @@ jobs:
         uses: Swatinem/rust-cache@v2
         with:
           key: ${{ matrix.TARGET }}
-      - name: Check (no default features, SBI 1.0.0)
+      - name: Check (no default features)
         uses: actions-rs/cargo@v1
         with:
           command: check
           args: --target ${{ matrix.TARGET }} --no-default-features --verbose
-      - name: Check (no default features, SBI 2.0-rc1)
-        uses: actions-rs/cargo@v1
-        with:
-          command: check
-          args: --features "sbi_2_0" --target ${{ matrix.TARGET }} --no-default-features --verbose
-      - name: Check (machine, SBI 1.0.0)
+      - name: Check (machine)
         uses: actions-rs/cargo@v1
         with:
           command: check
           args: --target ${{ matrix.TARGET }} --features "machine" --verbose
-      - name: Check (machine, SBI 2.0-rc1)
-        uses: actions-rs/cargo@v1
-        with:
-          command: check
-          args: --features "sbi_2_0" --target ${{ matrix.TARGET }} --features "machine" --verbose
 
   check-nightly:
     name: Cargo check (nightly)
@@ -89,26 +79,16 @@ jobs:
         uses: Swatinem/rust-cache@v2
         with:
           key: ${{ matrix.TARGET }}
-      - name: Check (singleton, SBI 1.0.0)
+      - name: Check (singleton)
         uses: actions-rs/cargo@v1
         with:
           command: check
           args: --features "singleton" --target ${{ matrix.TARGET }} --verbose
-      - name: Check (singleton, SBI 2.0-rc1)
-        uses: actions-rs/cargo@v1
-        with:
-          command: check
-          args: --features "singleton,sbi_2_0" --target ${{ matrix.TARGET }} --verbose
-      - name: Check (legacy, SBI 1.0.0)
+      - name: Check (legacy)
         uses: actions-rs/cargo@v1
         with:
           command: check
           args: --features "legacy" --target ${{ matrix.TARGET }} --verbose
-      - name: Check (legacy, SBI 2.0-rc1)
-        uses: actions-rs/cargo@v1
-        with:
-          command: check
-          args: --features "legacy,sbi_2_0" --target ${{ matrix.TARGET }} --verbose
 
   tests:
     name: Run tests
@@ -128,23 +108,13 @@ jobs:
         uses: actions-rs/cargo@v1
         with:
           command: clippy
-      - name: Run tests (no default features, SBI 1.0.0)
+      - name: Run tests (no default features)
         uses: actions-rs/cargo@v1
         with:
           command: test
           args: --no-default-features --verbose
-      - name: Run tests (no default features, SBI 2.0-rc1)
-        uses: actions-rs/cargo@v1
-        with:
-          command: test
-          args: --features "sbi_2_0" --no-default-features --verbose
-      - name: Run tests (machine, SBI 1.0.0)
+      - name: Run tests (machine)
         uses: actions-rs/cargo@v1
         with:
           command: test
           args: --features "machine" --verbose
-      - name: Run tests (machine, SBI 2.0-rc1)
-        uses: actions-rs/cargo@v1
-        with:
-          command: test
-          args: --features "machine,sbi_2_0" --verbose

+ 1 - 5
Cargo.toml

@@ -1,7 +1,7 @@
 [package]
 name = "rustsbi"
 description = "Minimal RISC-V's SBI implementation library in Rust"
-version = "0.3.2"
+version = "0.4.0-alpha.1"
 authors = [
     "Luo Jia <[email protected]>",
     "Campbell He <[email protected]>",
@@ -21,10 +21,6 @@ riscv = { version = "0.10.1", optional = true }
 
 [features]
 default = ["machine"]
-# Enable RISC-V SBI 2.0-rc1 extensions, i.e. the DBCN extension
-# It will add a generic parameter to RustSBI instance structure.
-# FIXME: remove this feature (and from CI workflow) on rustsbi 0.4.0 and adds this generic parameter permanently onto RustSBI.
-sbi_2_0 = []
 # Run RustSBI on machine mode
 # This feature enables to use RISC-V primitives on current machine mode environment
 # If you are developing a cross-architecture virtual machine, consider disabling this feature

+ 0 - 2
src/ecall/pmu.rs

@@ -21,7 +21,6 @@ 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),
-        #[cfg(feature = "sbi_2_0")]
         PMU_COUNTER_FW_READ_HI => counter_fw_read_hi(param0),
         _ => SbiRet::not_supported(),
     }
@@ -50,7 +49,6 @@ 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),
-        #[cfg(feature = "sbi_2_0")]
         PMU_COUNTER_FW_READ_HI => counter_fw_read_hi(param0),
         _ => SbiRet::not_supported(),
     }

+ 238 - 471
src/instance.rs

@@ -1,9 +1,7 @@
 use crate::{
-    spec::binary::SbiRet, Fence, HartMask, Hsm, Ipi, Pmu, Reset, Timer, IMPL_ID_RUSTSBI,
-    RUSTSBI_VERSION, SBI_SPEC_MAJOR, SBI_SPEC_MINOR,
+    spec::binary::SbiRet, Console, Fence, HartMask, Hsm, Ipi, Physical, Pmu, Reset, Timer,
+    IMPL_ID_RUSTSBI, RUSTSBI_VERSION, SBI_SPEC_MAJOR, SBI_SPEC_MINOR,
 };
-#[cfg(feature = "sbi_2_0")]
-use crate::{Console, Physical};
 use core::convert::Infallible;
 #[cfg(feature = "machine")]
 use riscv::register::{marchid, mimpid, mvendorid};
@@ -13,14 +11,13 @@ use riscv::register::{marchid, mimpid, mvendorid};
 /// By now RustSBI supports to run instance based interface on systems has environment pointer width
 /// that is the same as supervisor pointer width.
 #[derive(Clone, Debug)]
-pub struct RustSBI<T, I, R, H, S, P, #[cfg(feature = "sbi_2_0")] C> {
+pub struct RustSBI<T, I, R, H, S, P, C> {
     timer: Option<T>,
     ipi: Option<I>,
     rfnc: Option<R>,
     hsm: Option<H>,
     srst: Option<S>,
     pmu: Option<P>,
-    #[cfg(feature = "sbi_2_0")]
     dbcn: Option<C>,
     #[cfg(not(feature = "machine"))]
     info: MachineInfo,
@@ -40,310 +37,6 @@ pub struct MachineInfo {
     pub mimpid: usize,
 }
 
-// FIXME: on RustSBI 0.4.0, Console extension will be officially supported without a gate,
-// this macro can be moved back to impl RustSBI<...> code region at that time.
-macro_rules! impl_rustsbi {
-    () => {
-        /// Handle supervisor environment call with given parameters and return the `SbiRet` result.
-        #[inline]
-        #[rustfmt::skip] // fixme: remove in RustSBI 0.4.0
-        pub fn handle_ecall(
-            &mut self,
-            extension: usize,
-            function: usize,
-            param: [usize; 6],
-        ) -> SbiRet {
-            match extension {
-                spec::rfnc::EID_RFNC => {
-                    let Some(rfnc) = &mut self.rfnc else {
-                        return SbiRet::not_supported();
-                    };
-                    let [param0, param1, param2, param3, param4] =
-                        [param[0], param[1], param[2], param[3], param[4]];
-                    let hart_mask = crate::HartMask::from_mask_base(param0, param1);
-                    match function {
-                        spec::rfnc::REMOTE_FENCE_I => rfnc.remote_fence_i(hart_mask),
-                        spec::rfnc::REMOTE_SFENCE_VMA => {
-                            rfnc.remote_sfence_vma(hart_mask, param2, param3)
-                        }
-                        spec::rfnc::REMOTE_SFENCE_VMA_ASID => {
-                            rfnc.remote_sfence_vma_asid(hart_mask, param2, param3, param4)
-                        }
-                        spec::rfnc::REMOTE_HFENCE_GVMA_VMID => {
-                            rfnc.remote_hfence_gvma_vmid(hart_mask, param2, param3, param4)
-                        }
-                        spec::rfnc::REMOTE_HFENCE_GVMA => {
-                            rfnc.remote_hfence_gvma(hart_mask, param2, param3)
-                        }
-                        spec::rfnc::REMOTE_HFENCE_VVMA_ASID => {
-                            rfnc.remote_hfence_vvma_asid(hart_mask, param2, param3, param4)
-                        }
-                        spec::rfnc::REMOTE_HFENCE_VVMA => {
-                            rfnc.remote_hfence_vvma(hart_mask, param2, param3)
-                        }
-                        _ => SbiRet::not_supported(),
-                    }
-                }
-                spec::time::EID_TIME => match () {
-                    #[cfg(target_pointer_width = "64")]
-                    () => {
-                        let Some(timer) = &mut self.timer else {
-                            return SbiRet::not_supported();
-                        };
-                        let [param0] = [param[0]];
-                        match function {
-                            spec::time::SET_TIMER => {
-                                timer.set_timer(param0 as _);
-                                SbiRet::success(0)
-                            }
-                            _ => SbiRet::not_supported(),
-                        }
-                    }
-                    #[cfg(target_pointer_width = "32")]
-                    () => {
-                        let Some(timer) = &mut self.timer else {
-                            return SbiRet::not_supported();
-                        };
-                        let [param0, param1] = [param[0], param[1]];
-                        match function {
-                            spec::time::SET_TIMER => {
-                                timer.set_timer(concat_u32(param1, param0));
-                                SbiRet::success(0)
-                            }
-                            _ => SbiRet::not_supported(),
-                        }
-                    }
-                },
-                spec::spi::EID_SPI => {
-                    let Some(ipi) = &mut self.ipi else {
-                        return SbiRet::not_supported();
-                    };
-                    let [param0, param1] = [param[0], param[1]];
-                    match function {
-                        spec::spi::SEND_IPI => {
-                            ipi.send_ipi(HartMask::from_mask_base(param0, param1))
-                        }
-                        _ => SbiRet::not_supported(),
-                    }
-                }
-                spec::base::EID_BASE => {
-                    let [param0] = [param[0]];
-                    let value = match function {
-                        spec::base::GET_SBI_SPEC_VERSION => {
-                            (SBI_SPEC_MAJOR << 24) | (SBI_SPEC_MINOR)
-                        }
-                        spec::base::GET_SBI_IMPL_ID => IMPL_ID_RUSTSBI,
-                        spec::base::GET_SBI_IMPL_VERSION => RUSTSBI_VERSION,
-                        spec::base::PROBE_EXTENSION => {
-                            // only provides probes to standard extensions. If you have customized extensions to be probed,
-                            // run it even before this `handle_ecall` function.
-                            self.probe_extension(param0)
-                        }
-                        spec::base::GET_MVENDORID => match () {
-                            #[cfg(feature = "machine")]
-                            () => mvendorid::read().map(|r| r.bits()).unwrap_or(0),
-                            #[cfg(not(feature = "machine"))]
-                            () => self.info.mvendorid,
-                        },
-                        spec::base::GET_MARCHID => match () {
-                            #[cfg(feature = "machine")]
-                            () => marchid::read().map(|r| r.bits()).unwrap_or(0),
-                            #[cfg(not(feature = "machine"))]
-                            () => self.info.marchid,
-                        },
-                        spec::base::GET_MIMPID => match () {
-                            #[cfg(feature = "machine")]
-                            () => mimpid::read().map(|r| r.bits()).unwrap_or(0),
-                            #[cfg(not(feature = "machine"))]
-                            () => self.info.mimpid,
-                        },
-                        _ => return SbiRet::not_supported(),
-                    };
-                    SbiRet::success(value)
-                }
-                spec::hsm::EID_HSM => {
-                    let Some(hsm) = &mut self.hsm else {
-                        return SbiRet::not_supported();
-                    };
-                    let [param0, param1, param2] = [param[0], param[1], param[2]];
-                    match function {
-                        spec::hsm::HART_START => hsm.hart_start(param0, param1, param2),
-                        spec::hsm::HART_STOP => hsm.hart_stop(),
-                        spec::hsm::HART_GET_STATUS => hsm.hart_get_status(param0),
-                        spec::hsm::HART_SUSPEND => {
-                            if let Ok(suspend_type) = u32::try_from(param0) {
-                                hsm.hart_suspend(suspend_type, param1, param2)
-                            } else {
-                                SbiRet::invalid_param()
-                            }
-                        }
-                        _ => SbiRet::not_supported(),
-                    }
-                }
-                spec::srst::EID_SRST => {
-                    let Some(srst) = &mut self.srst else {
-                        return SbiRet::not_supported();
-                    };
-                    let [param0, param1] = [param[0], param[1]];
-                    match function {
-                        spec::srst::SYSTEM_RESET => {
-                            match (u32::try_from(param0), u32::try_from(param1)) {
-                                (Ok(reset_type), Ok(reset_reason)) => {
-                                    srst.system_reset(reset_type, reset_reason)
-                                }
-                                (_, _) => SbiRet::invalid_param(),
-                            }
-                        }
-                        _ => SbiRet::not_supported(),
-                    }
-                }
-                spec::pmu::EID_PMU => match () {
-                    #[cfg(target_pointer_width = "64")]
-                    () => {
-                        let Some(pmu) = &mut self.pmu else {
-                            return SbiRet::not_supported();
-                        };
-                        let [param0, param1, param2, param3, param4] =
-                            [param[0], param[1], param[2], param[3], param[4]];
-                        match function {
-                            spec::pmu::PMU_NUM_COUNTERS => SbiRet::success(pmu.num_counters()),
-                            spec::pmu::PMU_COUNTER_GET_INFO => pmu.counter_get_info(param0),
-                            spec::pmu::PMU_COUNTER_CONFIG_MATCHING => pmu.counter_config_matching(
-                                param0,
-                                param1,
-                                param2,
-                                param3,
-                                param4 as _,
-                            ),
-                            spec::pmu::PMU_COUNTER_START => {
-                                pmu.counter_start(param0, param1, param2, param3 as _)
-                            }
-                            spec::pmu::PMU_COUNTER_STOP => pmu.counter_stop(param0, param1, param2),
-                            spec::pmu::PMU_COUNTER_FW_READ => pmu.counter_fw_read(param0),
-                            #[cfg(feature = "sbi_2_0")]
-                            spec::pmu::PMU_COUNTER_FW_READ_HI => pmu.counter_fw_read(param0),
-                            _ => SbiRet::not_supported(),
-                        }
-                    }
-                    #[cfg(target_pointer_width = "32")]
-                    () => {
-                        let Some(pmu) = &mut self.pmu else {
-                            return SbiRet::not_supported();
-                        };
-                        let [param0, param1, param2, param3, param4, param5] =
-                            [param[0], param[1], param[2], param[3], param[4], param[5]];
-                        match function {
-                            spec::pmu::PMU_NUM_COUNTERS => SbiRet::success(pmu.num_counters()),
-                            spec::pmu::PMU_COUNTER_GET_INFO => pmu.counter_get_info(param0),
-                            spec::pmu::PMU_COUNTER_CONFIG_MATCHING => pmu.counter_config_matching(
-                                param0,
-                                param1,
-                                param2,
-                                param3,
-                                concat_u32(param5, param4),
-                            ),
-                            spec::pmu::PMU_COUNTER_START => pmu.counter_start(
-                                param0,
-                                param1,
-                                param2,
-                                concat_u32(param4, param3),
-                            ),
-                            spec::pmu::PMU_COUNTER_STOP => pmu.counter_stop(param0, param1, param2),
-                            spec::pmu::PMU_COUNTER_FW_READ => pmu.counter_fw_read(param0),
-                            #[cfg(feature = "sbi_2_0")]
-                            spec::pmu::PMU_COUNTER_FW_READ_HI => pmu.counter_fw_read(param0),
-                            _ => SbiRet::not_supported(),
-                        }
-                    }
-                },
-                #[cfg(feature = "sbi_2_0")]
-                spec::dbcn::EID_DBCN => {
-                    let Some(dbcn) = &mut self.dbcn else {
-                        return SbiRet::not_supported();
-                    };
-                    let [param0, param1, param2] = [param[0], param[1], param[2]];
-                    match function {
-                        spec::dbcn::CONSOLE_WRITE => {
-                            let bytes = Physical::new(param0, param1, param2);
-                            dbcn.write(bytes)
-                        }
-                        spec::dbcn::CONSOLE_READ => {
-                            let bytes = Physical::new(param0, param1, param2);
-                            dbcn.read(bytes)
-                        }
-                        spec::dbcn::CONSOLE_WRITE_BYTE => dbcn.write_byte((param0 & 0xFF) as u8),
-                        _ => SbiRet::not_supported(),
-                    }
-                }
-                _ => SbiRet::not_supported(),
-            }
-        }
-
-        #[inline]
-        fn probe_extension(&self, extension: usize) -> usize {
-            let ans = match extension {
-                spec::base::EID_BASE => true,
-                spec::time::EID_TIME => self.timer.is_some(),
-                spec::spi::EID_SPI => self.ipi.is_some(),
-                spec::rfnc::EID_RFNC => self.rfnc.is_some(),
-                spec::srst::EID_SRST => self.srst.is_some(),
-                spec::hsm::EID_HSM => self.hsm.is_some(),
-                spec::pmu::EID_PMU => self.pmu.is_some(),
-                #[cfg(feature = "sbi_2_0")]
-                spec::dbcn::EID_DBCN => self.dbcn.is_some(),
-                _ => false,
-            };
-            if ans {
-                spec::base::UNAVAILABLE_EXTENSION.wrapping_add(1)
-            } else {
-                spec::base::UNAVAILABLE_EXTENSION
-            }
-        }
-    };
-}
-
-#[cfg(not(feature = "sbi_2_0"))]
-impl<T: Timer, I: Ipi, R: Fence, H: Hsm, S: Reset, P: Pmu> RustSBI<T, I, R, H, S, P> {
-    /// Create RustSBI instance on current machine environment for all the SBI extensions
-    #[cfg(feature = "machine")]
-    #[inline]
-    pub const fn new_machine(timer: T, ipi: I, rfnc: R, hsm: H, srst: S, pmu: P) -> Self {
-        Self {
-            timer: Some(timer),
-            ipi: Some(ipi),
-            rfnc: Some(rfnc),
-            hsm: Some(hsm),
-            srst: Some(srst),
-            pmu: Some(pmu),
-        }
-    }
-
-    /// Create RustSBI instance on given machine information for all the SBI extensions
-    #[cfg(not(feature = "machine"))]
-    #[inline]
-    pub const fn with_machine_info(
-        timer: T,
-        ipi: I,
-        rfnc: R,
-        hsm: H,
-        srst: S,
-        pmu: P,
-        info: MachineInfo,
-    ) -> Self {
-        Self {
-            timer: Some(timer),
-            ipi: Some(ipi),
-            rfnc: Some(rfnc),
-            hsm: Some(hsm),
-            srst: Some(srst),
-            pmu: Some(pmu),
-            info,
-        }
-    }
-    impl_rustsbi! {}
-}
-
-#[cfg(feature = "sbi_2_0")]
 impl<T: Timer, I: Ipi, R: Fence, H: Hsm, S: Reset, P: Pmu, C: Console>
     RustSBI<T, I, R, H, S, P, C>
 {
@@ -386,7 +79,240 @@ impl<T: Timer, I: Ipi, R: Fence, H: Hsm, S: Reset, P: Pmu, C: Console>
             info,
         }
     }
-    impl_rustsbi! {}
+    /// Handle supervisor environment call with given parameters and return the `SbiRet` result.
+    #[inline]
+    pub fn handle_ecall(&mut self, extension: usize, function: usize, param: [usize; 6]) -> SbiRet {
+        match extension {
+            spec::rfnc::EID_RFNC => {
+                let Some(rfnc) = &mut self.rfnc else {
+                    return SbiRet::not_supported();
+                };
+                let [param0, param1, param2, param3, param4] =
+                    [param[0], param[1], param[2], param[3], param[4]];
+                let hart_mask = crate::HartMask::from_mask_base(param0, param1);
+                match function {
+                    spec::rfnc::REMOTE_FENCE_I => rfnc.remote_fence_i(hart_mask),
+                    spec::rfnc::REMOTE_SFENCE_VMA => {
+                        rfnc.remote_sfence_vma(hart_mask, param2, param3)
+                    }
+                    spec::rfnc::REMOTE_SFENCE_VMA_ASID => {
+                        rfnc.remote_sfence_vma_asid(hart_mask, param2, param3, param4)
+                    }
+                    spec::rfnc::REMOTE_HFENCE_GVMA_VMID => {
+                        rfnc.remote_hfence_gvma_vmid(hart_mask, param2, param3, param4)
+                    }
+                    spec::rfnc::REMOTE_HFENCE_GVMA => {
+                        rfnc.remote_hfence_gvma(hart_mask, param2, param3)
+                    }
+                    spec::rfnc::REMOTE_HFENCE_VVMA_ASID => {
+                        rfnc.remote_hfence_vvma_asid(hart_mask, param2, param3, param4)
+                    }
+                    spec::rfnc::REMOTE_HFENCE_VVMA => {
+                        rfnc.remote_hfence_vvma(hart_mask, param2, param3)
+                    }
+                    _ => SbiRet::not_supported(),
+                }
+            }
+            spec::time::EID_TIME => match () {
+                #[cfg(target_pointer_width = "64")]
+                () => {
+                    let Some(timer) = &mut self.timer else {
+                        return SbiRet::not_supported();
+                    };
+                    let [param0] = [param[0]];
+                    match function {
+                        spec::time::SET_TIMER => {
+                            timer.set_timer(param0 as _);
+                            SbiRet::success(0)
+                        }
+                        _ => SbiRet::not_supported(),
+                    }
+                }
+                #[cfg(target_pointer_width = "32")]
+                () => {
+                    let Some(timer) = &mut self.timer else {
+                        return SbiRet::not_supported();
+                    };
+                    let [param0, param1] = [param[0], param[1]];
+                    match function {
+                        spec::time::SET_TIMER => {
+                            timer.set_timer(concat_u32(param1, param0));
+                            SbiRet::success(0)
+                        }
+                        _ => SbiRet::not_supported(),
+                    }
+                }
+            },
+            spec::spi::EID_SPI => {
+                let Some(ipi) = &mut self.ipi else {
+                    return SbiRet::not_supported();
+                };
+                let [param0, param1] = [param[0], param[1]];
+                match function {
+                    spec::spi::SEND_IPI => ipi.send_ipi(HartMask::from_mask_base(param0, param1)),
+                    _ => SbiRet::not_supported(),
+                }
+            }
+            spec::base::EID_BASE => {
+                let [param0] = [param[0]];
+                let value = match function {
+                    spec::base::GET_SBI_SPEC_VERSION => (SBI_SPEC_MAJOR << 24) | (SBI_SPEC_MINOR),
+                    spec::base::GET_SBI_IMPL_ID => IMPL_ID_RUSTSBI,
+                    spec::base::GET_SBI_IMPL_VERSION => RUSTSBI_VERSION,
+                    spec::base::PROBE_EXTENSION => {
+                        // only provides probes to standard extensions. If you have customized extensions to be probed,
+                        // run it even before this `handle_ecall` function.
+                        self.probe_extension(param0)
+                    }
+                    spec::base::GET_MVENDORID => match () {
+                        #[cfg(feature = "machine")]
+                        () => mvendorid::read().map(|r| r.bits()).unwrap_or(0),
+                        #[cfg(not(feature = "machine"))]
+                        () => self.info.mvendorid,
+                    },
+                    spec::base::GET_MARCHID => match () {
+                        #[cfg(feature = "machine")]
+                        () => marchid::read().map(|r| r.bits()).unwrap_or(0),
+                        #[cfg(not(feature = "machine"))]
+                        () => self.info.marchid,
+                    },
+                    spec::base::GET_MIMPID => match () {
+                        #[cfg(feature = "machine")]
+                        () => mimpid::read().map(|r| r.bits()).unwrap_or(0),
+                        #[cfg(not(feature = "machine"))]
+                        () => self.info.mimpid,
+                    },
+                    _ => return SbiRet::not_supported(),
+                };
+                SbiRet::success(value)
+            }
+            spec::hsm::EID_HSM => {
+                let Some(hsm) = &mut self.hsm else {
+                    return SbiRet::not_supported();
+                };
+                let [param0, param1, param2] = [param[0], param[1], param[2]];
+                match function {
+                    spec::hsm::HART_START => hsm.hart_start(param0, param1, param2),
+                    spec::hsm::HART_STOP => hsm.hart_stop(),
+                    spec::hsm::HART_GET_STATUS => hsm.hart_get_status(param0),
+                    spec::hsm::HART_SUSPEND => {
+                        if let Ok(suspend_type) = u32::try_from(param0) {
+                            hsm.hart_suspend(suspend_type, param1, param2)
+                        } else {
+                            SbiRet::invalid_param()
+                        }
+                    }
+                    _ => SbiRet::not_supported(),
+                }
+            }
+            spec::srst::EID_SRST => {
+                let Some(srst) = &mut self.srst else {
+                    return SbiRet::not_supported();
+                };
+                let [param0, param1] = [param[0], param[1]];
+                match function {
+                    spec::srst::SYSTEM_RESET => {
+                        match (u32::try_from(param0), u32::try_from(param1)) {
+                            (Ok(reset_type), Ok(reset_reason)) => {
+                                srst.system_reset(reset_type, reset_reason)
+                            }
+                            (_, _) => SbiRet::invalid_param(),
+                        }
+                    }
+                    _ => SbiRet::not_supported(),
+                }
+            }
+            spec::pmu::EID_PMU => match () {
+                #[cfg(target_pointer_width = "64")]
+                () => {
+                    let Some(pmu) = &mut self.pmu else {
+                        return SbiRet::not_supported();
+                    };
+                    let [param0, param1, param2, param3, param4] =
+                        [param[0], param[1], param[2], param[3], param[4]];
+                    match function {
+                        spec::pmu::PMU_NUM_COUNTERS => SbiRet::success(pmu.num_counters()),
+                        spec::pmu::PMU_COUNTER_GET_INFO => pmu.counter_get_info(param0),
+                        spec::pmu::PMU_COUNTER_CONFIG_MATCHING => {
+                            pmu.counter_config_matching(param0, param1, param2, param3, param4 as _)
+                        }
+                        spec::pmu::PMU_COUNTER_START => {
+                            pmu.counter_start(param0, param1, param2, param3 as _)
+                        }
+                        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(),
+                    }
+                }
+                #[cfg(target_pointer_width = "32")]
+                () => {
+                    let Some(pmu) = &mut self.pmu else {
+                        return SbiRet::not_supported();
+                    };
+                    let [param0, param1, param2, param3, param4, param5] =
+                        [param[0], param[1], param[2], param[3], param[4], param[5]];
+                    match function {
+                        spec::pmu::PMU_NUM_COUNTERS => SbiRet::success(pmu.num_counters()),
+                        spec::pmu::PMU_COUNTER_GET_INFO => pmu.counter_get_info(param0),
+                        spec::pmu::PMU_COUNTER_CONFIG_MATCHING => pmu.counter_config_matching(
+                            param0,
+                            param1,
+                            param2,
+                            param3,
+                            concat_u32(param5, param4),
+                        ),
+                        spec::pmu::PMU_COUNTER_START => {
+                            pmu.counter_start(param0, param1, param2, concat_u32(param4, param3))
+                        }
+                        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(),
+                    }
+                }
+            },
+            spec::dbcn::EID_DBCN => {
+                let Some(dbcn) = &mut self.dbcn else {
+                    return SbiRet::not_supported();
+                };
+                let [param0, param1, param2] = [param[0], param[1], param[2]];
+                match function {
+                    spec::dbcn::CONSOLE_WRITE => {
+                        let bytes = Physical::new(param0, param1, param2);
+                        dbcn.write(bytes)
+                    }
+                    spec::dbcn::CONSOLE_READ => {
+                        let bytes = Physical::new(param0, param1, param2);
+                        dbcn.read(bytes)
+                    }
+                    spec::dbcn::CONSOLE_WRITE_BYTE => dbcn.write_byte((param0 & 0xFF) as u8),
+                    _ => SbiRet::not_supported(),
+                }
+            }
+            _ => SbiRet::not_supported(),
+        }
+    }
+
+    #[inline]
+    fn probe_extension(&self, extension: usize) -> usize {
+        let ans = match extension {
+            spec::base::EID_BASE => true,
+            spec::time::EID_TIME => self.timer.is_some(),
+            spec::spi::EID_SPI => self.ipi.is_some(),
+            spec::rfnc::EID_RFNC => self.rfnc.is_some(),
+            spec::srst::EID_SRST => self.srst.is_some(),
+            spec::hsm::EID_HSM => self.hsm.is_some(),
+            spec::pmu::EID_PMU => self.pmu.is_some(),
+            spec::dbcn::EID_DBCN => self.dbcn.is_some(),
+            _ => false,
+        };
+        if ans {
+            spec::base::UNAVAILABLE_EXTENSION.wrapping_add(1)
+        } else {
+            spec::base::UNAVAILABLE_EXTENSION
+        }
+    }
 }
 
 #[cfg(target_pointer_width = "32")]
@@ -396,54 +322,10 @@ const fn concat_u32(h: usize, l: usize) -> u64 {
 }
 
 /// Structure to build a RustSBI instance
-// FIXME: remove #[cfg(feature = "sbi_2_0")] once RustSBI hits 0.4.0
-pub struct Builder<T, I, R, H, S, P, #[cfg(feature = "sbi_2_0")] C> {
-    #[cfg(not(feature = "sbi_2_0"))]
-    inner: RustSBI<T, I, R, H, S, P>,
-    #[cfg(feature = "sbi_2_0")]
+pub struct Builder<T, I, R, H, S, P, C> {
     inner: RustSBI<T, I, R, H, S, P, C>,
 }
 
-#[cfg(not(feature = "sbi_2_0"))]
-impl Builder<Infallible, Infallible, Infallible, Infallible, Infallible, Infallible> {
-    /// Create a new `Builder` from current machine environment
-    #[inline]
-    #[cfg(feature = "machine")]
-    pub const fn new_machine(
-    ) -> Builder<Infallible, Infallible, Infallible, Infallible, Infallible, Infallible> {
-        Builder {
-            inner: RustSBI {
-                timer: None,
-                ipi: None,
-                rfnc: None,
-                hsm: None,
-                srst: None,
-                pmu: None,
-            },
-        }
-    }
-
-    /// Create a new `Builder` from machine information
-    #[inline]
-    #[cfg(not(feature = "machine"))]
-    pub const fn with_machine_info(
-        info: MachineInfo,
-    ) -> Builder<Infallible, Infallible, Infallible, Infallible, Infallible, Infallible> {
-        Builder {
-            inner: RustSBI {
-                timer: None,
-                ipi: None,
-                rfnc: None,
-                hsm: None,
-                srst: None,
-                pmu: None,
-                info,
-            },
-        }
-    }
-}
-
-#[cfg(feature = "sbi_2_0")]
 impl Builder<Infallible, Infallible, Infallible, Infallible, Infallible, Infallible, Infallible> {
     /// Create a new `Builder` from current machine environment
     #[inline]
@@ -492,119 +374,6 @@ impl Builder<Infallible, Infallible, Infallible, Infallible, Infallible, Infalli
 
 // fixme: struct `Infallible` should be replaced to never type once it's stablized
 
-// fixme: remove feature sbi_2_0 once RustSBI hits 0.4.0
-#[cfg(not(feature = "sbi_2_0"))]
-impl<T, I, R, H, S, P> Builder<T, I, R, H, S, P> {
-    /// Add Timer programmer extension to RustSBI
-    #[inline]
-    pub fn with_timer<T2: Timer>(self, timer: T2) -> Builder<T2, I, R, H, S, P> {
-        Builder {
-            inner: RustSBI {
-                timer: Some(timer),
-                ipi: self.inner.ipi,
-                rfnc: self.inner.rfnc,
-                hsm: self.inner.hsm,
-                srst: self.inner.srst,
-                pmu: self.inner.pmu,
-                #[cfg(not(feature = "machine"))]
-                info: self.inner.info,
-            },
-        }
-    }
-
-    /// Add Inter-processor Interrupt extension to RustSBI
-    #[inline]
-    pub fn with_ipi<I2: Ipi>(self, ipi: I2) -> Builder<T, I2, R, H, S, P> {
-        Builder {
-            inner: RustSBI {
-                timer: self.inner.timer,
-                ipi: Some(ipi),
-                rfnc: self.inner.rfnc,
-                hsm: self.inner.hsm,
-                srst: self.inner.srst,
-                pmu: self.inner.pmu,
-                #[cfg(not(feature = "machine"))]
-                info: self.inner.info,
-            },
-        }
-    }
-
-    /// Add Remote Fence extension to RustSBI
-    #[inline]
-    pub fn with_fence<R2: Fence>(self, fence: R2) -> Builder<T, I, R2, H, S, P> {
-        Builder {
-            inner: RustSBI {
-                timer: self.inner.timer,
-                ipi: self.inner.ipi,
-                rfnc: Some(fence),
-                hsm: self.inner.hsm,
-                srst: self.inner.srst,
-                pmu: self.inner.pmu,
-                #[cfg(not(feature = "machine"))]
-                info: self.inner.info,
-            },
-        }
-    }
-
-    /// Add Hart State Monitor extension to RustSBI
-    #[inline]
-    pub fn with_hsm<H2: Hsm>(self, hsm: H2) -> Builder<T, I, R, H2, S, P> {
-        Builder {
-            inner: RustSBI {
-                timer: self.inner.timer,
-                ipi: self.inner.ipi,
-                rfnc: self.inner.rfnc,
-                hsm: Some(hsm),
-                srst: self.inner.srst,
-                pmu: self.inner.pmu,
-                #[cfg(not(feature = "machine"))]
-                info: self.inner.info,
-            },
-        }
-    }
-
-    /// Add System Reset extension to RustSBI
-    #[inline]
-    pub fn with_reset<S2: Reset>(self, reset: S2) -> Builder<T, I, R, H, S2, P> {
-        Builder {
-            inner: RustSBI {
-                timer: self.inner.timer,
-                ipi: self.inner.ipi,
-                rfnc: self.inner.rfnc,
-                hsm: self.inner.hsm,
-                srst: Some(reset),
-                pmu: self.inner.pmu,
-                #[cfg(not(feature = "machine"))]
-                info: self.inner.info,
-            },
-        }
-    }
-
-    /// Add Performance Monitor Unit extension to RustSBI
-    #[inline]
-    pub fn with_pmu<P2: Pmu>(self, pmu: P2) -> Builder<T, I, R, H, S, P2> {
-        Builder {
-            inner: RustSBI {
-                timer: self.inner.timer,
-                ipi: self.inner.ipi,
-                rfnc: self.inner.rfnc,
-                hsm: self.inner.hsm,
-                srst: self.inner.srst,
-                pmu: Some(pmu),
-                #[cfg(not(feature = "machine"))]
-                info: self.inner.info,
-            },
-        }
-    }
-
-    /// Build the target RustSBI instance
-    #[inline]
-    pub fn build(self) -> RustSBI<T, I, R, H, S, P> {
-        self.inner
-    }
-}
-
-#[cfg(feature = "sbi_2_0")]
 impl<T, I, R, H, S, P, C> Builder<T, I, R, H, S, P, C> {
     /// Add Timer programmer extension to RustSBI
     #[inline]
@@ -837,13 +606,11 @@ impl Pmu for Infallible {
         unreachable!()
     }
 
-    #[cfg(feature = "sbi_2_0")]
     fn counter_fw_read_hi(&self, _: usize) -> SbiRet {
         unreachable!()
     }
 }
 
-#[cfg(feature = "sbi_2_0")]
 impl Console for Infallible {
     fn write(&self, _: crate::Physical<&[u8]>) -> SbiRet {
         unreachable!()

+ 1 - 7
src/lib.rs

@@ -171,7 +171,6 @@
 //!     ctx: SupervisorContext,
 //!     /* other environment variables ... */
 //! # #[cfg(not(feature = "legacy"))]
-//! # #[cfg(not(feature = "sbi_2_0"))] // fixme: remove in 0.4.0
 //!     sbi: RustSBI<Clint, Clint, MyPlatRfnc, MyPlatHsm, MyBoardPower, MyPlatPmu>,
 //!     /* custom_1: CustomSBI<...> */
 //! }
@@ -573,12 +572,7 @@ pub const LOGO: &str = r".______       __    __      _______.___________.  _____
 | _| `._____| \______/ |_______/       |__|  |_______/    |______/ |__|";
 
 // RustSBI supports RISC-V SBI specification 2.0-rc1
-const SBI_SPEC_MAJOR: usize = match () {
-    #[cfg(feature = "sbi_2_0")]
-    () => 2,
-    #[cfg(not(feature = "sbi_2_0"))]
-    () => 1,
-};
+const SBI_SPEC_MAJOR: usize = 2;
 const SBI_SPEC_MINOR: usize = 0;
 
 /// RustSBI implementation ID: 4

+ 1 - 3
src/pmu.rs

@@ -209,7 +209,6 @@ 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.
-    #[cfg(feature = "sbi_2_0")]
     fn counter_fw_read_hi(&self, counter_idx: usize) -> SbiRet {
         match () {
             #[cfg(not(target_pointer_width = "32"))]
@@ -282,7 +281,6 @@ impl<T: Pmu> Pmu for &T {
     fn counter_fw_read(&self, counter_idx: usize) -> SbiRet {
         T::counter_fw_read(self, counter_idx)
     }
-    #[cfg(feature = "sbi_2_0")]
     #[inline]
     fn counter_fw_read_hi(&self, counter_idx: usize) -> SbiRet {
         T::counter_fw_read_hi(self, counter_idx)
@@ -391,7 +389,7 @@ pub(crate) fn counter_fw_read(counter_idx: usize) -> SbiRet {
     SbiRet::not_supported()
 }
 
-#[cfg(all(feature = "singleton", feature = "sbi_2_0"))]
+#[cfg(feature = "singleton")]
 #[inline]
 pub(crate) fn counter_fw_read_hi(counter_idx: usize) -> SbiRet {
     if let Some(obj) = PMU.get() {