Ver código fonte

feat: forward extensions to current environment by `Forward` struct

Signed-off-by: Zhouqi Jiang <[email protected]>
Zhouqi Jiang 1 ano atrás
pai
commit
1bc30b35a3
4 arquivos alterados com 603 adições e 1 exclusões
  1. 1 0
      CHANGELOG.md
  2. 8 1
      Cargo.toml
  3. 590 0
      src/forward.rs
  4. 4 0
      src/lib.rs

+ 1 - 0
CHANGELOG.md

@@ -16,6 +16,7 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
 - support NACL and STA extensions
 - macro based `#[derive(RustSBI)]` interface
 - `into_inner` function for `HartMask`
+- forward extensions to current environment by `Forward` struct
 
 ### Modified
 

+ 8 - 1
Cargo.toml

@@ -19,16 +19,23 @@ exclude = ["/.github"]
 [dependencies]
 sbi-spec = "0.0.7-alpha.3"
 riscv = { version = "0.10.1", optional = true }
+# TODO change to version number once sbi-rt releases a new version
+sbi-rt = { git = "https://github.com/rustsbi/sbi-rt", features = ["integer-impls"], optional = true }
 rustsbi-macros = { version = "0.4.0-alpha.1", path = "macros" }
 static_assertions = "1.1.0"
 
 [features]
 default = []
-# Run RustSBI on machine mode
+# 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
 # to customize environment variables for RISC-V architecture like mvendorid, mimpid, etc.
 machine = ["rustsbi-macros/machine", "dep:riscv"]
+# Enables the struct `Forward`.
+# Struct `Forward` uses current SBI environment to implement the RustSBI environment.
+# This feature is only usable when current software runs on another SBI environment,
+# e.g. hypervisors for RISC-V architecture.
+forward = ["dep:sbi-rt"]
 
 [package.metadata.docs.rs]
 default-target = "riscv64imac-unknown-none-elf"

+ 590 - 0
src/forward.rs

