Browse Source

riscv: probe sbi extensions (#511)

LoGin 1 year ago
parent
commit
cb23beb255

+ 1 - 1
kernel/Cargo.toml

@@ -63,7 +63,7 @@ x86_64 = "0.14.10"
 # target为riscv64时,使用下面的依赖
 [target.'cfg(target_arch = "riscv64")'.dependencies]
 riscv = { version = "0.11.0", features = [ "s-mode" ] }
-sbi-rt = { git = "https://github.com/rustsbi/rustsbi" }
+sbi-rt = { git = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/rustsbi.git", rev = "80478bc417", features = ["legacy"] }
 
 
 # 构建时依赖项

+ 110 - 2
kernel/src/arch/riscv64/driver/sbi.rs

@@ -18,7 +18,115 @@
 /// console_putstr(message);
 /// ```
 pub fn console_putstr(s: &[u8]) {
-    for c in s {
-        sbi_rt::console_write_byte(*c);
+    if SbiDriver::extensions().contains(SBIExtensions::CONSOLE) {
+        for c in s {
+            sbi_rt::console_write_byte(*c);
+        }
+        return;
+    } else {
+        for c in s {
+            #[allow(deprecated)]
+            sbi_rt::legacy::console_putchar(*c as usize);
+        }
+    }
+}
+
+bitflags! {
+    pub struct SBIExtensions: u64 {
+        /// RISC-V SBI Base extension.
+        const BASE = 1 << 0;
+        /// Timer programmer extension.
+        const TIME = 1 << 1;
+        /// Inter-processor Interrupt extension.
+        const SPI = 1 << 2;
+        /// Remote Fence extension.
+        const RFENCE = 1 << 3;
+        /// Hart State Monitor extension.
+        const HSM = 1 << 4;
+        /// System Reset extension.
+        const RESET = 1 << 5;
+        /// Performance Monitoring Unit extension.
+        const PMU = 1 << 6;
+        /// Debug Console extension.
+        const CONSOLE = 1 << 7;
+        /// System Suspend extension.
+        const SUSPEND = 1 << 8;
+        /// SBI CPPC extension.
+        const CPPC = 1 << 9;
+        /// Nested Acceleration extension.
+        const NACL = 1 << 10;
+        /// Steal-time Accounting extension.
+        const STA = 1 << 11;
+    }
+}
+
+static mut EXTENSIONS: SBIExtensions = SBIExtensions::empty();
+
+#[derive(Debug)]
+pub struct SbiDriver;
+
+impl SbiDriver {
+    #[inline(never)]
+    pub fn early_init() {
+        unsafe {
+            EXTENSIONS = Self::probe_extensions();
+        }
+    }
+
+    /// 获取probe得到的SBI扩展信息。
+    pub fn extensions() -> &'static SBIExtensions {
+        unsafe { &EXTENSIONS }
+    }
+
+    fn probe_extensions() -> SBIExtensions {
+        let mut extensions = SBIExtensions::empty();
+        if sbi_rt::probe_extension(sbi_rt::Base).is_available() {
+            extensions |= SBIExtensions::BASE;
+        }
+        if sbi_rt::probe_extension(sbi_rt::Timer).is_available() {
+            extensions |= SBIExtensions::TIME;
+        }
+
+        if sbi_rt::probe_extension(sbi_rt::Ipi).is_available() {
+            extensions |= SBIExtensions::SPI;
+        }
+
+        if sbi_rt::probe_extension(sbi_rt::Fence).is_available() {
+            extensions |= SBIExtensions::RFENCE;
+        }
+
+        if sbi_rt::probe_extension(sbi_rt::Hsm).is_available() {
+            extensions |= SBIExtensions::HSM;
+        }
+
+        if sbi_rt::probe_extension(sbi_rt::Reset).is_available() {
+            extensions |= SBIExtensions::RESET;
+        }
+
+        if sbi_rt::probe_extension(sbi_rt::Pmu).is_available() {
+            extensions |= SBIExtensions::PMU;
+        }
+
+        if sbi_rt::probe_extension(sbi_rt::Console).is_available() {
+            extensions |= SBIExtensions::CONSOLE;
+        }
+
+        if sbi_rt::probe_extension(sbi_rt::Suspend).is_available() {
+            extensions |= SBIExtensions::SUSPEND;
+        }
+
+        if sbi_rt::probe_extension(sbi_rt::Cppc).is_available() {
+            extensions |= SBIExtensions::CPPC;
+        }
+
+        if sbi_rt::probe_extension(sbi_rt::Nacl).is_available() {
+            extensions |= SBIExtensions::NACL;
+        }
+
+        if sbi_rt::probe_extension(sbi_rt::Sta).is_available() {
+            extensions |= SBIExtensions::STA;
+        }
+
+        return extensions;
     }
 }

+ 6 - 2
kernel/src/arch/riscv64/init/mod.rs

@@ -2,7 +2,7 @@ use fdt::node::FdtNode;
 use system_error::SystemError;
 
 use crate::{
-    arch::mm::init::mm_early_init,
+    arch::{driver::sbi::SbiDriver, mm::init::mm_early_init},
     driver::{firmware::efi::init::efi_init, open_firmware::fdt::open_firmware_fdt_driver},
     init::{boot_params, init::start_kernel},
     kdebug, kinfo,
@@ -10,6 +10,8 @@ use crate::{
     print, println,
 };
 
+use super::driver::sbi::console_putstr;
+
 #[derive(Debug)]
 pub struct ArchBootParams {
     /// 启动时的fdt物理地址
@@ -76,9 +78,11 @@ unsafe fn parse_dtb() {
 
 #[inline(never)]
 pub fn early_setup_arch() -> Result<(), SystemError> {
-    let hartid = unsafe { BOOT_HARTID };
+    SbiDriver::early_init();
+    let hartid: usize = unsafe { BOOT_HARTID };
     let fdt_paddr = unsafe { BOOT_FDT_PADDR };
     boot_params().write().arch.fdt_paddr = fdt_paddr;
+
     kinfo!(
         "DragonOS kernel is running on hart {}, fdt address:{:?}",
         hartid,

+ 1 - 0
kernel/src/init/init.rs

@@ -44,6 +44,7 @@ pub fn start_kernel() -> ! {
 #[inline(never)]
 fn do_start_kernel() {
     init_before_mem_init();
+
     early_setup_arch().expect("setup_arch failed");
     unsafe { mm_init() };
     scm_reinit().unwrap();