浏览代码

Merge pull request #137 from woshiluo/patch/sifive_u

feat: support sifive_u
Luo Jia / Zhouqi Jiang 2 天之前
父节点
当前提交
a1c90f5141

+ 1 - 0
library/rustsbi/CHANGELOG.md

@@ -23,6 +23,7 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
 - lib: replace map+unwrap_or with Option::map_or in impls
 - doc: lib: alter link to Prototyper firmware in documentation.
 - doc: lib: clarify error codes in documents of SBI IPI and RFENCE extensions
+- doc: rustsbi: update `#[naked]` in docs to `#[unsafe(naked)]`
 
 ### Removed
 

+ 1 - 1
library/rustsbi/src/lib.rs

@@ -265,7 +265,7 @@
 //!
 //! ```no_run
 //! # #[cfg(nightly)] // disable checks
-//! #[naked]
+//! #[unsafe(naked)]
 //! #[link_section = ".text.entry"]
 //! #[export_name = "_start"]
 //! unsafe extern "C" fn entry() -> ! {

+ 0 - 1
prototyper/bench-kernel/src/main.rs

@@ -1,6 +1,5 @@
 #![no_std]
 #![no_main]
-#![feature(naked_functions)]
 #![allow(static_mut_refs)]
 
 #[macro_use]

+ 1 - 0
prototyper/prototyper/Cargo.toml

@@ -33,6 +33,7 @@ bouffalo-hal = { git = "https://github.com/rustsbi/bouffalo-hal", rev = "968b949
 static-toml = "1"
 seq-macro = "0.3.5"
 pastey = "0.1.0"
+uart_sifive = { git = "https://github.com/duskmoon314/uart-rs/" }
 
 [[bin]]
 name = "rustsbi-prototyper"

+ 7 - 0
prototyper/prototyper/src/fail.rs

@@ -48,6 +48,13 @@ pub fn device_tree_deserialize_root<'a>(
     }
 }
 
+#[cold]
+pub fn stop() -> ! {
+    loop {
+        core::hint::spin_loop()
+    }
+}
+
 cfg_if::cfg_if! {
     if #[cfg(feature = "payload")] {
     } else if #[cfg(feature = "jump")] {

+ 23 - 4
prototyper/prototyper/src/main.rs

