Bladeren bron

feat(prototyper): rewrite the driver interface using `dyn trait`

guttatus 2 maanden geleden
bovenliggende
commit
97b70c7bd6

+ 0 - 19
.vscode/launch.json

@@ -1,19 +0,0 @@
-{
-    // Use IntelliSense to learn about possible attributes.
-    // Hover to view descriptions of existing attributes.
-    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
-    "version": "0.2.0",
-    "configurations": [
-        {
-            "type": "gdb",
-            "request": "attach",
-            "name": "Attach to gdbserver",
-            "executable": "${workspaceRoot}/target/riscv64imac-unknown-none-elf/release/rustsbi-prototyper",
-            "target": "127.0.0.1:1234",
-            "remote": true,
-            "cwd": "${workspaceRoot}/prototyper/src",
-            "valuesFormatting": "parseText",
-            "gdbpath": "/usr/bin/riscv64-linux-gnu-gdb"
-        }
-    ]
-}

+ 1 - 2
prototyper/src/cfg.rs

@@ -6,10 +6,9 @@ pub const LEN_STACK_PER_HART: usize = 16 * 1024;
 pub const HEAP_SIZE: usize = 32 * 1024;
 /// Page size
 pub const PAGE_SIZE: usize = 4096;
-/// TLB_FLUSH_LIMIT defines the TLB refresh range limit. 
+/// TLB_FLUSH_LIMIT defines the TLB refresh range limit.
 /// If the TLB refresh range is greater than TLB_FLUSH_LIMIT, the entire TLB is refreshed.
 pub const TLB_FLUSH_LIMIT: usize = 4 * PAGE_SIZE;
 
-
 #[cfg(feature = "jump")]
 pub const JUMP_ADDRESS: usize = 0x80200000;

+ 1 - 1
prototyper/src/fail.rs

@@ -1,5 +1,5 @@
-use serde_device_tree::Dtb;
 use crate::riscv::current_hartid;
+use serde_device_tree::Dtb;
 
 use crate::devicetree;
 

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

@@ -42,7 +42,6 @@ fn get_fdt_address() -> usize {
     raw_fdt as usize
 }
 
-
 /// Gets boot hart information based on opaque and nonstandard_a2 parameters.
 ///
 /// Returns a BootHart struct containing FDT address and whether this is the boot hart.

+ 2 - 6
prototyper/src/main.rs

@@ -21,8 +21,6 @@ mod sbi;
 
 use core::arch::asm;
 
-use sbi::heap::heap_test;
-
 use crate::platform::PLATFORM;
 use crate::riscv::csr::menvcfg;
 use crate::riscv::current_hartid;
@@ -31,11 +29,11 @@ use crate::sbi::extensions::{
     PrivilegedVersion,
 };
 use crate::sbi::hart_context::NextStage;
+use crate::sbi::heap::sbi_heap_init;
 use crate::sbi::hsm::local_remote_hsm;
 use crate::sbi::ipi;
 use crate::sbi::trap::{self, trap_vec};
 use crate::sbi::trap_stack;
-use crate::sbi::heap::sbi_heap_init;
 
 pub const START_ADDRESS: usize = 0x80000000;
 pub const R_RISCV_RELATIVE: usize = 3;
@@ -49,7 +47,7 @@ extern "C" fn rust_main(_hart_id: usize, opaque: usize, nonstandard_a2: usize) {
     if boot_hart_info.is_boot_hart {
         // Initialize the sbi heap
         sbi_heap_init();
-        
+
         // parse the device tree
         let fdt_address = boot_hart_info.fdt_address;
 
@@ -60,7 +58,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() });
-        heap_test();
 
         // Get boot information and prepare for kernel entry.
         let boot_info = firmware::get_boot_info(nonstandard_a2);
@@ -207,4 +204,3 @@ unsafe extern "C" fn relocation_update() {
         options(noreturn)
     )
 }
-

+ 75 - 43
prototyper/src/platform/clint.rs

@@ -13,77 +13,109 @@ pub enum MachineClintType {
     TheadClint,
 }
 
