Kaynağa Gözat

macros: derive RISC-V extensions depend on field names

We can derive for fence, hsm, ipi, reset and timer for now.

Signed-off-by: Zhouqi Jiang <[email protected]>
Zhouqi Jiang 1 yıl önce
ebeveyn
işleme
e3a61bbf72
7 değiştirilmiş dosya ile 486 ekleme ve 143 silme
  1. 6 1
      Cargo.toml
  2. 35 0
      examples/derive.rs
  3. 13 0
      macros/Cargo.toml
  4. 118 0
      macros/src/lib.rs
  5. 0 138
      src/instance.rs
  6. 15 4
      src/lib.rs
  7. 299 0
      src/traits.rs

+ 6 - 1
Cargo.toml

@@ -19,9 +19,11 @@ exclude = ["/.github"]
 [dependencies]
 sbi-spec = "0.0.7-alpha.2"
 riscv = { version = "0.10.1", optional = true }
+rustsbi-macros = { path = "macros" }
+static_assertions = "1.1.0"
 
 [features]
-default = []
+default = ["machine"]
 # 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
@@ -34,4 +36,7 @@ targets = [
     "riscv32imac-unknown-none-elf", "riscv64imac-unknown-none-elf",
 ]
 
+[workspace]
+members = ["macros"]
+
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

+ 35 - 0
examples/derive.rs

@@ -0,0 +1,35 @@
+use rustsbi::{HartMask, RustSBI};
+use sbi_spec::binary::SbiRet;
+
+#[derive(RustSBI)]
+struct MySBI {
+    fence: MyFence,
+}
+
+struct MyFence;
+
+impl rustsbi::Fence for MyFence {
+    fn remote_fence_i(&self, _: HartMask) -> SbiRet {
+        println!("remote fence i");
+        SbiRet::success(0)
+    }
+
+    fn remote_sfence_vma(&self, _: HartMask, _: usize, _: usize) -> SbiRet {
+        todo!()
+    }
+
+    fn remote_sfence_vma_asid(&self, _: HartMask, _: usize, _: usize, _: usize) -> SbiRet {
+        todo!()
+    }
+}
+
+fn main() {
+    let sbi = MySBI { fence: MyFence };
+    sbi.handle_ecall(sbi_spec::rfnc::EID_RFNC, 0, [0; 6]);
+    let spec_version = sbi.handle_ecall(
+        sbi_spec::base::EID_BASE,
+        sbi_spec::base::GET_SBI_SPEC_VERSION,
+        [0; 6],
+    );
+    println!("spec version: {:x?}", spec_version.value);
+}

+ 13 - 0
macros/Cargo.toml

@@ -0,0 +1,13 @@
+[package]
+name = "rustsbi-macros"
+version = "0.1.0"
+edition = "2021"
+
+[lib]
+proc-macro = true
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+quote = "1.0.33"
+syn = "2.0.39"

+ 118 - 0
macros/src/lib.rs

