浏览代码

lib: improve error information on firmware failure

Signed-off-by: Zhouqi Jiang <luojia@hust.edu.cn>
Zhouqi Jiang 11 月之前
父节点
当前提交
633f14dcb6
共有 3 个文件被更改,包括 55 次插入25 次删除
  1. 15 7
      src/dynamic.rs
  2. 37 0
      src/fail.rs
  3. 3 18
      src/main.rs

+ 15 - 7
src/dynamic.rs

@@ -23,26 +23,34 @@ pub struct DynamicInfo {
 const DYNAMIC_INFO_VALID_ADDRESSES: Range<usize> = 0x1000..0xf000;
 const NEXT_ADDR_VALID_ADDRESSES: Range<usize> = 0x80000000..0x90000000;
 
+pub struct DynamicReadError {
+    pub bad_paddr: usize,
+}
+
 // TODO unconstrained lifetime
-pub fn read_paddr(paddr: usize) -> Result<DynamicInfo, ()> {
+pub fn read_paddr(paddr: usize) -> Result<DynamicInfo, DynamicReadError> {
     // check pointer before dereference
     if !DYNAMIC_INFO_VALID_ADDRESSES.contains(&paddr)
         || !DYNAMIC_INFO_VALID_ADDRESSES.contains(&(paddr + size_of::<DynamicInfo>()))
     {
-        return Err(());
+        return Err(DynamicReadError { bad_paddr: paddr });
     }
     let ans = unsafe { *(paddr as *const DynamicInfo) };
     Ok(ans)
 }
 
-#[derive(Default)]
-pub struct DynamicError {
-    invalid_mpp: bool,
-    invalid_next_addr: bool,
+pub struct DynamicError<'a> {
+    pub invalid_mpp: bool,
+    pub invalid_next_addr: bool,
+    pub bad_info: &'a DynamicInfo,
 }
 
 pub fn mpp_next_addr(info: &DynamicInfo) -> Result<(mstatus::MPP, usize), DynamicError> {
-    let mut error = DynamicError::default();
+    let mut error = DynamicError {
+        invalid_mpp: false,
+        invalid_next_addr: false,
+        bad_info: info,
+    };
 
     // fail safe, errors will be aggregated after whole checking process.
     let next_addr_valid = NEXT_ADDR_VALID_ADDRESSES.contains(&info.next_addr);

+ 37 - 0
src/fail.rs

@@ -0,0 +1,37 @@
+use crate::dynamic;
+use riscv::register::mstatus;
+
+#[cold]
+pub fn invalid_dynamic_info(err: dynamic::DynamicError) -> (mstatus::MPP, usize) {
+    error!("Invalid dynamic information:");
+    if err.invalid_mpp {
+        error!("- dynamic information contains invalid privilege mode");
+    }
+    if err.invalid_next_addr {
+        error!("- dynamic information contains invalid next jump address");
+    }
+    let explain_next_mode = match err.bad_info.next_mode {
+        3 => "Machine",
+        1 => "Supervisor",
+        0 => "User",
+        _ => "Invalid",
+    };
+    error!(
+        "help: dynamic information contains magic value 0x{:x}, version {}, next jump address 0x{:x}, next privilege mode {} ({}), options {:x}",
+        err.bad_info.magic, err.bad_info.version, err.bad_info.next_addr, err.bad_info.next_mode, explain_next_mode, err.bad_info.options
+    );
+    loop {
+        core::hint::spin_loop()
+    }
+}
+
+#[cold]
+pub fn no_dynamic_info_available(err: dynamic::DynamicReadError) -> dynamic::DynamicInfo {
+    error!(
+        "no dynamic information available at address 0x{:x}",
+        err.bad_paddr
+    );
+    loop {
+        core::hint::spin_loop()
+    }
+}

+ 3 - 18
src/main.rs

@@ -10,6 +10,7 @@ mod macros;
 mod board;
 mod console;
 mod dynamic;
+mod fail;
 
 use panic_halt as _;
 use riscv::register::mstatus;
@@ -24,30 +25,14 @@ extern "C" fn main(hart_id: usize, opaque: usize, nonstandard_a2: usize) -> usiz
     }
     info!("Initializing RustSBI machine-mode environment.");
 
-    let info = dynamic::read_paddr(nonstandard_a2).unwrap_or_else(fail_no_dynamic_info_available);
+    let info = dynamic::read_paddr(nonstandard_a2).unwrap_or_else(fail::no_dynamic_info_available);
 
-    let (mpp, next_addr) = dynamic::mpp_next_addr(&info).unwrap_or_else(fail_invalid_dynamic_info);
+    let (mpp, next_addr) = dynamic::mpp_next_addr(&info).unwrap_or_else(fail::invalid_dynamic_info);
 
     unsafe { mstatus::set_mpp(mpp) };
     next_addr
 }
 
-#[cold]
-fn fail_invalid_dynamic_info(_err: dynamic::DynamicError) -> (mstatus::MPP, usize) {
-    // TODO dynamic information contains invalid privilege mode or next address
-    loop {
-        core::hint::spin_loop()
-    }
-}
-
-#[cold]
-fn fail_no_dynamic_info_available(_err: ()) -> dynamic::DynamicInfo {
-    // TODO no dynamic information available
-    loop {
-        core::hint::spin_loop()
-    }
-}
-
 const LEN_STACK_PER_HART: usize = 16 * 1024;
 pub(crate) const NUM_HART_MAX: usize = 8;
 const LEN_STACK: usize = LEN_STACK_PER_HART * NUM_HART_MAX;