-#[doc(hidden)]
-#[allow(unused)]
-pub enum MachineClint {
-    SiFive(*const SifiveClint),
-    THead(*const THeadClint),
+/// For SiFive Clint
+pub struct SifiveClintWrap {
+    inner: *const SifiveClint,
+}
+
+impl SifiveClintWrap {
+    pub fn new(base: usize) -> Self {
+        Self {
+            inner: base as *const SifiveClint,
+        }
+    }
 }
 
-/// Ipi Device: Sifive Clint
-impl IpiDevice for MachineClint {
+impl IpiDevice for SifiveClintWrap {
     #[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
-            },
-        }
+        unsafe { (*self.inner).read_mtime() }
     }
 
     #[inline(always)]
     fn write_mtime(&self, val: u64) {
-        match self {
-            Self::SiFive(sifive_clint) => unsafe { (**sifive_clint).write_mtime(val) },
-            Self::THead(_) => {
-                unimplemented!()
-            }
-        }
+        unsafe { (*self.inner).write_mtime(val) }
     }
 
     #[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) },
-        }
+        unsafe { (*self.inner).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) },
-        }
+        unsafe { (*self.inner).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) },
-        }
+        unsafe { (*self.inner).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) },
-        }
+        unsafe { (*self.inner).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) },
+        unsafe { (*self.inner).clear_msip(hart_idx) }
+    }
+}
+
+/// For T-Head Clint
+pub struct THeadClintWrap {
+    inner: *const THeadClint,
+}
+
+impl THeadClintWrap {
+    pub fn new(base: usize) -> Self {
+        Self {
+            inner: base as *const THeadClint,
+        }
+    }
+}
+
+impl IpiDevice for THeadClintWrap {
+    #[inline(always)]
+    fn read_mtime(&self) -> u64 {
+        unsafe {
+            let mut mtime: u64 = 0;
+            asm!(
+                "rdtime {}",
+                inout(reg) mtime,
+            );
+            mtime
         }
     }
+
+    #[inline(always)]
+    fn write_mtime(&self, _val: u64) {
+        unimplemented!()
+    }
+
+    #[inline(always)]
+    fn read_mtimecmp(&self, hart_idx: usize) -> u64 {
+        unsafe { (*self.inner).read_mtimecmp(hart_idx) }
+    }
+
+    #[inline(always)]
+    fn write_mtimecmp(&self, hart_idx: usize, val: u64) {
+        unsafe { (*self.inner).write_mtimecmp(hart_idx, val) }
+    }
+
+    #[inline(always)]
+    fn read_msip(&self, hart_idx: usize) -> bool {
+        unsafe { (*self.inner).read_msip(hart_idx) }
+    }
+
+    #[inline(always)]
+    fn set_msip(&self, hart_idx: usize) {
+        unsafe { (*self.inner).set_msip(hart_idx) }
+    }
+
+    #[inline(always)]
+    fn clear_msip(&self, hart_idx: usize) {
+        unsafe { (*self.inner).clear_msip(hart_idx) }
+    }
 }

+ 24 - 20
prototyper/src/platform/console.rs

@@ -1,4 +1,4 @@
-use uart16550::Uart16550;
+use uart16550::{Register, Uart16550};
 use uart_xilinx::MmioUartAxiLite;
 
 use crate::sbi::console::ConsoleDevice;
@@ -14,31 +14,35 @@ pub enum MachineConsoleType {
     Uart16550U32,
     UartAxiLite,
 }
-#[doc(hidden)]
-#[allow(unused)]
-pub enum MachineConsole {
-    Uart16550U8(*const Uart16550<u8>),
-    Uart16550U32(*const Uart16550<u32>),
-    UartAxiLite(MmioUartAxiLite),
+
+pub struct Uart16550Wrap<R: Register> {
+    inner: *const Uart16550<R>,
 }
 
-unsafe impl Send for MachineConsole {}
-unsafe impl Sync for MachineConsole {}
+impl<R: Register> Uart16550Wrap<R> {
+    pub fn new(base: usize) -> Self {
+        Self {
+            inner: base as *const Uart16550<R>,
+        }
+    }
+}
 
-impl ConsoleDevice for MachineConsole {
+impl<R: Register> ConsoleDevice for Uart16550Wrap<R> {
     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),
-        }
+        unsafe { (*self.inner).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),
-        }
+        unsafe { (*self.inner).write(buf) }
+    }
+}
+
+impl ConsoleDevice for MmioUartAxiLite {
+    fn read(&self, buf: &mut [u8]) -> usize {
+        self.read(buf)
+    }
+
+    fn write(&self, buf: &[u8]) -> usize {
+        self.write(buf)
     }
 }