@@ -0,0 +1,590 @@
+use crate::{Console, Cppc, EnvInfo, Fence, Hsm, Ipi, Nacl, Pmu, Reset, Sta, Susp, Timer};
+use sbi_spec::{
+    binary::{HartMask, Physical, SbiRet, SharedPtr},
+    nacl::shmem_size::NATIVE,
+};
+
+/// Forwards SBI calls onto current supervisor environment.
+///
+/// If crate feature `forward` is enabled, this structure implements all RustSBI extensions
+/// by forwarding the calls into current supervisor environment. This is done by `sbi-rt`
+/// crate; thus `Forward` is only available when it's running in RISC-V SBI environments.
+///
+/// `Forward` implements all RustSBI traits, but is only effective if `#[cfg(feature = "forward")]`
+/// is enabled. Otherwise, struct `Forward` is `unimplemented!()` on SBI calls.
+///
+/// # Examples
+///
+/// This structure can be used as a structure field in `#[derive(RustSBI)]`, with helper
+/// macro `#[rustsbi(extension_1, extension_2, ...)]` annotating what extensions should be
+/// forwarded to `sbi-rt` in the structure.
+///
+/// ```rust
+/// use rustsbi::{Forward, RustSBI};
+///
+/// // Forwards fence, timer and console extensions, but the hsm extension
+/// // is still handled by the `hsm` field variable.
+/// #[derive(RustSBI)]
+/// struct VmSBI {
+///     hsm: VmHsm,
+///     #[rustsbi(fence, timer, console, info)]
+///     forward: Forward,
+/// }
+///
+/// # use sbi_spec::binary::SbiRet;
+/// # struct VmHsm;
+/// # impl rustsbi::Hsm for VmHsm {
+/// #     fn hart_start(&self, _: usize, _: usize, _: usize) -> SbiRet { unimplemented!() }
+/// #     fn hart_stop(&self) -> SbiRet { unimplemented!() }
+/// #     fn hart_get_status(&self, _: usize) -> SbiRet { unimplemented!() }
+/// # }
+/// ```
+#[derive(Debug, Clone)]
+pub struct Forward;
+
+impl Console for Forward {
+    #[inline]
+    fn write(&self, bytes: Physical<&[u8]>) -> SbiRet {
+        match () {
+            #[cfg(feature = "forward")]
+            () => sbi_rt::console_write(bytes),
+            #[cfg(not(feature = "forward"))]
+            () => {
+                let _ = bytes;
+                unimplemented!()
+            }
+        }
+    }
+
+    #[inline]
+    fn read(&self, bytes: Physical<&mut [u8]>) -> SbiRet {
+        match () {
+            #[cfg(feature = "forward")]
+            () => sbi_rt::console_read(bytes),
+            #[cfg(not(feature = "forward"))]
+            () => {
+                let _ = bytes;
+                unimplemented!()
+            }
+        }
+    }
+
+    #[inline]
+    fn write_byte(&self, byte: u8) -> SbiRet {
+        match () {
+            #[cfg(feature = "forward")]
+            () => sbi_rt::console_write_byte(byte),
+            #[cfg(not(feature = "forward"))]
+            () => {
+                let _ = byte;
+                unimplemented!()
+            }
+        }
+    }
+}
+
+impl Cppc for Forward {
+    #[inline]
+    fn probe(&self, reg_id: u32) -> SbiRet {
+        match () {
+            #[cfg(feature = "forward")]
+            () => sbi_rt::cppc_probe(reg_id),
+            #[cfg(not(feature = "forward"))]
+            () => {
+                let _ = reg_id;
+                unimplemented!()
+            }
+        }
+    }
+
+    #[inline]
+    fn read(&self, reg_id: u32) -> SbiRet {
+        match () {
+            #[cfg(feature = "forward")]
+            () => sbi_rt::cppc_read(reg_id),
+            #[cfg(not(feature = "forward"))]
+            () => {
+                let _ = reg_id;
+                unimplemented!()
+            }
+        }
+    }
+
+    #[inline]
+    fn read_hi(&self, reg_id: u32) -> SbiRet {
+        match () {
+            #[cfg(feature = "forward")]
+            () => sbi_rt::cppc_read_hi(reg_id),
+            #[cfg(not(feature = "forward"))]
+            () => {
+                let _ = reg_id;
+                unimplemented!()
+            }
+        }
+    }
+
+    #[inline]
+    fn write(&self, reg_id: u32, val: u64) -> SbiRet {
+        match () {
+            #[cfg(feature = "forward")]
+            () => sbi_rt::cppc_write(reg_id, val),
+            #[cfg(not(feature = "forward"))]
+            () => {
+                let _ = (reg_id, val);
+                unimplemented!()
+            }
+        }
+    }
+}
+
+impl Fence for Forward {
+    #[inline]
+    fn remote_fence_i(&self, hart_mask: HartMask) -> SbiRet {
+        match () {
+            #[cfg(feature = "forward")]
+            () => sbi_rt::remote_fence_i(hart_mask),
+            #[cfg(not(feature = "forward"))]
+            () => {
+                let _ = hart_mask;
+                unimplemented!()
+            }
+        }
+    }
+
+    #[inline]
+    fn remote_sfence_vma(&self, hart_mask: HartMask, start_addr: usize, size: usize) -> SbiRet {
+        match () {
+            #[cfg(feature = "forward")]
+            () => sbi_rt::remote_sfence_vma(hart_mask, start_addr, size),
+            #[cfg(not(feature = "forward"))]
+            () => {
+                let _ = (hart_mask, start_addr, size);
+                unimplemented!()
+            }
+        }
+    }
+
+    #[inline]
+    fn remote_sfence_vma_asid(
+        &self,
+        hart_mask: HartMask,
+        start_addr: usize,
+        size: usize,
+        asid: usize,
+    ) -> SbiRet {
+        match () {
+            #[cfg(feature = "forward")]
+            () => sbi_rt::remote_sfence_vma_asid(hart_mask, start_addr, size, asid),
+            #[cfg(not(feature = "forward"))]
+            () => {
+                let _ = (hart_mask, start_addr, size, asid);
+                unimplemented!()
+            }
+        }
+    }
+
+    #[inline]
+    fn remote_hfence_gvma_vmid(
+        &self,
+        hart_mask: HartMask,
+        start_addr: usize,
+        size: usize,
+        vmid: usize,
+    ) -> SbiRet {
+        match () {
+            #[cfg(feature = "forward")]
+            () => sbi_rt::remote_hfence_gvma_vmid(hart_mask, start_addr, size, vmid),
+            #[cfg(not(feature = "forward"))]
+            () => {
+                let _ = (hart_mask, start_addr, size, vmid);
+                unimplemented!()
+            }
+        }
+    }
+
+    #[inline]
+    fn remote_hfence_gvma(&self, hart_mask: HartMask, start_addr: usize, size: usize) -> SbiRet {
+        match () {
+            #[cfg(feature = "forward")]
+            () => sbi_rt::remote_hfence_gvma(hart_mask, start_addr, size),
+            #[cfg(not(feature = "forward"))]
+            () => {
+                let _ = (hart_mask, start_addr, size);
+                unimplemented!()
+            }
+        }
+    }
+
+    #[inline]
+    fn remote_hfence_vvma_asid(
+        &self,
+        hart_mask: HartMask,
+        start_addr: usize,
+        size: usize,
+        asid: usize,
+    ) -> SbiRet {
+        match () {
+            #[cfg(feature = "forward")]
+            () => sbi_rt::remote_hfence_vvma_asid(hart_mask, start_addr, size, asid),
+            #[cfg(not(feature = "forward"))]
+            () => {
+                let _ = (hart_mask, start_addr, size, asid);
+                unimplemented!()
+            }
+        }
+    }
+
+    #[inline]
+    fn remote_hfence_vvma(&self, hart_mask: HartMask, start_addr: usize, size: usize) -> SbiRet {
+        match () {
+            #[cfg(feature = "forward")]
+            () => sbi_rt::remote_hfence_vvma(hart_mask, start_addr, size),
+            #[cfg(not(feature = "forward"))]
+            () => {
+                let _ = (hart_mask, start_addr, size);
+                unimplemented!()
+            }
+        }
+    }
+}
+
+impl Hsm for Forward {
+    #[inline]
+    fn hart_start(&self, hartid: usize, start_addr: usize, opaque: usize) -> SbiRet {
+        match () {
+            #[cfg(feature = "forward")]
+            () => sbi_rt::hart_start(hartid, start_addr, opaque),
+            #[cfg(not(feature = "forward"))]
+            () => {
+                let _ = (hartid, start_addr, opaque);
+                unimplemented!()
+            }
+        }
+    }
+
+    #[inline]
+    fn hart_stop(&self) -> SbiRet {
+        match () {
+            #[cfg(feature = "forward")]
+            () => sbi_rt::hart_stop(),
+            #[cfg(not(feature = "forward"))]
+            () => {
+                unimplemented!()
+            }
+        }
+    }
+
+    #[inline]
+    fn hart_get_status(&self, hartid: usize) -> SbiRet {
+        match () {
+            #[cfg(feature = "forward")]
+            () => sbi_rt::hart_get_status(hartid),
+            #[cfg(not(feature = "forward"))]
+            () => {
+                let _ = hartid;
+                unimplemented!()
+            }
+        }
+    }
+
+    #[inline]
+    fn hart_suspend(&self, suspend_type: u32, resume_addr: usize, opaque: usize) -> SbiRet {
+        match () {
+            #[cfg(feature = "forward")]
+            () => sbi_rt::hart_suspend(suspend_type, resume_addr, opaque),
+            #[cfg(not(feature = "forward"))]
+            () => {
+                let _ = (suspend_type, resume_addr, opaque);
+                unimplemented!()
+            }
+        }
+    }
+}
+
+impl Ipi for Forward {
+    #[inline]
+    fn send_ipi(&self, hart_mask: HartMask) -> SbiRet {
+        match () {
+            #[cfg(feature = "forward")]
+            () => sbi_rt::send_ipi(hart_mask),
+            #[cfg(not(feature = "forward"))]
+            () => {
+                let _ = hart_mask;
+                unimplemented!()
+            }
+        }
+    }
+}
+
+impl Nacl for Forward {
+    #[inline]
+    fn probe_feature(&self, feature_id: u32) -> SbiRet {
+        match () {
+            #[cfg(feature = "forward")]
+            () => sbi_rt::nacl_probe_feature(feature_id),
+            #[cfg(not(feature = "forward"))]
+            () => {
+                let _ = feature_id;
+                unimplemented!()
+            }
+        }
+    }
+
+    #[inline]
+    fn set_shmem(&self, shmem: SharedPtr<[u8; NATIVE]>, flags: usize) -> SbiRet {
+        match () {
+            #[cfg(feature = "forward")]
+            () => sbi_rt::nacl_set_shmem(shmem, flags),
+            #[cfg(not(feature = "forward"))]
+            () => {
+                let _ = (shmem, flags);
+                unimplemented!()
+            }
+        }
+    }
+
+    #[inline]
+    fn sync_csr(&self, csr_num: usize) -> SbiRet {
+        match () {
+            #[cfg(feature = "forward")]
+            () => sbi_rt::nacl_sync_csr(csr_num),
+            #[cfg(not(feature = "forward"))]
+            () => {
+                let _ = csr_num;
+                unimplemented!()
+            }
+        }
+    }
+
+    #[inline]
+    fn sync_hfence(&self, entry_index: usize) -> SbiRet {
+        match () {
+            #[cfg(feature = "forward")]
+            () => sbi_rt::nacl_sync_hfence(entry_index),
+            #[cfg(not(feature = "forward"))]
+            () => {
+                let _ = entry_index;
+                unimplemented!()
+            }
+        }
+    }
+
+    #[inline]
+    fn sync_sret(&self) -> SbiRet {
+        match () {
+            #[cfg(feature = "forward")]
+            () => sbi_rt::nacl_sync_sret(),
+            #[cfg(not(feature = "forward"))]
+            () => unimplemented!(),
+        }
+    }
+}
+
+impl Pmu for Forward {
+    #[inline]
+    fn num_counters(&self) -> usize {
+        match () {
+            #[cfg(feature = "forward")]
+            () => sbi_rt::pmu_num_counters(),
+            #[cfg(not(feature = "forward"))]
+            () => unimplemented!(),
+        }
+    }
+
+    #[inline]
+    fn counter_get_info(&self, counter_idx: usize) -> SbiRet {
+        match () {
+            #[cfg(feature = "forward")]
+            () => sbi_rt::pmu_counter_get_info(counter_idx),
+            #[cfg(not(feature = "forward"))]
+            () => {
+                let _ = counter_idx;
+                unimplemented!()
+            }
+        }
+    }
+
+    #[inline]
+    fn counter_config_matching(
+        &self,
+        counter_idx_base: usize,
+        counter_idx_mask: usize,
+        config_flags: usize,
+        event_idx: usize,
+        event_data: u64,
+    ) -> SbiRet {
+        match () {
+            #[cfg(feature = "forward")]
+            () => sbi_rt::pmu_counter_config_matching(
+                counter_idx_base,
+                counter_idx_mask,
+                config_flags,
+                event_idx,
+                event_data,
+            ),
+            #[cfg(not(feature = "forward"))]
+            () => {
+                let _ = (
+                    counter_idx_base,
+                    counter_idx_mask,
+                    config_flags,
+                    event_idx,
+                    event_data,
+                );
+                unimplemented!()
+            }
+        }
+    }
+
+    #[inline]
+    fn counter_start(
+        &self,
+        counter_idx_base: usize,
+        counter_idx_mask: usize,
+        start_flags: usize,
+        initial_value: u64,
+    ) -> SbiRet {
+        match () {
+            #[cfg(feature = "forward")]
+            () => sbi_rt::pmu_counter_start(
+                counter_idx_base,
+                counter_idx_mask,
+                start_flags,
+                initial_value,
+            ),
+            #[cfg(not(feature = "forward"))]
+            () => {
+                let _ = (
+                    counter_idx_base,
+                    counter_idx_mask,
+                    start_flags,
+                    initial_value,
+                );
+                unimplemented!()
+            }
+        }
+    }
+
+    #[inline]
+    fn counter_stop(
+        &self,
+        counter_idx_base: usize,
+        counter_idx_mask: usize,
+        stop_flags: usize,
+    ) -> SbiRet {
+        match () {
+            #[cfg(feature = "forward")]
+            () => sbi_rt::pmu_counter_stop(counter_idx_base, counter_idx_mask, stop_flags),
+            #[cfg(not(feature = "forward"))]
+            () => {
+                let _ = (counter_idx_base, counter_idx_mask, stop_flags);
+                unimplemented!()
+            }
+        }
+    }
+
+    #[inline]
+    fn counter_fw_read(&self, counter_idx: usize) -> SbiRet {
+        match () {
+            #[cfg(feature = "forward")]
+            () => sbi_rt::pmu_counter_fw_read(counter_idx),
+            #[cfg(not(feature = "forward"))]
+            () => {
+                let _ = counter_idx;
+                unimplemented!()
+            }
+        }
+    }
+}
+
+impl Reset for Forward {
+    #[inline]
+    fn system_reset(&self, reset_type: u32, reset_reason: u32) -> SbiRet {
+        match () {
+            #[cfg(feature = "forward")]
+            () => sbi_rt::system_reset(reset_type, reset_reason),
+            #[cfg(not(feature = "forward"))]
+            () => {
+                let _ = (reset_type, reset_reason);
+                unimplemented!()
+            }
+        }
+    }
+}
+
+impl Sta for Forward {
+    #[inline]
+    fn set_shmem(&self, shmem: SharedPtr<[u8; 64]>, flags: usize) -> SbiRet {
+        match () {
+            #[cfg(feature = "forward")]
+            () => sbi_rt::sta_set_shmem(shmem, flags),
+            #[cfg(not(feature = "forward"))]
+            () => {
+                let _ = (shmem, flags);
+                unimplemented!()
+            }
+        }
+    }
+}
+
+impl Susp for Forward {
+    #[inline]
+    fn system_suspend(&self, sleep_type: u32, resume_addr: usize, opaque: usize) -> SbiRet {
+        match () {
+            #[cfg(feature = "forward")]
+            () => sbi_rt::system_suspend(sleep_type, resume_addr, opaque),
+            #[cfg(not(feature = "forward"))]
+            () => {
+                let _ = (sleep_type, resume_addr, opaque);
+                unimplemented!()
+            }
+        }
+    }
+}
+
+impl Timer for Forward {
+    #[inline]
+    fn set_timer(&self, stime_value: u64) {
+        match () {
+            #[cfg(feature = "forward")]
+            () => sbi_rt::set_timer(stime_value),
+            #[cfg(not(feature = "forward"))]
+            () => {
+                let _ = stime_value;
+                unimplemented!()
+            }
+        };
+    }
+}
+
+impl EnvInfo for Forward {
+    #[inline]
+    fn mvendorid(&self) -> usize {
+        match () {
+            #[cfg(feature = "forward")]
+            () => sbi_rt::get_mvendorid(),
+            #[cfg(not(feature = "forward"))]
+            () => unimplemented!(),
+        }
+    }
+
+    #[inline]
+    fn marchid(&self) -> usize {
+        match () {
+            #[cfg(feature = "forward")]
+            () => sbi_rt::get_marchid(),
+            #[cfg(not(feature = "forward"))]
+            () => unimplemented!(),
+        }
+    }
+
+    #[inline]
+    fn mimpid(&self) -> usize {
+        match () {
+            #[cfg(feature = "forward")]
+            () => sbi_rt::get_mimpid(),
+            #[cfg(not(feature = "forward"))]
+            () => unimplemented!(),
+        }
+    }
+}

+ 4 - 0
src/lib.rs

@@ -551,6 +551,8 @@ mod rfence;
 mod sta;
 mod susp;
 mod timer;
+
+mod forward;
 mod traits;
 
 /// The RustSBI logo without blank lines on the beginning.
@@ -1049,6 +1051,8 @@ pub use susp::Susp;
 pub use timer::Timer;
 pub use traits::{EnvInfo, RustSBI};
 
+pub use forward::Forward;
+
 // Macro internal functions and structures
 
 #[cfg(feature = "machine")]