@@ -41,7 +41,30 @@ pub const R_RISCV_RELATIVE: usize = 3;
 extern "C" fn rust_main(_hart_id: usize, opaque: usize, nonstandard_a2: usize) {
     // Track whether SBI is initialized and ready.
 
+    // Get boot information and prepare for kernel entry.
+    let boot_info = firmware::get_boot_info(nonstandard_a2);
+    let (mpp, next_addr) = (boot_info.mpp, boot_info.next_address);
+
+    // Check if current cpu support target privillege.
+    //
+    // If not, go to loop trap sliently.
+    use ::riscv::register::{misa, mstatus::MPP};
+    match mpp {
+        MPP::Supervisor => {
+            if !misa::read().unwrap().has_extension('S') {
+                fail::stop();
+            }
+        }
+        MPP::User => {
+            if !misa::read().unwrap().has_extension('U') {
+                fail::stop();
+            }
+        }
+        _ => {}
+    }
+
     let boot_hart_info = firmware::get_boot_hart(opaque, nonstandard_a2);
+
     // boot hart task entry.
     if boot_hart_info.is_boot_hart {
         // Initialize the sbi heap
@@ -58,10 +81,6 @@ extern "C" fn rust_main(_hart_id: usize, opaque: usize, nonstandard_a2: usize) {
         firmware::set_pmp(unsafe { PLATFORM.info.memory_range.as_ref().unwrap() });
         firmware::log_pmp_cfg(unsafe { PLATFORM.info.memory_range.as_ref().unwrap() });
 
-        // Get boot information and prepare for kernel entry.
-        let boot_info = firmware::get_boot_info(nonstandard_a2);
-        let (mpp, next_addr) = (boot_info.mpp, boot_info.next_address);
-
         // Log boot hart ID and PMP information
         let hart_id = current_hartid();
         info!("{:<30}: {}", "Boot HART ID", hart_id);

+ 31 - 0
prototyper/prototyper/src/platform/console.rs

@@ -1,12 +1,15 @@
 use bouffalo_hal::uart::RegisterBlock as BflbUartRegisterBlock;
+use uart_sifive::MmioUartSifive;
 use uart_xilinx::MmioUartAxiLite;
 use uart16550::{Register, Uart16550};
 
 use crate::sbi::console::ConsoleDevice;
+
 pub(crate) const UART16650U8_COMPATIBLE: [&str; 1] = ["ns16550a"];
 pub(crate) const UART16650U32_COMPATIBLE: [&str; 1] = ["snps,dw-apb-uart"];
 pub(crate) const UARTAXILITE_COMPATIBLE: [&str; 1] = ["xlnx,xps-uartlite-1.00.a"];
 pub(crate) const UARTBFLB_COMPATIBLE: [&str; 1] = ["bflb,bl808-uart"];
+pub(crate) const UARTSIFIVE_COMPATIBLE: [&str; 1] = ["sifive,uart0"];
 
 #[doc(hidden)]
 #[allow(unused)]
@@ -16,6 +19,7 @@ pub enum MachineConsoleType {
     Uart16550U32,
     UartAxiLite,
     UartBflb,
+    UartSifive,
 }
 
 /// For Uart 16550
@@ -52,6 +56,33 @@ impl ConsoleDevice for MmioUartAxiLite {
     }
 }
 
+/// Wrapper of UartSifive, warp for initialization.
+pub struct UartSifiveWrap {
+    inner: MmioUartSifive,
+}
+
+impl UartSifiveWrap {
+    pub fn new(addr: usize) -> Self {
+        let inner = MmioUartSifive::new(addr);
+        inner.disable_interrupt();
+        inner.enable_read();
+        inner.enable_write();
+        // TODO: calcuate & set div register
+        Self { inner }
+    }
+}
+
+/// For Uart Sifive
+impl ConsoleDevice for UartSifiveWrap {
+    fn read(&self, buf: &mut [u8]) -> usize {
+        self.inner.read(buf)
+    }
+
+    fn write(&self, buf: &[u8]) -> usize {
+        self.inner.write(buf)
+    }
+}
+
 /// For Uart BFLB
 pub struct UartBflbWrap {
     inner: *const BflbUartRegisterBlock,

+ 8 - 1
prototyper/prototyper/src/platform/mod.rs

@@ -15,9 +15,10 @@ use crate::fail;
 use crate::platform::clint::{MachineClintType, SIFIVE_CLINT_COMPATIBLE, THEAD_CLINT_COMPATIBLE};
 use crate::platform::console::Uart16550Wrap;
 use crate::platform::console::UartBflbWrap;
+use crate::platform::console::UartSifiveWrap;
 use crate::platform::console::{
     MachineConsoleType, UART16650U8_COMPATIBLE, UART16650U32_COMPATIBLE, UARTAXILITE_COMPATIBLE,
-    UARTBFLB_COMPATIBLE,
+    UARTBFLB_COMPATIBLE, UARTSIFIVE_COMPATIBLE,
 };
 use crate::platform::reset::SIFIVETEST_COMPATIBLE;
 use crate::sbi::SBI;
@@ -118,6 +119,9 @@ impl Platform {
                         if UARTBFLB_COMPATIBLE.contains(&device_id) {
                             self.info.console = Some((regs.start, MachineConsoleType::UartBflb));
                         }
+                        if UARTSIFIVE_COMPATIBLE.contains(&device_id) {
+                            self.info.console = Some((regs.start, MachineConsoleType::UartSifive));
+                        }
                     }
                 }
             }
@@ -283,6 +287,9 @@ impl Platform {
                 MachineConsoleType::UartBflb => Some(SbiConsole::new(Mutex::new(Box::new(
                     UartBflbWrap::new(base),
                 )))),
+                MachineConsoleType::UartSifive => Some(SbiConsole::new(Mutex::new(Box::new(
+                    UartSifiveWrap::new(base),
+                )))),
             };
         } else {
             self.sbi.console = None;

+ 2 - 17
prototyper/prototyper/src/sbi/features.rs

@@ -1,3 +1,4 @@
+use riscv::register::misa;
 use seq_macro::seq;
 use serde_device_tree::buildin::NodeSeq;
 
@@ -90,14 +91,7 @@ pub fn extension_detection(cpus: &NodeSeq) {
             let dt_supported = check_extension_in_device_tree(ext_name, &cpu_data);
             extensions[ext_index] = match ext {
                 Extension::Hypervisor if hart_id == current_hartid() => {
-                    let misa_supported = unsafe { misa_check_hypervisor_extension() };
-                    if dt_supported != misa_supported {
-                        warn!(
-                            "Device tree and MISA disagree on 'H' support for hart {}",
-                            hart_id
-                        );
-                    }
-                    misa_supported
+                    misa::read().unwrap().has_extension('H')
                 }
                 _ => dt_supported,
             };
@@ -177,15 +171,6 @@ fn mhpm_detection() {
     hart_context_mut(current_hartid()).features.mhpm_bits = 64;
 }
 
-/// Checks if the Hypervisor ('H') extension is supported via the `misa` CSR.
-pub unsafe fn misa_check_hypervisor_extension() -> bool {
-    let misa_val: usize;
-    unsafe {
-        core::arch::asm!("csrr {}, misa", out(reg) misa_val, options(nomem, nostack));
-    }
-    misa_val != 0 && (misa_val >> 7) & 1 != 0 // H extension bit is at position 7
-}
-
 pub fn hart_features_detection() {
     privileged_version_detection();
     mhpm_detection();