+ 37 - 27
prototyper/src/platform/mod.rs

@@ -1,10 +1,21 @@
+use alloc::boxed::Box;
+use clint::{SifiveClintWrap, THeadClintWrap};
+use core::{
+    fmt::{Display, Formatter, Result},
+    ops::Range,
+    sync::atomic::{AtomicBool, Ordering},
+};
+use reset::SifiveTestDeviceWrap;
+use spin::Mutex;
+use uart_xilinx::MmioUartAxiLite;
+
 use crate::cfg::NUM_HART_MAX;
 use crate::devicetree::*;
 use crate::fail;
-use crate::platform::clint::{MachineClint, MachineClintType, CLINT_COMPATIBLE};
+use crate::platform::clint::{MachineClintType, CLINT_COMPATIBLE};
+use crate::platform::console::Uart16550Wrap;
 use crate::platform::console::{
-    MachineConsole, MachineConsoleType, UART16650U32_COMPATIBLE, UART16650U8_COMPATIBLE,
-    UARTAXILITE_COMPATIBLE,
+    MachineConsoleType, UART16650U32_COMPATIBLE, UART16650U8_COMPATIBLE, UARTAXILITE_COMPATIBLE,
 };
 use crate::platform::reset::SIFIVETEST_COMPATIBLE;
 use crate::sbi::console::SbiConsole;
@@ -16,14 +27,6 @@ use crate::sbi::reset::SbiReset;
 use crate::sbi::rfence::SbiRFence;
 use crate::sbi::trap_stack;
 use crate::sbi::SBI;
-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;
 
 mod clint;
 mod console;
