浏览代码

feat(prototyper): add T-Head clint driver

guttatus 3 月之前
父节点
当前提交
584a3f8e0b

+ 18 - 1
Cargo.lock

@@ -1,6 +1,6 @@
 # This file is automatically @generated by Cargo.
 # It is not intended for manual editing.
-version = 3
+version = 4
 
 [[package]]
 name = "aclint"
@@ -63,6 +63,12 @@ version = "1.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
 
+[[package]]
+name = "bit_field"
+version = "0.10.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61"
+
 [[package]]
 name = "bitflags"
 version = "2.6.0"
@@ -323,6 +329,7 @@ dependencies = [
  "spin",
  "uart16550",
  "uart_xilinx",
+ "xuantie-riscv",
 ]
 
 [[package]]
@@ -587,3 +594,13 @@ version = "0.1.0"
 dependencies = [
  "clap",
 ]
+
+[[package]]
+name = "xuantie-riscv"
+version = "0.0.0"
+source = "git+https://github.com/guttatus/xuantie?branch=edtion#e3f8f83658b9c081307ca8235500886f389d47aa"
+dependencies = [
+ "bit_field",
+ "bitflags",
+ "volatile-register",
+]

+ 1 - 1
prototyper/Cargo.toml

@@ -23,7 +23,7 @@ uart16550 = "0.0.1"
 riscv-decode = "0.2.1"
 fast-trap = { version = "0.0.1", features = ["riscv-m"] }
 uart_xilinx = { git = "https://github.com/duskmoon314/uart-rs/" }
-
+xuantie-riscv = { git= "https://github.com/guttatus/xuantie", branch = "edtion" }
 
 [[bin]]
 name = "rustsbi-prototyper"

+ 4 - 6
prototyper/src/macros.rs