@@ -0,0 +1,118 @@
+use proc_macro::TokenStream;
+use quote::quote;
+use syn::{parse_macro_input, punctuated::Punctuated, Data, DeriveInput, Fields, Ident};
+
+#[derive(Default)]
+struct RustSBIImp {
+    fence: Option<Ident>,
+    hsm: Option<Ident>,
+    ipi: Option<Ident>,
+    reset: Option<Ident>,
+    timer: Option<Ident>,
+}
+
+/// Implement RustSBI trait for structure of each extensions.
+#[proc_macro_derive(RustSBI, attributes(rustsbi))]
+pub fn derive_rustsbi(input: TokenStream) -> TokenStream {
+    let input = parse_macro_input!(input as DeriveInput);
+
+    let Data::Struct(strukt) = input.data else {
+        panic!("#[derive(RustSBI)] must be used on structs");
+    };
+
+    let fields = match strukt.fields {
+        Fields::Named(f) => f.named,
+        Fields::Unnamed(f) => f.unnamed,
+        Fields::Unit => Punctuated::new(),
+    };
+
+    let mut imp = RustSBIImp::default();
+    for field in fields {
+        if let Some(name) = &field.ident {
+            match name.to_string().as_str() {
+                "rfnc" | "fence" => imp.fence = Some(name.clone()),
+                "hsm" => imp.hsm = Some(name.clone()),
+                "spi" | "ipi" => imp.ipi = Some(name.clone()),
+                "srst" | "reset" => imp.reset = Some(name.clone()),
+                "timer" => imp.timer = Some(name.clone()),
+                _ => {}
+            }
+        }
+    }
+
+    let mut ans = TokenStream::new();
+    ans.extend(impl_derive_rustsbi(&input.ident, &imp));
+    ans
+}
+
+fn impl_derive_rustsbi(name: &Ident, imp: &RustSBIImp) -> TokenStream {
+    let base_probe: usize = 1;
+    let fence_probe: usize = if imp.fence.is_some() { 1 } else { 0 };
+    let hsm_probe: usize = if imp.hsm.is_some() { 1 } else { 0 };
+    let ipi_probe: usize = if imp.ipi.is_some() { 1 } else { 0 };
+    let reset_probe: usize = if imp.reset.is_some() { 1 } else { 0 };
+    let timer_probe: usize = if imp.timer.is_some() { 1 } else { 0 };
+    let base_procedure = quote! {
+        ::rustsbi::spec::base::EID_BASE => ::rustsbi::_rustsbi_base_machine(param, function,
+            ::rustsbi::_StandardExtensionProbe {
+                base: #base_probe,
+                fence: #fence_probe,
+                hsm: #hsm_probe,
+                ipi: #ipi_probe,
+                reset: #reset_probe,
+                timer: #timer_probe,
+            }),
+    };
+    let fence_procedure = if let Some(fence) = &imp.fence {
+        quote! {
+            ::rustsbi::spec::rfnc::EID_RFNC => ::rustsbi::_rustsbi_fence(&self.#fence, param, function),
+        }
+    } else {
+        quote! {}
+    };
+    let hsm_procedure = if let Some(hsm) = &imp.hsm {
+        quote! {
+            ::rustsbi::spec::hsm::EID_HSM => ::rustsbi::_rustsbi_hsm(&self.#hsm, param, function),
+        }
+    } else {
+        quote! {}
+    };
+    let ipi_procedure = if let Some(ipi) = &imp.ipi {
+        quote! {
+            ::rustsbi::spec::spi::EID_SPI => ::rustsbi::_rustsbi_ipi(&self.#ipi, param, function),
+        }
+    } else {
+        quote! {}
+    };
+    let reset_procedure = if let Some(reset) = &imp.reset {
+        quote! {
+            ::rustsbi::spec::srst::EID_SRST => ::rustsbi::_rustsbi_reset(&self.#reset, param, function),
+        }
+    } else {
+        quote! {}
+    };
+    let timer_procedure = if let Some(timer) = &imp.timer {
+        quote! {
+            ::rustsbi::spec::timer::EID_TIMER => ::rustsbi::_rustsbi_timer(&self.#timer, param, function),
+        }
+    } else {
+        quote! {}
+    };
+    let gen = quote! {
+    impl rustsbi::RustSBI for #name {
+        #[inline]
+        fn handle_ecall(&self, extension: usize, function: usize, param: [usize; 6]) -> ::rustsbi::spec::binary::SbiRet {
+            match extension {
+                #fence_procedure
+                #base_procedure
+                #hsm_procedure
+                #ipi_procedure
+                #reset_procedure
+                #timer_procedure
+                _ => SbiRet::not_supported(),
+            }
+        }
+    }
+        };
+    gen.into()
+}

+ 0 - 138
src/instance.rs

@@ -704,141 +704,3 @@ impl<T, I, R, H, S, P, C, SU, CP> Builder<T, I, R, H, S, P, C, SU, CP> {
         self.inner
     }
 }
-
-// Placeholder for a structure that implements all RustSBI traits but is never accessed
-
-// fixme: Should be replaced to never type `!` once it's stablized
-// https://github.com/rust-lang/rust/issues/35121
-
-// fixme: should be replaced to impl SomeTrait for ! once never type is stablized
-
-impl Timer for Infallible {
-    fn set_timer(&self, _: u64) {
-        unreachable!()
-    }
-}
-
-impl Ipi for Infallible {
-    fn send_ipi(&self, _: HartMask) -> SbiRet {
-        unreachable!()
-    }
-}
-
-impl Fence for Infallible {
-    fn remote_fence_i(&self, _: HartMask) -> SbiRet {
-        unreachable!()
-    }
-
-    fn remote_sfence_vma(&self, _: HartMask, _: usize, _: usize) -> SbiRet {
-        unreachable!()
-    }
-
-    fn remote_sfence_vma_asid(&self, _: HartMask, _: usize, _: usize, _: usize) -> SbiRet {
-        unreachable!()
-    }
-
-    fn remote_hfence_gvma_vmid(&self, _: HartMask, _: usize, _: usize, _: usize) -> SbiRet {
-        unreachable!()
-    }
-
-    fn remote_hfence_gvma(&self, _: HartMask, _: usize, _: usize) -> SbiRet {
-        unreachable!()
-    }
-
-    fn remote_hfence_vvma_asid(&self, _: HartMask, _: usize, _: usize, _: usize) -> SbiRet {
-        unreachable!()
-    }
-
-    fn remote_hfence_vvma(&self, _: HartMask, _: usize, _: usize) -> SbiRet {
-        unreachable!()
-    }
-}
-
-impl Hsm for Infallible {
-    fn hart_start(&self, _: usize, _: usize, _: usize) -> SbiRet {
-        unreachable!()
-    }
-
-    fn hart_stop(&self) -> SbiRet {
-        unreachable!()
-    }
-
-    fn hart_get_status(&self, _: usize) -> SbiRet {
-        unreachable!()
-    }
-
-    fn hart_suspend(&self, _: u32, _: usize, _: usize) -> SbiRet {
-        unreachable!()
-    }
-}
-
-impl Reset for Infallible {
-    fn system_reset(&self, _: u32, _: u32) -> SbiRet {
-        unreachable!()
-    }
-}
-
-impl Pmu for Infallible {
-    fn num_counters(&self) -> usize {
-        unreachable!()
-    }
-
-    fn counter_get_info(&self, _: usize) -> SbiRet {
-        unreachable!()
-    }
-
-    fn counter_config_matching(&self, _: usize, _: usize, _: usize, _: usize, _: u64) -> SbiRet {
-        unreachable!()
-    }
-
-    fn counter_start(&self, _: usize, _: usize, _: usize, _: u64) -> SbiRet {
-        unreachable!()
-    }
-
-    fn counter_stop(&self, _: usize, _: usize, _: usize) -> SbiRet {
-        unreachable!()
-    }
-
-    fn counter_fw_read(&self, _: usize) -> SbiRet {
-        unreachable!()
-    }
-
-    fn counter_fw_read_hi(&self, _: usize) -> SbiRet {
-        unreachable!()
-    }
-}
-
-impl Console for Infallible {
-    fn write(&self, _: Physical<&[u8]>) -> SbiRet {
-        unreachable!()
-    }
-
-    fn read(&self, _: Physical<&mut [u8]>) -> SbiRet {
-        unreachable!()
-    }
-
-    fn write_byte(&self, _: u8) -> SbiRet {
-        unreachable!()
-    }
-}
-
-impl Susp for Infallible {
-    fn system_suspend(&self, _: u32, _: usize, _: usize) -> SbiRet {
-        unreachable!()
-    }
-}
-
-impl Cppc for Infallible {
-    fn probe(&self, _: u32) -> SbiRet {
-        unreachable!()
-    }
-    fn read(&self, _: u32) -> SbiRet {
-        unreachable!()
-    }
-    fn read_hi(&self, _: u32) -> SbiRet {
-        unreachable!()
-    }
-    fn write(&self, _: u32, _: u64) -> SbiRet {
-        unreachable!()
-    }
-}

+ 15 - 4
src/lib.rs

@@ -508,7 +508,7 @@ mod console;
 mod cppc;
 mod hart_mask;
 mod hsm;
-mod instance;
+// mod instance;
 mod ipi;
 mod nacl;
 mod pmu;
@@ -517,6 +517,7 @@ mod rfence;
 mod sta;
 mod susp;
 mod timer;
+mod traits;
 
 /// The RustSBI logo without blank lines on the beginning
 pub const LOGO: &str = r".______       __    __      _______.___________.  _______..______   __
@@ -545,11 +546,13 @@ const RUSTSBI_VERSION: usize =
 pub const VERSION: &str = env!("CARGO_PKG_VERSION");
 
 pub extern crate sbi_spec as spec;
+pub use rustsbi_macros::RustSBI;
+
 pub use console::Console;
 pub use cppc::Cppc;
 pub use hart_mask::HartMask;
 pub use hsm::Hsm;
-pub use instance::{Builder, RustSBI};
+// pub use instance::{Builder, RustSBI};
 pub use ipi::Ipi;
 pub use nacl::Nacl;
 pub use pmu::Pmu;
@@ -558,6 +561,14 @@ pub use rfence::Rfence as Fence;
 pub use sta::Sta;
 pub use susp::Susp;
 pub use timer::Timer;
+pub use traits::RustSBI;
+
+// macro internal functions and structures
+#[doc(hidden)]
+pub use traits::{
+    _StandardExtensionProbe, _rustsbi_base_machine, _rustsbi_fence, _rustsbi_hsm, _rustsbi_ipi,
+    _rustsbi_srst, _rustsbi_timer,
+};
 
-#[cfg(not(feature = "machine"))]
-pub use instance::MachineInfo;
+// #[cfg(not(feature = "machine"))]
+// pub use instance::MachineInfo;

+ 299 - 0
src/traits.rs

@@ -0,0 +1,299 @@
+use core::convert::Infallible;
+
+use crate::HartMask;
+use riscv::register::{marchid, mimpid, mvendorid};
+use spec::binary::{Physical, SbiRet};
+
+/// RustSBI trait including standard extensions.
+pub trait RustSBI {
+    /// Handle supervisor environment call with given parameters and return the `SbiRet` result.
+    fn handle_ecall(&self, extension: usize, function: usize, param: [usize; 6]) -> SbiRet;
+}
+
+/* macro internal structures and functions */
+
+#[doc(hidden)]
+pub struct _StandardExtensionProbe {
+    pub base: usize,
+    pub fence: usize,
+    pub timer: usize,
+    pub ipi: usize,
+    pub hsm: usize,
+    pub reset: usize,
+}
+
+#[doc(hidden)]
+#[inline(always)]
+pub fn _rustsbi_base_machine(
+    param: [usize; 6],
+    function: usize,
+    probe: _StandardExtensionProbe,
+) -> SbiRet {
+    let [param0] = [param[0]];
+    let value = match function {
+        spec::base::GET_SBI_SPEC_VERSION => (crate::SBI_SPEC_MAJOR << 24) | (crate::SBI_SPEC_MINOR),
+        spec::base::GET_SBI_IMPL_ID => crate::IMPL_ID_RUSTSBI,
+        spec::base::GET_SBI_IMPL_VERSION => crate::RUSTSBI_VERSION,
+        spec::base::PROBE_EXTENSION => {
+            // only provides probes to standard extensions. If you have customized extensions to be probed,
+            // run it even before this `handle_ecall` function.
+            probe_extension(param0, probe)
+        }
+        spec::base::GET_MVENDORID => mvendorid::read().map(|r| r.bits()).unwrap_or(0),
+        spec::base::GET_MARCHID => marchid::read().map(|r| r.bits()).unwrap_or(0),
+        spec::base::GET_MIMPID => mimpid::read().map(|r| r.bits()).unwrap_or(0),
+        _ => return SbiRet::not_supported(),
+    };
+    SbiRet::success(value)
+}
+
+#[inline(always)]
+fn probe_extension(extension: usize, probe: _StandardExtensionProbe) -> usize {
+    match extension {
+        spec::base::EID_BASE => probe.base,
+        spec::time::EID_TIME => probe.timer,
+        spec::spi::EID_SPI => probe.ipi,
+        spec::rfnc::EID_RFNC => probe.fence,
+        spec::srst::EID_SRST => probe.reset,
+        spec::hsm::EID_HSM => probe.hsm,
+        // spec::pmu::EID_PMU => self.pmu.is_some(),
+        // spec::dbcn::EID_DBCN => self.dbcn.is_some(),
+        // spec::susp::EID_SUSP => self.susp.is_some(),
+        // spec::cppc::EID_CPPC => self.cppc.is_some(),
+        _ => spec::base::UNAVAILABLE_EXTENSION,
+    }
+}
+
+#[doc(hidden)]
+#[inline(always)]
+pub fn _rustsbi_fence<T: crate::Fence>(fence: T, param: [usize; 6], function: usize) -> SbiRet {
+    let [param0, param1, param2, param3, param4] =
+        [param[0], param[1], param[2], param[3], param[4]];
+    let hart_mask = HartMask::from_mask_base(param0, param1);
+    match function {
+        spec::rfnc::REMOTE_FENCE_I => fence.remote_fence_i(hart_mask),
+        spec::rfnc::REMOTE_SFENCE_VMA => fence.remote_sfence_vma(hart_mask, param2, param3),
+        spec::rfnc::REMOTE_SFENCE_VMA_ASID => {
+            fence.remote_sfence_vma_asid(hart_mask, param2, param3, param4)
+        }
+        spec::rfnc::REMOTE_HFENCE_GVMA_VMID => {
+            fence.remote_hfence_gvma_vmid(hart_mask, param2, param3, param4)
+        }
+        spec::rfnc::REMOTE_HFENCE_GVMA => fence.remote_hfence_gvma(hart_mask, param2, param3),
+        spec::rfnc::REMOTE_HFENCE_VVMA_ASID => {
+            fence.remote_hfence_vvma_asid(hart_mask, param2, param3, param4)
+        }
+        spec::rfnc::REMOTE_HFENCE_VVMA => fence.remote_hfence_vvma(hart_mask, param2, param3),
+        _ => SbiRet::not_supported(),
+    }
+}
+
+#[doc(hidden)]
+#[inline(always)]
+pub fn _rustsbi_timer<T: crate::Timer>(timer: T, param: [usize; 6], function: usize) -> SbiRet {
+    match () {
+        #[cfg(target_pointer_width = "64")]
+        () => {
+            let [param0] = [param[0]];
+            match function {
+                spec::time::SET_TIMER => {
+                    timer.set_timer(param0 as _);
+                    SbiRet::success(0)
+                }
+                _ => SbiRet::not_supported(),
+            }
+        }
+        #[cfg(target_pointer_width = "32")]
+        () => {
+            let [param0, param1] = [param[0], param[1]];
+            match function {
+                spec::time::SET_TIMER => {
+                    timer.set_timer(concat_u32(param1, param0));
+                    SbiRet::success(0)
+                }
+                _ => SbiRet::not_supported(),
+            }
+        }
+    }
+}
+
+#[doc(hidden)]
+#[inline(always)]
+pub fn _rustsbi_ipi<T: crate::Ipi>(ipi: T, param: [usize; 6], function: usize) -> SbiRet {
+    let [param0, param1] = [param[0], param[1]];
+    match function {
+        spec::spi::SEND_IPI => ipi.send_ipi(HartMask::from_mask_base(param0, param1)),
+        _ => SbiRet::not_supported(),
+    }
+}
+
+#[doc(hidden)]
+#[inline(always)]
+pub fn _rustsbi_hsm<T: crate::Hsm>(hsm: T, param: [usize; 6], function: usize) -> SbiRet {
+    let [param0, param1, param2] = [param[0], param[1], param[2]];
+    match function {
+        spec::hsm::HART_START => hsm.hart_start(param0, param1, param2),
+        spec::hsm::HART_STOP => hsm.hart_stop(),
+        spec::hsm::HART_GET_STATUS => hsm.hart_get_status(param0),
+        spec::hsm::HART_SUSPEND => {
+            if let Ok(suspend_type) = u32::try_from(param0) {
+                hsm.hart_suspend(suspend_type, param1, param2)
+            } else {
+                SbiRet::invalid_param()
+            }
+        }
+        _ => SbiRet::not_supported(),
+    }
+}
+
+#[doc(hidden)]
+#[inline(always)]
+pub fn _rustsbi_srst<T: crate::Reset>(reset: T, param: [usize; 6], function: usize) -> SbiRet {
+    let [param0, param1] = [param[0], param[1]];
+    match function {
+        spec::srst::SYSTEM_RESET => match (u32::try_from(param0), u32::try_from(param1)) {
+            (Ok(reset_type), Ok(reset_reason)) => reset.system_reset(reset_type, reset_reason),
+            (_, _) => SbiRet::invalid_param(),
+        },
+        _ => SbiRet::not_supported(),
+    }
+}
+
+// Placeholder for a structure that implements all RustSBI traits but is never accessed
+
+// fixme: Should be replaced to never type `!` once it's stablized
+// https://github.com/rust-lang/rust/issues/35121
+
+// fixme: should be replaced to impl SomeTrait for ! once never type is stablized
+
+impl crate::Timer for Infallible {
+    fn set_timer(&self, _: u64) {
+        unreachable!()
+    }
+}
+
+impl crate::Ipi for Infallible {
+    fn send_ipi(&self, _: HartMask) -> SbiRet {
+        unreachable!()
+    }
+}
+
+impl crate::Fence for Infallible {
+    #[inline]
+    fn remote_fence_i(&self, _: HartMask) -> SbiRet {
+        unreachable!()
+    }
+    #[inline]
+    fn remote_sfence_vma(&self, _: HartMask, _: usize, _: usize) -> SbiRet {
+        unreachable!()
+    }
+    #[inline]
+    fn remote_sfence_vma_asid(&self, _: HartMask, _: usize, _: usize, _: usize) -> SbiRet {
+        unreachable!()
+    }
+    #[inline]
+    fn remote_hfence_gvma_vmid(&self, _: HartMask, _: usize, _: usize, _: usize) -> SbiRet {
+        unreachable!()
+    }
+    #[inline]
+    fn remote_hfence_gvma(&self, _: HartMask, _: usize, _: usize) -> SbiRet {
+        unreachable!()
+    }
+    #[inline]
+    fn remote_hfence_vvma_asid(&self, _: HartMask, _: usize, _: usize, _: usize) -> SbiRet {
+        unreachable!()
+    }
+    #[inline]
+    fn remote_hfence_vvma(&self, _: HartMask, _: usize, _: usize) -> SbiRet {
+        unreachable!()
+    }
+}
+
+impl crate::Hsm for Infallible {
+    fn hart_start(&self, _: usize, _: usize, _: usize) -> SbiRet {
+        unreachable!()
+    }
+
+    fn hart_stop(&self) -> SbiRet {
+        unreachable!()
+    }
+
+    fn hart_get_status(&self, _: usize) -> SbiRet {
+        unreachable!()
+    }
+
+    fn hart_suspend(&self, _: u32, _: usize, _: usize) -> SbiRet {
+        unreachable!()
+    }
+}
+
+impl crate::Reset for Infallible {
+    fn system_reset(&self, _: u32, _: u32) -> SbiRet {
+        unreachable!()
+    }
+}
+
+impl crate::Pmu for Infallible {
+    fn num_counters(&self) -> usize {
+        unreachable!()
+    }
+
+    fn counter_get_info(&self, _: usize) -> SbiRet {
+        unreachable!()
+    }
+
+    fn counter_config_matching(&self, _: usize, _: usize, _: usize, _: usize, _: u64) -> SbiRet {
+        unreachable!()
+    }
+
+    fn counter_start(&self, _: usize, _: usize, _: usize, _: u64) -> SbiRet {
+        unreachable!()
+    }
+
+    fn counter_stop(&self, _: usize, _: usize, _: usize) -> SbiRet {
+        unreachable!()
+    }
+
+    fn counter_fw_read(&self, _: usize) -> SbiRet {
+        unreachable!()
+    }
+
+    fn counter_fw_read_hi(&self, _: usize) -> SbiRet {
+        unreachable!()
+    }
+}
+
+impl crate::Console for Infallible {
+    fn write(&self, _: Physical<&[u8]>) -> SbiRet {
+        unreachable!()
+    }
+
+    fn read(&self, _: Physical<&mut [u8]>) -> SbiRet {
+        unreachable!()
+    }
+
+    fn write_byte(&self, _: u8) -> SbiRet {
+        unreachable!()
+    }
+}
+
+impl crate::Susp for Infallible {
+    fn system_suspend(&self, _: u32, _: usize, _: usize) -> SbiRet {
+        unreachable!()
+    }
+}
+
+impl crate::Cppc for Infallible {
+    fn probe(&self, _: u32) -> SbiRet {
+        unreachable!()
+    }
+    fn read(&self, _: u32) -> SbiRet {
+        unreachable!()
+    }
+    fn read_hi(&self, _: u32) -> SbiRet {
+        unreachable!()
+    }
+    fn write(&self, _: u32, _: u64) -> SbiRet {
+        unreachable!()
+    }
+}