浏览代码

feat(prototyper): support sifive_u

Signed-off-by: Woshiluo Luo <woshiluo.luo@outlook.com>
Woshiluo Luo 2 周之前
父节点
当前提交
e3a617ec9b

+ 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() -> ! {

+ 45 - 54
prototyper/bench-kernel/src/main.rs

@@ -1,6 +1,5 @@
 #![no_std]
 #![no_main]
-#![feature(naked_functions)]
 #![allow(static_mut_refs)]
 
 #[macro_use]
@@ -30,31 +29,29 @@ const RISCV_IMAGE_MAGIC: u64 = 0x5643534952; /* Magic number, little endian, "RI
 const RISCV_IMAGE_MAGIC2: u32 = 0x05435352; /* Magic number 2, little endian, "RSC\x05" */
 
 /// boot header
-#[naked]
+#[unsafe(naked)]
 #[unsafe(no_mangle)]
 #[unsafe(link_section = ".head.text")]
 unsafe extern "C" fn _boot_header() -> ! {
-    unsafe {
-        naked_asm!(
-            "j _start",
-            ".word 0",
-            ".balign 8",
-            ".dword 0x200000",
-            ".dword iend - istart",
-            ".dword {RISCV_HEAD_FLAGS}",
-            ".word  {RISCV_HEADER_VERSION}",
-            ".word  0",
-            ".dword 0",
-            ".dword {RISCV_IMAGE_MAGIC}",
-            ".balign 4",
-            ".word  {RISCV_IMAGE_MAGIC2}",
-            ".word  0",
-            RISCV_HEAD_FLAGS = const RISCV_HEAD_FLAGS,
-            RISCV_HEADER_VERSION = const RISCV_HEADER_VERSION,
-            RISCV_IMAGE_MAGIC = const RISCV_IMAGE_MAGIC,
-            RISCV_IMAGE_MAGIC2 = const RISCV_IMAGE_MAGIC2,
-        );
-    }
+    naked_asm!(
+        "j _start",
+        ".word 0",
+        ".balign 8",
+        ".dword 0x200000",
+        ".dword iend - istart",
+        ".dword {RISCV_HEAD_FLAGS}",
+        ".word  {RISCV_HEADER_VERSION}",
+        ".word  0",
+        ".dword 0",
+        ".dword {RISCV_IMAGE_MAGIC}",
+        ".balign 4",
+        ".word  {RISCV_IMAGE_MAGIC2}",
+        ".word  0",
+        RISCV_HEAD_FLAGS = const RISCV_HEAD_FLAGS,
+        RISCV_HEADER_VERSION = const RISCV_HEADER_VERSION,
+        RISCV_IMAGE_MAGIC = const RISCV_IMAGE_MAGIC,
+        RISCV_IMAGE_MAGIC2 = const RISCV_IMAGE_MAGIC2,
+    );
 }
 
 const STACK_SIZE: usize = 512 * 1024; // 512 KiB
@@ -88,53 +85,47 @@ static mut BOOT_HART_ID: usize = 0;
 /// # Safety
 ///
 /// 裸函数。
-#[naked]
+#[unsafe(naked)]
 #[unsafe(no_mangle)]
 #[unsafe(link_section = ".text.entry")]
 unsafe extern "C" fn _start(hartid: usize, device_tree_paddr: usize) -> ! {
-    unsafe {
-        naked_asm!(
-            // clear bss segment
-            "   la      t0, sbss
+    naked_asm!(
+        // clear bss segment
+        "   la      t0, sbss
             la      t1, ebss
         1:  bgeu    t0, t1, 2f
             sd      zero, 0(t0)
             addi    t0, t0, 8
             j       1b",
-            "2:",
-            "   la sp, {stack} + {stack_size}",
-            "   j  {main}",
-            stack_size = const STACK_SIZE,
-            stack      =   sym STACK,
-            main       =   sym rust_main,
-        )
-    }
+        "2:",
+        "   la sp, {stack} + {stack_size}",
+        "   j  {main}",
+        stack_size = const STACK_SIZE,
+        stack      =   sym STACK,
+        main       =   sym rust_main,
+    )
 }
 
-#[naked]
+#[unsafe(naked)]
 #[unsafe(no_mangle)]
 extern "C" fn init_hart(hartid: usize, opaque: usize) {
-    unsafe {
-        naked_asm!(
-            "add sp, a1, zero",
-            "csrw sscratch, sp",
-            "call {init_main}",
-            init_main = sym init_main,
-        )
-    }
+    naked_asm!(
+        "add sp, a1, zero",
+        "csrw sscratch, sp",
+        "call {init_main}",
+        init_main = sym init_main,
+    )
 }
 
-#[naked]
+#[unsafe(naked)]
 #[unsafe(no_mangle)]
 extern "C" fn core_send_ipi(hartid: usize, opaque: usize) {
-    unsafe {
-        naked_asm!(
-            "add sp, a1, zero",
-            "csrw sscratch, sp",
-            "call {send_ipi}",
-            send_ipi = sym send_ipi,
-        )
-    }
+    naked_asm!(
+        "add sp, a1, zero",
+        "csrw sscratch, sp",
+        "call {send_ipi}",
+        send_ipi = sym send_ipi,
+    )
 }
 
 extern "C" fn send_ipi(hartid: usize) -> ! {

+ 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")] {

+ 1 - 1
prototyper/prototyper/src/firmware/mod.rs

@@ -26,7 +26,7 @@ pub struct BootHart {
     pub is_boot_hart: bool,
 }
 
-#[naked]
+#[unsafe(naked)]
 #[unsafe(link_section = ".fdt")]
 #[repr(align(16))]
 #[cfg(feature = "fdt")]

+ 2 - 2
prototyper/prototyper/src/firmware/payload.rs

@@ -19,10 +19,10 @@ pub fn get_boot_info(_nonstandard_a2: usize) -> BootInfo {
     }
 }
 
-#[naked]
+#[unsafe(naked)]
 #[unsafe(link_section = ".payload")]
 pub extern "C" fn payload_image() {
-    unsafe { naked_asm!(concat!(".incbin \"", env!("PROTOTYPER_PAYLOAD_PATH"), "\""),) }
+    naked_asm!(concat!(".incbin \"", env!("PROTOTYPER_PAYLOAD_PATH"), "\""),)
 }
 
 #[inline]

+ 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();