From cb23beb255d8e32b45d879ac19386a3597ca4115 Mon Sep 17 00:00:00 2001 From: LoGin Date: Wed, 7 Feb 2024 17:15:17 +0800 Subject: [PATCH] riscv: probe sbi extensions (#511) --- kernel/Cargo.toml | 2 +- kernel/src/arch/riscv64/driver/sbi.rs | 112 +++++++++++++++++++++++++- kernel/src/arch/riscv64/init/mod.rs | 8 +- kernel/src/init/init.rs | 1 + 4 files changed, 118 insertions(+), 5 deletions(-) diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml index 7fe6b38b..4440b034 100644 --- a/kernel/Cargo.toml +++ b/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"] } # 构建时依赖项 diff --git a/kernel/src/arch/riscv64/driver/sbi.rs b/kernel/src/arch/riscv64/driver/sbi.rs index ac1ce6be..d859db74 100644 --- a/kernel/src/arch/riscv64/driver/sbi.rs +++ b/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; } } diff --git a/kernel/src/arch/riscv64/init/mod.rs b/kernel/src/arch/riscv64/init/mod.rs index 1c851151..e3e10d0f 100644 --- a/kernel/src/arch/riscv64/init/mod.rs +++ b/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, diff --git a/kernel/src/init/init.rs b/kernel/src/init/init.rs index 8fb414ad..641793a5 100644 --- a/kernel/src/init/init.rs +++ b/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();