@@ -69,7 +72,7 @@ impl BoardInfo {
 
 pub struct Platform {
     pub info: BoardInfo,
-    pub sbi: SBI<MachineConsole, MachineClint, SifiveTestDevice>,
+    pub sbi: SBI,
     pub ready: AtomicBool,
 }
 
@@ -202,14 +205,17 @@ impl Platform {
 
     fn sbi_console_init(&mut self) {
         if let Some((base, console_type)) = self.info.console {
-            let new_console = match console_type {
-                MachineConsoleType::Uart16550U8 => MachineConsole::Uart16550U8(base as _),
-                MachineConsoleType::Uart16550U32 => MachineConsole::Uart16550U32(base as _),
-                MachineConsoleType::UartAxiLite => {
-                    MachineConsole::UartAxiLite(MmioUartAxiLite::new(base))
-                }
+            self.sbi.console = match console_type {
+                MachineConsoleType::Uart16550U8 => Some(SbiConsole::new(Mutex::new(Box::new(
+                    Uart16550Wrap::<u8>::new(base),
+                )))),
+                MachineConsoleType::Uart16550U32 => Some(SbiConsole::new(Mutex::new(Box::new(
+                    Uart16550Wrap::<u32>::new(base),
+                )))),
+                MachineConsoleType::UartAxiLite => Some(SbiConsole::new(Mutex::new(Box::new(
+                    MmioUartAxiLite::new(base),
+                )))),
             };
-            self.sbi.console = Some(SbiConsole::new(Mutex::new(new_console)));
         } else {
             self.sbi.console = None;
         }
@@ -217,7 +223,9 @@ impl Platform {
 
     fn sbi_reset_init(&mut self) {
         if let Some(base) = self.info.reset {
-            self.sbi.reset = Some(SbiReset::new(AtomicPtr::new(base as _)));
+            self.sbi.reset = Some(SbiReset::new(Mutex::new(Box::new(
+                SifiveTestDeviceWrap::new(base),
+            ))));
         } else {
             self.sbi.reset = None;
         }
@@ -225,14 +233,16 @@ impl Platform {
 
     fn sbi_ipi_init(&mut self) {
         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 = match clint_type {
+                MachineClintType::SiFiveClint => Some(SbiIpi::new(
+                    Mutex::new(Box::new(SifiveClintWrap::new(base))),
+                    self.info.cpu_num.unwrap_or(NUM_HART_MAX),
+                )),
+                MachineClintType::TheadClint => Some(SbiIpi::new(
+                    Mutex::new(Box::new(THeadClintWrap::new(base))),
+                    self.info.cpu_num.unwrap_or(NUM_HART_MAX),
+                )),
             };
-            self.sbi.ipi = Some(SbiIpi::new(
-                Mutex::new(new_clint),
-                self.info.cpu_num.unwrap_or(NUM_HART_MAX),
-            ));
         } else {
             self.sbi.ipi = None;
         }

+ 16 - 4
prototyper/src/platform/reset.rs

@@ -3,20 +3,32 @@ use sifive_test_device::SifiveTestDevice;
 use crate::sbi::reset::ResetDevice;
 pub(crate) const SIFIVETEST_COMPATIBLE: [&str; 1] = ["sifive,test0"];
 
+pub struct SifiveTestDeviceWrap {
+    inner: *const SifiveTestDevice,
+}
+
+impl SifiveTestDeviceWrap {
+    pub fn new(base: usize) -> Self {
+        Self {
+            inner: base as *const SifiveTestDevice,
+        }
+    }
+}
+
 /// Reset Device: SifiveTestDevice
-impl ResetDevice for SifiveTestDevice {
+impl ResetDevice for SifiveTestDeviceWrap {
     #[inline]
     fn fail(&self, code: u16) -> ! {
-        self.fail(code)
+        unsafe { (*self.inner).fail(code) }
     }
 
     #[inline]
     fn pass(&self) -> ! {
-        self.pass()
+        unsafe { (*self.inner).pass() }
     }
 
     #[inline]
     fn reset(&self) -> ! {
-        self.reset()
+        unsafe { (*self.inner).reset() }
     }
 }

+ 9 - 7
prototyper/src/sbi/console.rs

@@ -1,8 +1,10 @@
-use crate::platform::PLATFORM;
+use alloc::boxed::Box;
 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 {
     /// Reads bytes from the console into the provided buffer.
@@ -22,17 +24,17 @@ pub trait ConsoleDevice {
 ///
 /// This provides a safe interface for interacting with console hardware through the
 /// SBI specification.
-pub struct SbiConsole<T: ConsoleDevice> {
-    inner: Mutex<T>,
+pub struct SbiConsole {
+    inner: Mutex<Box<dyn ConsoleDevice>>,
 }
 
-impl<T: ConsoleDevice> SbiConsole<T> {
+impl SbiConsole {
     /// Creates a new SBI console that wraps the provided locked console device.
     ///
     /// # Arguments
     /// * `inner` - A mutex containing the console device implementation
     #[inline]
-    pub fn new(inner: Mutex<T>) -> Self {
+    pub fn new(inner: Mutex<Box<dyn ConsoleDevice>>) -> Self {
         Self { inner }
     }
 
@@ -67,7 +69,7 @@ impl<T: ConsoleDevice> SbiConsole<T> {
     }
 }
 
-impl<T: ConsoleDevice> Console for SbiConsole<T> {
+impl Console for SbiConsole {
     /// Write a physical memory buffer to the console.
     #[inline]
     fn write(&self, bytes: Physical<&[u8]>) -> SbiRet {
@@ -96,7 +98,7 @@ impl<T: ConsoleDevice> Console for SbiConsole<T> {
     }
 }
 
-impl<T: ConsoleDevice> fmt::Write for SbiConsole<T> {
+impl fmt::Write for SbiConsole {
     /// Implement Write trait for string formatting.
     #[inline]
     fn write_str(&mut self, s: &str) -> fmt::Result {

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

@@ -1,11 +1,11 @@
-use buddy_system_allocator::LockedHeap;
 use crate::cfg::HEAP_SIZE;
+use buddy_system_allocator::LockedHeap;
 
 #[link_section = ".bss.heap"]
 static mut HEAP: [u8; HEAP_SIZE] = [0; HEAP_SIZE];
 
 #[global_allocator]
-static HEAP_ALLOCATOR: LockedHeap::<15> = LockedHeap::<15>::empty();
+static HEAP_ALLOCATOR: LockedHeap<15> = LockedHeap::<15>::empty();
 
 pub fn sbi_heap_init() {
     unsafe {

+ 7 - 6
prototyper/src/sbi/ipi.rs

@@ -6,6 +6,7 @@ use crate::sbi::hsm::remote_hsm;
 use crate::sbi::rfence;
 use crate::sbi::trap;
 use crate::sbi::trap_stack::ROOT_STACK;
+use alloc::boxed::Box;
 use core::sync::atomic::Ordering::Relaxed;
 use rustsbi::{HartMask, SbiRet};
 use spin::Mutex;
@@ -35,14 +36,14 @@ pub trait IpiDevice {
 }
 
 /// SBI IPI implementation.
-pub struct SbiIpi<T: IpiDevice> {
+pub struct SbiIpi {
     /// Reference to atomic pointer to IPI device.
-    pub ipi_dev: Mutex<T>,
+    pub ipi_dev: Mutex<Box<dyn IpiDevice>>,
     /// Maximum hart ID in the system
     pub max_hart_id: usize,
 }
 
-impl<T: IpiDevice> rustsbi::Timer for SbiIpi<T> {
+impl rustsbi::Timer for SbiIpi {
     /// Set timer value for current hart.
     #[inline]
     fn set_timer(&self, stime_value: u64) {
@@ -65,7 +66,7 @@ impl<T: IpiDevice> rustsbi::Timer for SbiIpi<T> {
     }
 }
 
-impl<T: IpiDevice> rustsbi::Ipi for SbiIpi<T> {
+impl rustsbi::Ipi for SbiIpi {
     /// Send IPI to specified harts.
     #[inline]
     fn send_ipi(&self, hart_mask: rustsbi::HartMask) -> SbiRet {
@@ -112,10 +113,10 @@ impl<T: IpiDevice> rustsbi::Ipi for SbiIpi<T> {
     }
 }
 
-impl<T: IpiDevice> SbiIpi<T> {
+impl SbiIpi {
     /// Create new SBI IPI instance.
     #[inline]
-    pub fn new(ipi_dev: Mutex<T>, max_hart_id: usize) -> Self {
+    pub fn new(ipi_dev: Mutex<Box<dyn IpiDevice>>, max_hart_id: usize) -> Self {
         Self {
             ipi_dev,
             max_hart_id,

+ 9 - 9
prototyper/src/sbi/mod.rs

@@ -10,34 +10,34 @@ pub mod early_trap;
 pub mod extensions;
 pub mod fifo;
 pub mod hart_context;
+pub mod heap;
 pub mod logger;
 pub mod trap;
 pub mod trap_stack;
-pub mod heap;
 
-use console::{ConsoleDevice, SbiConsole};
+use console::SbiConsole;
 use hsm::SbiHsm;
-use ipi::{IpiDevice, SbiIpi};
-use reset::{ResetDevice, SbiReset};
+use ipi::SbiIpi;
+use reset::SbiReset;
 use rfence::SbiRFence;
 
 #[derive(RustSBI, Default)]
 #[rustsbi(dynamic)]
 #[allow(clippy::upper_case_acronyms)]
-pub struct SBI<C: ConsoleDevice, I: IpiDevice, R: ResetDevice> {
+pub struct SBI {
     #[rustsbi(console)]
-    pub console: Option<SbiConsole<C>>,
+    pub console: Option<SbiConsole>,
     #[rustsbi(ipi, timer)]
-    pub ipi: Option<SbiIpi<I>>,
+    pub ipi: Option<SbiIpi>,
     #[rustsbi(hsm)]
     pub hsm: Option<SbiHsm>,
     #[rustsbi(reset)]
-    pub reset: Option<SbiReset<R>>,
+    pub reset: Option<SbiReset>,
     #[rustsbi(fence)]
     pub rfence: Option<SbiRFence>,
 }
 
-impl<C: ConsoleDevice, I: IpiDevice, R: ResetDevice> SBI<C, I, R> {
+impl SBI {
     pub const fn new() -> Self {
         SBI {
             console: None,

+ 19 - 29
prototyper/src/sbi/reset.rs

@@ -1,5 +1,6 @@
-use core::sync::atomic::{AtomicPtr, Ordering::Relaxed};
+use alloc::boxed::Box;
 use rustsbi::SbiRet;
+use spin::Mutex;
 
 use crate::platform::PLATFORM;
 
@@ -9,31 +10,23 @@ pub trait ResetDevice {
     fn reset(&self) -> !;
 }
 
-pub struct SbiReset<T: ResetDevice> {
-    pub reset_dev: AtomicPtr<T>,
+pub struct SbiReset {
+    pub reset_dev: Mutex<Box<dyn ResetDevice>>,
 }
 
-impl<T: ResetDevice> SbiReset<T> {
-    pub fn new(reset_dev: AtomicPtr<T>) -> Self {
+impl SbiReset {
+    pub fn new(reset_dev: Mutex<Box<dyn ResetDevice>>) -> Self {
         Self { reset_dev }
     }
 
     #[allow(unused)]
     pub fn fail(&self) -> ! {
-        let reset_dev = self.reset_dev.load(Relaxed);
-        if reset_dev.is_null() {
-            trace!("test fail, begin dead loop");
-            loop {
-                core::hint::spin_loop()
-            }
-        } else {
-            trace!("Test fail, invoke process exit procedure on Reset device");
-            unsafe { (*reset_dev).fail(0) }
-        }
+        trace!("Test fail, invoke process exit procedure on Reset device");
+        self.reset_dev.lock().fail(0);
     }
 }
 
-impl<T: ResetDevice> rustsbi::Reset for SbiReset<T> {
+impl rustsbi::Reset for SbiReset {
     #[inline]
     fn system_reset(&self, reset_type: u32, reset_reason: u32) -> SbiRet {
         use rustsbi::spec::srst::{
@@ -42,19 +35,11 @@ impl<T: ResetDevice> rustsbi::Reset for SbiReset<T> {
         };
         match reset_type {
             RESET_TYPE_SHUTDOWN => match reset_reason {
-                RESET_REASON_NO_REASON => unsafe {
-                    (*self.reset_dev.load(Relaxed)).pass();
-                },
-                RESET_REASON_SYSTEM_FAILURE => unsafe {
-                    (*self.reset_dev.load(Relaxed)).fail(u16::MAX);
-                },
-                value => unsafe {
-                    (*self.reset_dev.load(Relaxed)).fail(value as _);
-                },
-            },
-            RESET_TYPE_COLD_REBOOT | RESET_TYPE_WARM_REBOOT => unsafe {
-                (*self.reset_dev.load(Relaxed)).reset();
+                RESET_REASON_NO_REASON => self.reset_dev.lock().pass(),
+                RESET_REASON_SYSTEM_FAILURE => self.reset_dev.lock().fail(u16::MAX),
+                value => self.reset_dev.lock().fail(value as _),
             },
+            RESET_TYPE_COLD_REBOOT | RESET_TYPE_WARM_REBOOT => self.reset_dev.lock().reset(),
 
             _ => SbiRet::invalid_param(),
         }
@@ -65,6 +50,11 @@ impl<T: ResetDevice> rustsbi::Reset for SbiReset<T> {
 pub fn fail() -> ! {
     match unsafe { PLATFORM.sbi.reset.as_ref() } {
         Some(reset) => reset.fail(),
-        None => panic!("SBI or IPI device not initialized"),
+        None => {
+            trace!("test fail, begin dead loop");
+            loop {
+                core::hint::spin_loop()
+            }
+        }
     }
 }

+ 1 - 1
prototyper/src/sbi/trap_stack.rs

@@ -1,9 +1,9 @@
+use crate::cfg::{LEN_STACK_PER_HART, NUM_HART_MAX};
 use crate::riscv::current_hartid;
 use crate::sbi::hart_context::HartContext;
 use crate::sbi::trap::fast_handler;
 use core::mem::forget;
 use fast_trap::FreeTrapStack;
-use crate::cfg::{NUM_HART_MAX, LEN_STACK_PER_HART};
 
 /// Root stack array for all harts, placed in BSS Stack section.
 #[link_section = ".bss.stack"]