Просмотр исходного кода

Merge pull request #25 from luojia65/guest-instance

rustsbi: guest instance; u32 function and module id
Luo Jia 3 лет назад
Родитель
Сommit
0cab5e3fc9
12 измененных файлов с 86 добавлено и 60 удалено
  1. 3 1
      CHANGELOG.md
  2. 10 5
      Cargo.toml
  3. 24 16
      src/ecall.rs
  4. 15 9
      src/ecall/base.rs
  5. 5 5
      src/ecall/hsm.rs
  6. 2 2
      src/ecall/ipi.rs
  7. 8 8
      src/ecall/pmu.rs
  8. 8 8
      src/ecall/rfence.rs
  9. 2 2
      src/ecall/srst.rs
  10. 3 3
      src/ecall/timer.rs
  11. 1 1
      src/extension.rs
  12. 5 0
      src/lib.rs

+ 3 - 1
CHANGELOG.md

@@ -27,7 +27,7 @@ module on SBI v0.3 format. Users are encouraged to use 0.2.1 and newer version i
 ## [0.2.0] - 2022-02-13
 
 ### Added
-- Support for RISC-V SBI v0.3 Specification
+- Support for RISC-V SBI v1.0 and v0.3 Specification
 - S-level Illegal instruction exception is now delegated into S-level software handler
 - Support RFENCE extension in RustSBI framework
 - Added a test kernel to test SBI function on RustSBI implementations
@@ -38,7 +38,9 @@ module on SBI v0.3 format. Users are encouraged to use 0.2.1 and newer version i
 - Build under new asm! macro
 
 ### Modified
+
 - Reform RustSBI project into a library
+- Use `u32` function and module id width for SBI 1.0
 - Function `rustsbi::ecall` now require `a0`-`a5` input parameters
 - Enhanced in-line code documents from SBI standard
 - Now IPI module requires to return an `SbiRet` value

+ 10 - 5
Cargo.toml

@@ -15,7 +15,15 @@ keywords = ["riscv", "sbi", "rustsbi"]
 categories = ["os", "embedded", "hardware-support", "no-std"]
 edition = "2018"
 
-# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+[dependencies]
+embedded-hal = "0.2.6"
+nb = "1.0"
+riscv = "0.7"
+
+[features]
+default = []
+# Dynamic pointer widths on SBI implementations; useful for developing hypervisors
+guest = []
 
 [package.metadata.docs.rs]
 default-target = "riscv64imac-unknown-none-elf"
@@ -23,7 +31,4 @@ targets = [
     "riscv32imac-unknown-none-elf", "riscv64imac-unknown-none-elf",
 ]
 
-[dependencies]
-embedded-hal = "0.2.6"
-nb = "1.0"
-riscv = "0.7"
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

+ 24 - 16
src/ecall.rs

@@ -10,23 +10,23 @@ mod rfence;
 mod srst;
 mod timer;
 
-pub const EXTENSION_BASE: usize = 0x10;
-pub const EXTENSION_TIMER: usize = 0x54494D45;
-pub const EXTENSION_IPI: usize = 0x735049;
-pub const EXTENSION_RFENCE: usize = 0x52464E43;
-pub const EXTENSION_HSM: usize = 0x48534D;
-pub const EXTENSION_SRST: usize = 0x53525354;
-pub const EXTENSION_PMU: usize = 0x504D55;
+pub const EXTENSION_BASE: u32 = 0x10;
+pub const EXTENSION_TIMER: u32 = 0x54494D45;
+pub const EXTENSION_IPI: u32 = 0x735049;
+pub const EXTENSION_RFENCE: u32 = 0x52464E43;
+pub const EXTENSION_HSM: u32 = 0x48534D;
+pub const EXTENSION_SRST: u32 = 0x53525354;
+pub const EXTENSION_PMU: u32 = 0x504D55;
 