@@ -1,11 +1,9 @@
-// Ref: rcore-console crate
-
 #[allow(unused)]
 macro_rules! print {
     ($($arg:tt)*) => {
         use core::fmt::Write;
-        if unsafe {$crate::board::BOARD.have_console()} {
-            let console = unsafe { $crate::board::BOARD.sbi.console.as_mut().unwrap() };
+        if unsafe {$crate::platform::PLATFORM.have_console()} {
+            let console = unsafe { $crate::platform::PLATFORM.sbi.console.as_mut().unwrap() };
             console.write_fmt(core::format_args!($($arg)*)).unwrap();
             drop(console);
         }
@@ -17,8 +15,8 @@ macro_rules! println {
     () => ($crate::print!("\n\r"));
     ($($arg:tt)*) => {{
         use core::fmt::Write;
-        if unsafe {$crate::board::BOARD.have_console()} {
-            let console = unsafe { $crate::board::BOARD.sbi.console.as_mut().unwrap() };
+        if unsafe {$crate::platform::PLATFORM.have_console()} {
+            let console = unsafe { $crate::platform::PLATFORM.sbi.console.as_mut().unwrap() };
             console.write_fmt(core::format_args!($($arg)*)).unwrap();
             console.write_str("\n\r").unwrap();
         }

+ 7 - 7
prototyper/src/main.rs

@@ -9,7 +9,7 @@ extern crate log;
 #[macro_use]
 mod macros;
 
-mod board;
+mod platform;
 mod dt;
 mod fail;
 mod firmware;
@@ -18,7 +18,7 @@ mod sbi;
 
 use core::arch::asm;
 
-use crate::board::BOARD;
+use crate::platform::PLATFORM;
 use crate::riscv_spec::{current_hartid, menvcfg};
 use crate::sbi::extensions::{
     hart_extension_probe, hart_privileged_version, privileged_version_detection, Extension,
@@ -44,10 +44,10 @@ extern "C" fn rust_main(_hart_id: usize, opaque: usize, nonstandard_a2: usize) {
         let fdt_address = boot_hart_info.fdt_address;
 
         unsafe {
-            BOARD.init(fdt_address);
-            BOARD.print_board_info();
+            PLATFORM.init(fdt_address);
+            PLATFORM.print_board_info();
         }
-        firmware::set_pmp(unsafe { BOARD.info.memory_range.as_ref().unwrap() });
+        firmware::set_pmp(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);
@@ -71,11 +71,11 @@ extern "C" fn rust_main(_hart_id: usize, opaque: usize, nonstandard_a2: usize) {
         trap_stack::prepare_for_trap();
 
         // Wait for boot hart to complete SBI initialization.
-        while !unsafe { BOARD.ready() } {
+        while !unsafe { PLATFORM.ready() } {
             core::hint::spin_loop()
         }
 
-        firmware::set_pmp(unsafe { BOARD.info.memory_range.as_ref().unwrap() });
+        firmware::set_pmp(unsafe { PLATFORM.info.memory_range.as_ref().unwrap() });
     }
 
     // Detection Priv Ver

+ 89 - 0
prototyper/src/platform/clint.rs

@@ -0,0 +1,89 @@
+use core::arch::asm;
+use aclint::SifiveClint;
+use xuantie_riscv::peripheral::clint::THeadClint;
+
+use crate::sbi::ipi::IpiDevice;
+pub(crate) const CLINT_COMPATIBLE: [&str; 1] = ["riscv,clint0"];
+
+#[doc(hidden)]
+#[allow(unused)]
+#[derive(Clone, Copy, Debug)]
+pub enum MachineClintType {
+    SiFiveClint,
+    TheadClint,
+}
+
+#[doc(hidden)]
+#[allow(unused)]
+pub enum MachineClint {
+    SiFive(*const SifiveClint),
+    THead(*const THeadClint),
+}
+
+/// Ipi Device: Sifive Clint
+impl IpiDevice for MachineClint {
+    #[inline(always)]
+    fn read_mtime(&self) -> u64 {
+        match self {
+            Self::SiFive(sifive_clint) => unsafe { (**sifive_clint).read_mtime() },
+            Self::THead(_) => unsafe {
+                let mut mtime: u64 = 0;
+                asm!(
+                    "rdtime {}",
+                    inout(reg) mtime,
+                );
+                mtime
+            },
+        }
+    }
+
+    #[inline(always)]
+    fn write_mtime(&self, val: u64) {
+        match self {
+            Self::SiFive(sifive_clint) => unsafe { (**sifive_clint).write_mtime(val) },
+            Self::THead(_) => {
+                unimplemented!()
+            }
+        }
+    }
+
+    #[inline(always)]
+    fn read_mtimecmp(&self, hart_idx: usize) -> u64 {
+        match self {
+            Self::SiFive(sifive_clint) => unsafe { (**sifive_clint).read_mtimecmp(hart_idx) },
+            Self::THead(thead_clint) => unsafe { (**thead_clint).read_mtimecmp(hart_idx) },
+        }
+    }
+
+    #[inline(always)]
+    fn write_mtimecmp(&self, hart_idx: usize, val: u64) {
+        match self {
+            Self::SiFive(sifive_clint) => unsafe { (**sifive_clint).write_mtimecmp(hart_idx, val) },
+            Self::THead(thead_clint) => unsafe { (**thead_clint).write_mtimecmp(hart_idx, val) },
+        }
+    }
+
+    #[inline(always)]
+    fn read_msip(&self, hart_idx: usize) -> bool {
+        match self {
+            Self::SiFive(sifive_clint) => unsafe { (**sifive_clint).read_msip(hart_idx) },
+            Self::THead(thead_clint) => unsafe { (**thead_clint).read_msip(hart_idx) },
+        }
+    }
+
+    #[inline(always)]
+    fn set_msip(&self, hart_idx: usize) {
+        match self {
+            Self::SiFive(sifive_clint) => unsafe { (**sifive_clint).set_msip(hart_idx) },
+            Self::THead(thead_clint) => unsafe { (**thead_clint).set_msip(hart_idx) },
+        }
+    }
+
+    #[inline(always)]
+    fn clear_msip(&self, hart_idx: usize) {
+        match self {
+            Self::SiFive(sifive_clint) => unsafe { (**sifive_clint).clear_msip(hart_idx) },
+            Self::THead(thead_clint) => unsafe { (**thead_clint).clear_msip(hart_idx) },
+        }
+    }
+}

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

@@ -0,0 +1,44 @@
+use uart16550::Uart16550;
+use uart_xilinx::MmioUartAxiLite;
+
+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"];
+
+#[doc(hidden)]
+#[allow(unused)]
+#[derive(Clone, Copy, Debug)]
+pub enum MachineConsoleType {
+    Uart16550U8,
+    Uart16550U32,
+    UartAxiLite,
+}
+#[doc(hidden)]
+#[allow(unused)]
+pub enum MachineConsole {
+    Uart16550U8(*const Uart16550<u8>),
+    Uart16550U32(*const Uart16550<u32>),
+    UartAxiLite(MmioUartAxiLite),
+}
+
+unsafe impl Send for MachineConsole {}
+unsafe impl Sync for MachineConsole {}
+
+impl ConsoleDevice for MachineConsole {
+    fn read(&self, buf: &mut [u8]) -> usize {
+        match self {
+            Self::Uart16550U8(uart16550) => unsafe { (**uart16550).read(buf) },
+            Self::Uart16550U32(uart16550) => unsafe { (**uart16550).read(buf) },
+            Self::UartAxiLite(axilite) => axilite.read(buf),
+        }
+    }
+
+    fn write(&self, buf: &[u8]) -> usize {
+        match self {
+            MachineConsole::Uart16550U8(uart16550) => unsafe { (**uart16550).write(buf) },
+            MachineConsole::Uart16550U32(uart16550) => unsafe { (**uart16550).write(buf) },
+            Self::UartAxiLite(axilite) => axilite.write(buf),
+        }
+    }
+}

+ 51 - 134
prototyper/src/board.rs → prototyper/src/platform/mod.rs

@@ -1,31 +1,32 @@
-use aclint::SifiveClint;
-use core::{
-    fmt::{Display, Formatter, Result},
-    ops::Range,
-    sync::atomic::{AtomicBool, AtomicPtr, Ordering},
-};
-use sifive_test_device::SifiveTestDevice;
-use spin::Mutex;
-use uart16550::Uart16550;
-use uart_xilinx::uart_lite::uart::MmioUartAxiLite;
-
 use crate::fail;
-use crate::sbi::console::{ConsoleDevice, SbiConsole};
+use crate::platform::clint::{MachineClint, MachineClintType, CLINT_COMPATIBLE};
+use crate::platform::console::{
+    MachineConsole, MachineConsoleType, UART16650U32_COMPATIBLE, UART16650U8_COMPATIBLE,
+    UARTAXILITE_COMPATIBLE,
+};
+use crate::platform::reset::SIFIVETEST_COMPATIBLE;
+use crate::sbi::console::SbiConsole;
 use crate::sbi::extensions;
 use crate::sbi::hsm::SbiHsm;
-use crate::sbi::ipi::{IpiDevice, SbiIpi};
+use crate::sbi::ipi::SbiIpi;
 use crate::sbi::logger;
-use crate::sbi::reset::{ResetDevice, SbiReset};
+use crate::sbi::reset::SbiReset;
 use crate::sbi::trap_stack;
 use crate::sbi::trap_stack::NUM_HART_MAX;
 use crate::sbi::SBI;
 use crate::{dt, sbi::rfence::SbiRFence};
+use core::{
+    fmt::{Display, Formatter, Result},
+    ops::Range,
+    sync::atomic::{AtomicBool, AtomicPtr, Ordering},
+};
+use sifive_test_device::SifiveTestDevice;
+use spin::Mutex;
+use uart_xilinx::MmioUartAxiLite;
 
-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 SIFIVETEST_COMPATIBLE: [&str; 1] = ["sifive,test0"];
-pub(crate) const SIFIVECLINT_COMPATIBLE: [&str; 1] = ["riscv,clint0"];
+mod clint;
+mod console;
+mod reset;
 
 type BaseAddress = usize;
 /// Store finite-length string on the stack.
@@ -45,7 +46,7 @@ pub struct BoardInfo {
     pub memory_range: Option<Range<usize>>,
     pub console: Option<(BaseAddress, MachineConsoleType)>,
     pub reset: Option<BaseAddress>,
-    pub ipi: Option<BaseAddress>,
+    pub ipi: Option<(BaseAddress, MachineClintType)>,
     pub cpu_num: Option<usize>,
     pub cpu_enabled: Option<CpuEnableList>,
     pub model: StringInline<128>,
@@ -65,16 +66,15 @@ impl BoardInfo {
     }
 }
 
-pub struct Board {
+pub struct Platform {
     pub info: BoardInfo,
-    pub sbi: SBI<MachineConsole, SifiveClint, SifiveTestDevice>,
+    pub sbi: SBI<MachineConsole, MachineClint, SifiveTestDevice>,
     pub ready: AtomicBool,
 }
 
-#[allow(unused)]
-impl Board {
+impl Platform {
     pub const fn new() -> Self {
-        Board {
+        Platform {
             info: BoardInfo::new(),
             sbi: SBI::new(),
             ready: AtomicBool::new(false),
@@ -89,30 +89,6 @@ impl Board {
         self.ready.swap(true, Ordering::Release);
     }
 
-    pub fn have_console(&self) -> bool {
-        self.sbi.console.is_some()
-    }
-
-    pub fn have_reset(&self) -> bool {
-        self.sbi.reset.is_some()
-    }
-
-    pub fn have_ipi(&self) -> bool {
-        self.sbi.ipi.is_some()
-    }
-
-    pub fn have_hsm(&self) -> bool {
-        self.sbi.hsm.is_some()
-    }
-
-    pub fn have_rfence(&self) -> bool {
-        self.sbi.rfence.is_some()
-    }
-
-    pub fn ready(&self) -> bool {
-        self.ready.load(Ordering::Acquire)
-    }
-
     pub fn print_board_info(&self) {
         info!("RustSBI version {}", rustsbi::VERSION);
         rustsbi::LOGO.lines().for_each(|line| info!("{}", line));
@@ -169,8 +145,12 @@ impl Board {
                 let base_address = regs.start;
                 for device_id in compatible.iter() {
                     // Initialize clint device.
-                    if SIFIVECLINT_COMPATIBLE.contains(&device_id) {
-                        self.info.ipi = Some(base_address);
+                    if CLINT_COMPATIBLE.contains(&device_id) {
+                        if node.get_prop("clint,has-no-64bit-mmio").is_some() {
+                            self.info.ipi = Some((base_address, MachineClintType::TheadClint));
+                        } else {
+                            self.info.ipi = Some((base_address, MachineClintType::SiFiveClint));
+                        }
                     }
                     // Initialize reset device.
                     if SIFIVETEST_COMPATIBLE.contains(&device_id) {
@@ -253,9 +233,13 @@ impl Board {
     }
 
     fn sbi_ipi_init(&mut self) {
-        if let Some(base) = self.info.ipi {
+        if let Some((base, clint_type)) = self.info.ipi {
+            let new_clint = match clint_type {
+                MachineClintType::SiFiveClint => MachineClint::SiFive(base as _),
+                MachineClintType::TheadClint => MachineClint::THead(base as _),
+            };
             self.sbi.ipi = Some(SbiIpi::new(
-                AtomicPtr::new(base as _),
+                Mutex::new(new_clint),
                 self.info.cpu_num.unwrap_or(NUM_HART_MAX),
             ));
         } else {
@@ -282,98 +266,31 @@ impl Board {
     }
 }
 
-pub(crate) static mut BOARD: Board = Board::new();
-
-/// Console Device: Uart16550
-#[doc(hidden)]
-#[allow(unused)]
-#[derive(Clone, Copy, Debug)]
-pub enum MachineConsoleType {
-    Uart16550U8,
-    Uart16550U32,
-    UartAxiLite,
-}
-#[doc(hidden)]
 #[allow(unused)]
-pub enum MachineConsole {
-    Uart16550U8(*const Uart16550<u8>),
-    Uart16550U32(*const Uart16550<u32>),
-    UartAxiLite(MmioUartAxiLite),
-}
-
-unsafe impl Send for MachineConsole {}
-unsafe impl Sync for MachineConsole {}
-
-impl ConsoleDevice for MachineConsole {
-    fn read(&self, buf: &mut [u8]) -> usize {
-        match self {
-            Self::Uart16550U8(uart16550) => unsafe { (**uart16550).read(buf) },
-            Self::Uart16550U32(uart16550) => unsafe { (**uart16550).read(buf) },
-            Self::UartAxiLite(axilite) => axilite.read(buf),
-        }
-    }
-
-    fn write(&self, buf: &[u8]) -> usize {
-        match self {
-            MachineConsole::Uart16550U8(uart16550) => unsafe { (**uart16550).write(buf) },
-            MachineConsole::Uart16550U32(uart16550) => unsafe { (**uart16550).write(buf) },
-            Self::UartAxiLite(axilite) => axilite.write(buf),
-        }
-    }
-}
-
-/// Ipi Device: Sifive Clint
-impl IpiDevice for SifiveClint {
-    #[inline(always)]
-    fn read_mtime(&self) -> u64 {
-        self.read_mtime()
-    }
-
-    #[inline(always)]
-    fn write_mtime(&self, val: u64) {
-        self.write_mtime(val)
+impl Platform {
+    pub fn have_console(&self) -> bool {
+        self.sbi.console.is_some()
     }
 
-    #[inline(always)]
-    fn read_mtimecmp(&self, hart_idx: usize) -> u64 {
-        self.read_mtimecmp(hart_idx)
+    pub fn have_reset(&self) -> bool {
+        self.sbi.reset.is_some()
     }
 
-    #[inline(always)]
-    fn write_mtimecmp(&self, hart_idx: usize, val: u64) {
-        self.write_mtimecmp(hart_idx, val)
+    pub fn have_ipi(&self) -> bool {
+        self.sbi.ipi.is_some()
     }
 
-    #[inline(always)]
-    fn read_msip(&self, hart_idx: usize) -> bool {
-        self.read_msip(hart_idx)
+    pub fn have_hsm(&self) -> bool {
+        self.sbi.hsm.is_some()
     }
 
-    #[inline(always)]
-    fn set_msip(&self, hart_idx: usize) {
-        self.set_msip(hart_idx)
+    pub fn have_rfence(&self) -> bool {
+        self.sbi.rfence.is_some()
     }
 
-    #[inline(always)]
-    fn clear_msip(&self, hart_idx: usize) {
-        self.clear_msip(hart_idx)
+    pub fn ready(&self) -> bool {
+        self.ready.load(Ordering::Acquire)
     }
 }
 
-/// Reset Device: SifiveTestDevice
-impl ResetDevice for SifiveTestDevice {
-    #[inline]
-    fn fail(&self, code: u16) -> ! {
-        self.fail(code)
-    }
-
-    #[inline]
-    fn pass(&self) -> ! {
-        self.pass()
-    }
-
-    #[inline]
-    fn reset(&self) -> ! {
-        self.reset()
-    }
-}
+pub(crate) static mut PLATFORM: Platform = Platform::new();

+ 22 - 0
prototyper/src/platform/reset.rs

@@ -0,0 +1,22 @@
+use sifive_test_device::SifiveTestDevice;
+
+use crate::sbi::reset::ResetDevice;
+pub(crate) const SIFIVETEST_COMPATIBLE: [&str; 1] = ["sifive,test0"];
+
+/// Reset Device: SifiveTestDevice
+impl ResetDevice for SifiveTestDevice {
+    #[inline]
+    fn fail(&self, code: u16) -> ! {
+        self.fail(code)
+    }
+
+    #[inline]
+    fn pass(&self) -> ! {
+        self.pass()
+    }
+
+    #[inline]
+    fn reset(&self) -> ! {
+        self.reset()
+    }
+}

+ 3 - 3
prototyper/src/sbi/console.rs

@@ -1,7 +1,7 @@
-use crate::board::BOARD;
 use core::fmt::{self, Write};
 use rustsbi::{Console, Physical, SbiRet};
 use spin::Mutex;
+use crate::platform::PLATFORM;
 
 /// A trait that must be implemented by console devices to provide basic I/O functionality.
 pub trait ConsoleDevice {
@@ -114,11 +114,11 @@ impl<T: ConsoleDevice> fmt::Write for SbiConsole<T> {
 /// Global function to write a character to the console.
 #[inline]
 pub fn putchar(c: usize) -> usize {
-    unsafe { BOARD.sbi.console.as_mut().unwrap().putchar(c) }
+    unsafe { PLATFORM.sbi.console.as_mut().unwrap().putchar(c) }
 }
 
 /// Global function to read a character from the console.
 #[inline]
 pub fn getchar() -> usize {
-    unsafe { BOARD.sbi.console.as_mut().unwrap().getchar() }
+    unsafe { PLATFORM.sbi.console.as_mut().unwrap().getchar() }
 }

+ 4 - 1
prototyper/src/sbi/extensions.rs

@@ -116,7 +116,10 @@ pub fn init(cpus: &NodeSeq) {
         unsafe {
             ROOT_STACK
                 .get_mut(hart_id)
-                .map(|stack| stack.hart_context().extensions = HartFeatures(hart_exts))
+                .map(|stack| stack.hart_context().features = HartFeatures{
+                    extension: hart_exts,
+                    privileged_version: PrivilegedVersion::Version1_12,
+                })
                 .unwrap()
         }
     }

+ 3 - 3
prototyper/src/sbi/hsm.rs

@@ -6,7 +6,7 @@ use core::{
 use riscv::register::mstatus::MPP;
 use rustsbi::{spec::hsm::hart_state, SbiRet};
 
-use crate::board::BOARD;
+use crate::platform::PLATFORM;
 use crate::riscv_spec::current_hartid;
 use crate::sbi::hart_context::NextStage;
 use crate::sbi::trap_stack::ROOT_STACK;
@@ -196,7 +196,7 @@ impl rustsbi::Hsm for SbiHsm {
                     next_mode: MPP::Supervisor,
                 }) {
                     unsafe {
-                        BOARD.sbi.ipi.as_ref().unwrap().set_msip(hartid);
+                        PLATFORM.sbi.ipi.as_ref().unwrap().set_msip(hartid);
                     }
                     SbiRet::success(0)
                 } else {
@@ -232,7 +232,7 @@ impl rustsbi::Hsm for SbiHsm {
         use rustsbi::spec::hsm::suspend_type::{NON_RETENTIVE, RETENTIVE};
         if matches!(suspend_type, NON_RETENTIVE | RETENTIVE) {
             unsafe {
-                BOARD.sbi.ipi.as_ref().unwrap().clear_msip(current_hartid());
+                PLATFORM.sbi.ipi.as_ref().unwrap().clear_msip(current_hartid());
             }
             unsafe {
                 riscv::register::mie::set_msoft();

+ 18 - 20
prototyper/src/sbi/ipi.rs

@@ -1,7 +1,7 @@
-use core::sync::atomic::{AtomicPtr, Ordering::Relaxed};
+use core::sync::atomic::Ordering::Relaxed;
 use rustsbi::{HartMask, SbiRet};
-
-use crate::board::BOARD;
+use spin::Mutex;
+use crate::platform::PLATFORM;
 use crate::riscv_spec::{current_hartid, stimecmp};
 use crate::sbi::extensions::{hart_extension_probe, Extension};
 use crate::sbi::hsm::remote_hsm;
@@ -36,7 +36,7 @@ pub trait IpiDevice {
 /// SBI IPI implementation.
 pub struct SbiIpi<T: IpiDevice> {
     /// Reference to atomic pointer to IPI device.
-    pub ipi_dev: AtomicPtr<T>,
+    pub ipi_dev: Mutex<T>,
     /// Maximum hart ID in the system
     pub max_hart_id: usize,
 }
@@ -68,7 +68,6 @@ impl<T: IpiDevice> rustsbi::Ipi for SbiIpi<T> {
     /// Send IPI to specified harts.
     #[inline]
     fn send_ipi(&self, hart_mask: rustsbi::HartMask) -> SbiRet {
-        let ipi_dev = unsafe { &*self.ipi_dev.load(Relaxed) };
         let mut hart_mask = hart_mask;
 
         for hart_id in 0..=self.max_hart_id {
@@ -86,7 +85,7 @@ impl<T: IpiDevice> rustsbi::Ipi for SbiIpi<T> {
             };
 
             if unsafe {
-                BOARD
+                PLATFORM
                     .info
                     .cpu_enabled
                     .is_none_or(|list| list.get(hart_id).is_none_or(|res| !(*res)))
@@ -104,7 +103,7 @@ impl<T: IpiDevice> rustsbi::Ipi for SbiIpi<T> {
             }
 
             if set_ipi_type(hart_id, IPI_TYPE_SSOFT) == 0 {
-                ipi_dev.set_msip(hart_id);
+                self.set_msip(hart_id);
             }
         }
 
@@ -115,7 +114,7 @@ impl<T: IpiDevice> rustsbi::Ipi for SbiIpi<T> {
 impl<T: IpiDevice> SbiIpi<T> {
     /// Create new SBI IPI instance.
     #[inline]
-    pub fn new(ipi_dev: AtomicPtr<T>, max_hart_id: usize) -> Self {
+    pub fn new(ipi_dev: Mutex<T>, max_hart_id: usize) -> Self {
         Self {
             ipi_dev,
             max_hart_id,
@@ -129,7 +128,6 @@ impl<T: IpiDevice> SbiIpi<T> {
         ctx: rfence::RFenceContext,
     ) -> SbiRet {
         let current_hart = current_hartid();
-        let ipi_dev = unsafe { &*self.ipi_dev.load(Relaxed) };
         let mut hart_mask = hart_mask;
 
         for hart_id in 0..=self.max_hart_id {
@@ -147,7 +145,7 @@ impl<T: IpiDevice> SbiIpi<T> {
             };
 
             if unsafe {
-                BOARD
+                PLATFORM
                     .info
                     .cpu_enabled
                     .is_none_or(|list| list.get(hart_id).is_none_or(|res| !(*res)))
@@ -174,7 +172,7 @@ impl<T: IpiDevice> SbiIpi<T> {
                 if hart_id != current_hart {
                     let old_ipi_type = set_ipi_type(hart_id, IPI_TYPE_FENCE);
                     if old_ipi_type == 0 {
-                        ipi_dev.set_msip(hart_id);
+                        self.set_msip(hart_id);
                     }
                 }
             }
@@ -191,31 +189,31 @@ impl<T: IpiDevice> SbiIpi<T> {
     /// Get lower 32 bits of machine time.
     #[inline]
     pub fn get_time(&self) -> usize {
-        unsafe { (*self.ipi_dev.load(Relaxed)).read_mtime() as usize }
+        self.ipi_dev.lock().read_mtime() as usize
     }
 
     /// Get upper 32 bits of machine time.
     #[inline]
     pub fn get_timeh(&self) -> usize {
-        unsafe { ((*self.ipi_dev.load(Relaxed)).read_mtime() >> 32) as usize }
+        ( self.ipi_dev.lock().read_mtime() >> 32) as usize
     }
 
     /// Set machine software interrupt pending for hart.
     #[inline]
     pub fn set_msip(&self, hart_idx: usize) {
-        unsafe { (*self.ipi_dev.load(Relaxed)).set_msip(hart_idx) }
+        self.ipi_dev.lock().set_msip(hart_idx);
     }
 
     /// Clear machine software interrupt pending for hart.
     #[inline]
     pub fn clear_msip(&self, hart_idx: usize) {
-        unsafe { (*self.ipi_dev.load(Relaxed)).clear_msip(hart_idx) }
+        self.ipi_dev.lock().clear_msip(hart_idx);
     }
 
     /// Write machine timer compare value for hart.
     #[inline]
     pub fn write_mtimecmp(&self, hart_idx: usize, val: u64) {
-        unsafe { (*self.ipi_dev.load(Relaxed)).write_mtimecmp(hart_idx, val) }
+        self.ipi_dev.lock().write_mtimecmp(hart_idx, val);
     }
 
     /// Clear all pending interrupts for current hart.
@@ -223,7 +221,7 @@ impl<T: IpiDevice> SbiIpi<T> {
     pub fn clear(&self) {
         let hart_id = current_hartid();
         // Load ipi_dev once instead of twice
-        let ipi_dev = unsafe { &*self.ipi_dev.load(Relaxed) };
+        let ipi_dev = self.ipi_dev.lock();
         ipi_dev.clear_msip(hart_id);
         ipi_dev.write_mtimecmp(hart_id, u64::MAX);
     }
@@ -254,7 +252,7 @@ pub fn get_and_reset_ipi_type() -> u8 {
 /// Clear machine software interrupt pending for current hart.
 #[inline]
 pub fn clear_msip() {
-    match unsafe { BOARD.sbi.ipi.as_ref() } {
+    match unsafe { PLATFORM.sbi.ipi.as_ref() } {
         Some(ipi) => ipi.clear_msip(current_hartid()),
         None => error!("SBI or IPI device not initialized"),
     }
@@ -263,7 +261,7 @@ pub fn clear_msip() {
 /// Clear machine timer interrupt for current hart.
 #[inline]
 pub fn clear_mtime() {
-    match unsafe { BOARD.sbi.ipi.as_ref() } {
+    match unsafe { PLATFORM.sbi.ipi.as_ref() } {
         Some(ipi) => ipi.write_mtimecmp(current_hartid(), u64::MAX),
         None => error!("SBI or IPI device not initialized"),
     }
@@ -272,7 +270,7 @@ pub fn clear_mtime() {
 /// Clear all pending interrupts for current hart.
 #[inline]
 pub fn clear_all() {
-    match unsafe { BOARD.sbi.ipi.as_ref() } {
+    match unsafe { PLATFORM.sbi.ipi.as_ref() } {
         Some(ipi) => ipi.clear(),
         None => error!("SBI or IPI device not initialized"),
     }

+ 2 - 2
prototyper/src/sbi/reset.rs

@@ -1,7 +1,7 @@
 use core::sync::atomic::{AtomicPtr, Ordering::Relaxed};
 use rustsbi::SbiRet;
 
-use crate::board::BOARD;
+use crate::platform::PLATFORM;
 
 pub trait ResetDevice {
     fn fail(&self, code: u16) -> !;
@@ -61,7 +61,7 @@ impl<T: ResetDevice> rustsbi::Reset for SbiReset<T> {
 }
 
 pub fn fail() -> ! {
-    match unsafe { BOARD.sbi.reset.as_ref() } {
+    match unsafe { PLATFORM.sbi.reset.as_ref() } {
         Some(reset) => reset.fail(),
         None => panic!("SBI or IPI device not initialized"),
     }

+ 2 - 2
prototyper/src/sbi/rfence.rs

@@ -1,7 +1,7 @@
 use rustsbi::{HartMask, SbiRet};
 use spin::Mutex;
 
-use crate::board::BOARD;
+use crate::platform::PLATFORM;
 use crate::riscv_spec::current_hartid;
 use crate::sbi::fifo::{Fifo, FifoError};
 use crate::sbi::trap;
@@ -187,7 +187,7 @@ fn validate_address_range(start_addr: usize, size: usize) -> Result<usize, SbiRe
 
 /// Processes a remote fence operation by sending IPI to target harts.
 fn remote_fence_process(rfence_ctx: RFenceContext, hart_mask: HartMask) -> SbiRet {
-    let sbi_ret = unsafe { BOARD.sbi.ipi.as_ref() }
+    let sbi_ret = unsafe { PLATFORM.sbi.ipi.as_ref() }
         .unwrap()
         .send_ipi_by_fence(hart_mask, rfence_ctx);
 

+ 9 - 15
prototyper/src/sbi/trap.rs

@@ -6,7 +6,7 @@ use riscv::register::{
 };
 use rustsbi::RustSBI;
 
-use crate::board::BOARD;
+use crate::platform::PLATFORM;
 use crate::riscv_spec::{current_hartid, CSR_TIME, CSR_TIMEH};
 use crate::sbi::console;
 use crate::sbi::hsm::local_hsm;
@@ -382,7 +382,7 @@ pub extern "C" fn fast_handler(
         T::Exception(E::SupervisorEnvCall) => {
             use sbi_spec::{base, hsm, legacy};
             let mut ret = unsafe {
-                BOARD
+                PLATFORM
                     .sbi
                     .handle_ecall(a7, a6, [ctx.a0(), a1, a2, a3, a4, a5])
             };
@@ -436,17 +436,11 @@ pub extern "C" fn fast_handler(
         }
         // Handle other traps
         trap => {
-            println!(
-                "
------------------------------
-> trap:    {trap:?}
-> mepc:    {:#018x}
-> mtval:   {:#018x}
------------------------------
-            ",
-                mepc::read(),
-                mtval::read()
-            );
+            error!("-----------------------------");
+            error!("trap:    {trap:?}");
+            error!("mepc:    {:#018x}", mepc::read());
+            error!("mtval:   {:#018x}", mtval::read());
+            error!("-----------------------------");
             panic!("Stopped with unsupported trap")
         }
     }
@@ -488,7 +482,7 @@ fn illegal_instruction_handler(ctx: &mut FastContext) -> bool {
                     csr.rd()
                 );
                 ctx.regs().a[(csr.rd() - 10) as usize] =
-                    unsafe { BOARD.sbi.ipi.as_ref() }.unwrap().get_time();
+                    unsafe { PLATFORM.sbi.ipi.as_ref() }.unwrap().get_time();
             }
             CSR_TIMEH => {
                 assert!(
@@ -497,7 +491,7 @@ fn illegal_instruction_handler(ctx: &mut FastContext) -> bool {
                     csr.rd()
                 );
                 ctx.regs().a[(csr.rd() - 10) as usize] =
-                    unsafe { BOARD.sbi.ipi.as_ref() }.unwrap().get_timeh();
+                    unsafe { PLATFORM.sbi.ipi.as_ref() }.unwrap().get_timeh();
             }
             _ => return false,
         },