Skip to content

Commit

Permalink
ROM: Log NMI/exception details to CPTRA_FW_EXTENDED_ERROR_INFO. (#753)
Browse files Browse the repository at this point in the history
This information is useful to debug unexpected ROM or hardware failures.
  • Loading branch information
korran authored Sep 13, 2023
1 parent bf1a7f7 commit 00b0503
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 18 deletions.
13 changes: 0 additions & 13 deletions drivers/src/soc_ifc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ Abstract:

use caliptra_error::{CaliptraError, CaliptraResult};
use caliptra_registers::soc_ifc::enums::DeviceLifecycleE;
use caliptra_registers::soc_ifc::regs::CptraWdtStatusReadVal;
use caliptra_registers::soc_ifc::{self, SocIfcReg};

use crate::{memory_layout, FuseBank};
Expand Down Expand Up @@ -164,18 +163,6 @@ impl SocIfc {
.write(|w| w.timer1_en(false));
}

/// Get the WDT status.
///
/// This is useful to call from a fatal-error-handling routine.
///
/// # Safety
///
/// This function is safe to call from a trap handler.
pub unsafe fn wdt_status() -> CptraWdtStatusReadVal {
let soc_ifc = SocIfcReg::new();
soc_ifc.regs().cptra_wdt_status().read()
}

pub fn get_cycle_count(&self, seconds: u32) -> CaliptraResult<u64> {
const GIGA_UNIT: u32 = 1_000_000_000;
let clock_period_picosecs = self.soc_ifc.regs().cptra_timer_config().read();
Expand Down
46 changes: 41 additions & 5 deletions rom/dev/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ Abstract:

use crate::{lock::lock_registers, print::HexBytes};
use caliptra_cfi_lib::CfiCounter;
use caliptra_registers::soc_ifc::SocIfcReg;
use core::hint::black_box;

use caliptra_drivers::{
Expand Down Expand Up @@ -217,29 +218,64 @@ fn launch_fmc(env: &mut RomEnv) -> ! {
#[inline(never)]
extern "C" fn exception_handler(exception: &exception::ExceptionRecord) {
cprintln!(
"EXCEPTION mcause=0x{:08X} mscause=0x{:08X} mepc=0x{:08X}",
"EXCEPTION mcause=0x{:08X} mscause=0x{:08X} mepc=0x{:08X} ra=0x{:08X}",
exception.mcause,
exception.mscause,
exception.mepc
exception.mepc,
exception.ra
);

{
let mut soc_ifc = unsafe { SocIfcReg::new() };
let soc_ifc = soc_ifc.regs_mut();
let ext_info = soc_ifc.cptra_fw_extended_error_info();
ext_info.at(0).write(|_| exception.mcause);
ext_info.at(1).write(|_| exception.mscause);
ext_info.at(2).write(|_| exception.mepc);
ext_info.at(3).write(|_| exception.ra);
}

handle_fatal_error(CaliptraError::ROM_GLOBAL_EXCEPTION.into());
}

#[no_mangle]
#[inline(never)]
extern "C" fn nmi_handler(exception: &exception::ExceptionRecord) {
let mut soc_ifc = unsafe { SocIfcReg::new() };

// If the NMI was fired by caliptra instead of the uC, this register
// contains the reason(s)
let err_interrupt_status = u32::from(
soc_ifc
.regs()
.intr_block_rf()
.error_internal_intr_r()
.read(),
);

cprintln!(
"NMI mcause=0x{:08X} mscause=0x{:08X} mepc=0x{:08X}",
"NMI mcause=0x{:08X} mscause=0x{:08X} mepc=0x{:08X} ra=0x{:08X} error_internal_intr_r={:08X}",
exception.mcause,
exception.mscause,
exception.mepc
exception.mepc,
exception.ra,
err_interrupt_status,
);

{
let soc_ifc = soc_ifc.regs_mut();
let ext_info = soc_ifc.cptra_fw_extended_error_info();
ext_info.at(0).write(|_| exception.mcause);
ext_info.at(1).write(|_| exception.mscause);
ext_info.at(2).write(|_| exception.mepc);
ext_info.at(3).write(|_| exception.ra);
ext_info.at(4).write(|_| err_interrupt_status);
}

// Check if the NMI was due to WDT expiry.
let mut error = CaliptraError::ROM_GLOBAL_NMI;

let wdt_status = unsafe { SocIfc::wdt_status() };
let wdt_status = soc_ifc.regs().cptra_wdt_status().read();
if wdt_status.t1_timeout() || wdt_status.t2_timeout() {
cprintln!("WDT Expired");
error = CaliptraError::ROM_GLOBAL_WDT_EXPIRED;
Expand Down

0 comments on commit 00b0503

Please sign in to comment.