-const LEGACY_SET_TIMER: usize = 0x0;
-const LEGACY_CONSOLE_PUTCHAR: usize = 0x01;
-const LEGACY_CONSOLE_GETCHAR: usize = 0x02;
-// const LEGACY_CLEAR_IPI: usize = 0x03;
-const LEGACY_SEND_IPI: usize = 0x04;
-// const LEGACY_REMOTE_FENCE_I: usize = 0x05;
-// const LEGACY_REMOTE_SFENCE_VMA: usize = 0x06;
-// const LEGACY_REMOTE_SFENCE_VMA_ASID: usize = 0x07;
-const LEGACY_SHUTDOWN: usize = 0x08;
+const LEGACY_SET_TIMER: u32 = 0x0;
+const LEGACY_CONSOLE_PUTCHAR: u32 = 0x01;
+const LEGACY_CONSOLE_GETCHAR: u32 = 0x02;
+// const LEGACY_CLEAR_IPI: u32 = 0x03;
+const LEGACY_SEND_IPI: u32 = 0x04;
+// const LEGACY_REMOTE_FENCE_I: u32 = 0x05;
+// const LEGACY_REMOTE_SFENCE_VMA: u32 = 0x06;
+// const LEGACY_REMOTE_SFENCE_VMA_ASID: u32 = 0x07;
+const LEGACY_SHUTDOWN: u32 = 0x08;
 
 /// Supervisor environment call handler function
 ///
@@ -67,6 +67,14 @@ const LEGACY_SHUTDOWN: usize = 0x08;
 /// This skips the `ecall` instruction itself which is 4-byte long in all conditions.
 #[inline]
 pub fn handle_ecall(extension: usize, function: usize, param: [usize; 6]) -> SbiRet {
+    // RISC-V SBI requires SBI extension IDs (EIDs) and SBI function IDs (FIDs)
+    // are encoded as signed 32-bit integers
+    #[cfg(not(target_pointer_width = "32"))]
+    if extension > u32::MAX as usize || function > u32::MAX as usize {
+        return SbiRet::not_supported();
+    }
+    let (extension, function) = (extension as u32, function as u32);
+    // process actual environment calls
     match extension {
         EXTENSION_RFENCE => {
             rfence::handle_ecall_rfence(function, param[0], param[1], param[2], param[3], param[4])

+ 15 - 9
src/ecall/base.rs

@@ -3,16 +3,16 @@ use super::SbiRet;
 use crate::{SBI_SPEC_MAJOR, SBI_SPEC_MINOR};
 use riscv::register::{marchid, mimpid, mvendorid};
 
-const FUNCTION_BASE_GET_SPEC_VERSION: usize = 0x0;
-const FUNCTION_BASE_GET_SBI_IMPL_ID: usize = 0x1;
-const FUNCTION_BASE_GET_SBI_IMPL_VERSION: usize = 0x2;
-const FUNCTION_BASE_PROBE_EXTENSION: usize = 0x3;
-const FUNCTION_BASE_GET_MVENDORID: usize = 0x4;
-const FUNCTION_BASE_GET_MARCHID: usize = 0x5;
-const FUNCTION_BASE_GET_MIMPID: usize = 0x6;
+const FUNCTION_BASE_GET_SPEC_VERSION: u32 = 0x0;
+const FUNCTION_BASE_GET_SBI_IMPL_ID: u32 = 0x1;
+const FUNCTION_BASE_GET_SBI_IMPL_VERSION: u32 = 0x2;
+const FUNCTION_BASE_PROBE_EXTENSION: u32 = 0x3;
+const FUNCTION_BASE_GET_MVENDORID: u32 = 0x4;
+const FUNCTION_BASE_GET_MARCHID: u32 = 0x5;
+const FUNCTION_BASE_GET_MIMPID: u32 = 0x6;
 
 #[inline]
-pub fn handle_ecall_base(function: usize, param0: usize) -> SbiRet {
+pub fn handle_ecall_base(function: u32, param0: usize) -> SbiRet {
     match function {
         FUNCTION_BASE_GET_SPEC_VERSION => get_spec_version(),
         FUNCTION_BASE_GET_SBI_IMPL_ID => get_sbi_impl_id(),
@@ -47,7 +47,13 @@ fn get_sbi_impl_version() -> SbiRet {
 fn probe_extension(extension_id: usize) -> SbiRet {
     const NO_EXTENSION: usize = 0;
     const HAS_EXTENSION: usize = 1;
-    let ans = crate::extension::probe_extension(extension_id);
+    // SBI extension IDs (EIDs) and SBI function IDs (FIDs) are encoded as signed 32-bit integers.
+    // When passed in registers these follow the standard above calling convention rules.
+    #[cfg(not(target_pointer_width = "32"))]
+    if extension_id > u32::MAX as usize {
+        return SbiRet::ok(NO_EXTENSION);
+    }
+    let ans = crate::extension::probe_extension(extension_id as u32);
     SbiRet::ok(if ans { HAS_EXTENSION } else { NO_EXTENSION })
 }
 

+ 5 - 5
src/ecall/hsm.rs

@@ -1,13 +1,13 @@
 //! hsm extension
 use super::SbiRet;
 
-const FUNCTION_HSM_HART_START: usize = 0x0;
-const FUNCTION_HSM_HART_STOP: usize = 0x1;
-const FUNCTION_HSM_HART_GET_STATUS: usize = 0x2;
-const FUNCTION_HSM_HART_SUSPEND: usize = 0x3;
+const FUNCTION_HSM_HART_START: u32 = 0x0;
+const FUNCTION_HSM_HART_STOP: u32 = 0x1;
+const FUNCTION_HSM_HART_GET_STATUS: u32 = 0x2;
+const FUNCTION_HSM_HART_SUSPEND: u32 = 0x3;
 
 #[inline]
-pub fn handle_ecall_hsm(function: usize, param0: usize, param1: usize, param2: usize) -> SbiRet {
+pub fn handle_ecall_hsm(function: u32, param0: usize, param1: usize, param2: usize) -> SbiRet {
     match function {
         FUNCTION_HSM_HART_START => hart_start(param0, param1, param2),
         FUNCTION_HSM_HART_STOP => hart_stop(param0),

+ 2 - 2
src/ecall/ipi.rs

@@ -2,10 +2,10 @@ use super::SbiRet;
 use crate::hart_mask::HartMask;
 use crate::ipi::send_ipi_many;
 
-const FUNCTION_IPI_SEND_IPI: usize = 0x0;
+const FUNCTION_IPI_SEND_IPI: u32 = 0x0;
 
 #[inline]
-pub fn handle_ecall_ipi(function: usize, param0: usize, param1: usize) -> SbiRet {
+pub fn handle_ecall_ipi(function: u32, param0: usize, param1: usize) -> SbiRet {
     match function {
         FUNCTION_IPI_SEND_IPI => send_ipi(param0, param1),
         _ => SbiRet::not_supported(),

+ 8 - 8
src/ecall/pmu.rs

@@ -2,17 +2,17 @@
 use super::SbiRet;
 use crate::pmu;
 
-const FUNCTION_PMU_NUM_COUNTERS: usize = 0x0;
-const FUNCTION_PMU_COUNTER_GET_INFO: usize = 0x1;
-const FUNCTION_PMU_COUNTER_CONFIG_MATCHING: usize = 0x2;
-const FUNCTION_PMU_COUNTER_START: usize = 0x3;
-const FUNCTION_PMU_COUNTER_STOP: usize = 0x4;
-const FUNCTION_PMU_COUNTER_FW_READ: usize = 0x5;
+const FUNCTION_PMU_NUM_COUNTERS: u32 = 0x0;
+const FUNCTION_PMU_COUNTER_GET_INFO: u32 = 0x1;
+const FUNCTION_PMU_COUNTER_CONFIG_MATCHING: u32 = 0x2;
+const FUNCTION_PMU_COUNTER_START: u32 = 0x3;
+const FUNCTION_PMU_COUNTER_STOP: u32 = 0x4;
+const FUNCTION_PMU_COUNTER_FW_READ: u32 = 0x5;
 
 #[inline]
 #[cfg(target_pointer_width = "64")]
 pub fn handle_ecall_pmu_64(
-    function: usize,
+    function: u32,
     param0: usize,
     param1: usize,
     param2: usize,
@@ -35,7 +35,7 @@ pub fn handle_ecall_pmu_64(
 #[inline]
 #[cfg(target_pointer_width = "32")]
 pub fn handle_ecall_pmu_32(
-    function: usize,
+    function: u32,
     param0: usize,
     param1: usize,
     param2: usize,

+ 8 - 8
src/ecall/rfence.rs

@@ -2,17 +2,17 @@ use super::SbiRet;
 use crate::hart_mask::HartMask;
 use crate::rfence;
 
-const FUNCTION_RFENCE_REMOTE_FENCE_I: usize = 0x0;
-const FUNCTION_RFENCE_REMOTE_SFENCE_VMA: usize = 0x1;
-const FUNCTION_RFENCE_REMOTE_SFENCE_VMA_ASID: usize = 0x2;
-const FUNCTION_RFENCE_REMOTE_HFENCE_GVMA_VMID: usize = 0x3;
-const FUNCTION_RFENCE_REMOTE_HFENCE_GVMA: usize = 0x4;
-const FUNCTION_RFENCE_REMOTE_HFENCE_VVMA_ASID: usize = 0x5;
-const FUNCTION_RFENCE_REMOTE_HFENCE_VVMA: usize = 0x6;
+const FUNCTION_RFENCE_REMOTE_FENCE_I: u32 = 0x0;
+const FUNCTION_RFENCE_REMOTE_SFENCE_VMA: u32 = 0x1;
+const FUNCTION_RFENCE_REMOTE_SFENCE_VMA_ASID: u32 = 0x2;
+const FUNCTION_RFENCE_REMOTE_HFENCE_GVMA_VMID: u32 = 0x3;
+const FUNCTION_RFENCE_REMOTE_HFENCE_GVMA: u32 = 0x4;
+const FUNCTION_RFENCE_REMOTE_HFENCE_VVMA_ASID: u32 = 0x5;
+const FUNCTION_RFENCE_REMOTE_HFENCE_VVMA: u32 = 0x6;
 
 #[inline]
 pub fn handle_ecall_rfence(
-    function: usize,
+    function: u32,
     param0: usize,
     param1: usize,
     param2: usize,

+ 2 - 2
src/ecall/srst.rs

@@ -1,9 +1,9 @@
 use super::SbiRet;
 
-const FUNCTION_SYSTEM_RESET: usize = 0x0;
+const FUNCTION_SYSTEM_RESET: u32 = 0x0;
 
 #[inline]
-pub fn handle_ecall_srst(function: usize, param0: usize, param1: usize) -> SbiRet {
+pub fn handle_ecall_srst(function: u32, param0: usize, param1: usize) -> SbiRet {
     match function {
         FUNCTION_SYSTEM_RESET => system_reset(param0, param1),
         _ => SbiRet::not_supported(),

+ 3 - 3
src/ecall/timer.rs

@@ -1,10 +1,10 @@
 use super::SbiRet;
 
-const FUNCTION_TIMER_SET_TIMER: usize = 0x0;
+const FUNCTION_TIMER_SET_TIMER: u32 = 0x0;
 
 #[inline]
 #[cfg(target_pointer_width = "64")]
-pub fn handle_ecall_timer_64(function: usize, param0: usize) -> SbiRet {
+pub fn handle_ecall_timer_64(function: u32, param0: usize) -> SbiRet {
     match function {
         FUNCTION_TIMER_SET_TIMER => set_timer(param0),
         _ => SbiRet::not_supported(),
@@ -13,7 +13,7 @@ pub fn handle_ecall_timer_64(function: usize, param0: usize) -> SbiRet {
 
 #[inline]
 #[cfg(target_pointer_width = "32")]
-pub fn handle_ecall_timer_32(function: usize, param0: usize, param1: usize) -> SbiRet {
+pub fn handle_ecall_timer_32(function: u32, param0: usize, param1: usize) -> SbiRet {
     match function {
         FUNCTION_TIMER_SET_TIMER => set_timer(param0, param1),
         _ => SbiRet::not_supported(),

+ 1 - 1
src/extension.rs

@@ -1,7 +1,7 @@
 use crate::ecall::*;
 
 #[inline]
-pub fn probe_extension(extension: usize) -> bool {
+pub fn probe_extension(extension: u32) -> bool {
     match extension {
         EXTENSION_BASE => true,
         EXTENSION_TIMER => crate::timer::probe_timer(),

+ 5 - 0
src/lib.rs

@@ -179,6 +179,11 @@ mod timer;
 
 mod util;
 
+#[cfg(feature = "guest")]
+mod guest;
+
+pub mod instance;
+
 const SBI_SPEC_MAJOR: usize = 0;
 const SBI_SPEC_MINOR: usize = 3;