From 4af8595696897e8c0e8bfaa63a33c26ba272839e Mon Sep 17 00:00:00 2001 From: Sree Revoori Date: Mon, 20 Nov 2023 21:22:22 +0000 Subject: [PATCH] Add test triggering cpu fault and check extended error info To do this, we write an illegal instruction at the rom_entry symbol in the rom binary. --- rom/dev/tests/rom_integration_tests/main.rs | 1 + .../rom_integration_tests/test_cpu_fault.rs | 59 +++++++++++++++++++ 2 files changed, 60 insertions(+) create mode 100644 rom/dev/tests/rom_integration_tests/test_cpu_fault.rs diff --git a/rom/dev/tests/rom_integration_tests/main.rs b/rom/dev/tests/rom_integration_tests/main.rs index f75f0dc59c..41e9f2f095 100644 --- a/rom/dev/tests/rom_integration_tests/main.rs +++ b/rom/dev/tests/rom_integration_tests/main.rs @@ -5,6 +5,7 @@ mod helpers; mod rv32_unit_tests; mod test_capabilities; mod test_cfi; +mod test_cpu_fault; mod test_dice_derivations; mod test_fake_rom; mod test_fmcalias_derivation; diff --git a/rom/dev/tests/rom_integration_tests/test_cpu_fault.rs b/rom/dev/tests/rom_integration_tests/test_cpu_fault.rs new file mode 100644 index 0000000000..be13a06d40 --- /dev/null +++ b/rom/dev/tests/rom_integration_tests/test_cpu_fault.rs @@ -0,0 +1,59 @@ +// Licensed under the Apache-2.0 license + +use caliptra_builder::firmware; +use caliptra_hw_model::{BootParams, HwModel, InitParams}; +use elf::{endian::LittleEndian, ElfBytes}; + +#[test] +fn test_cpu_fault() { + const GLOBAL_EXCEPTION: u32 = 0x01050002; + + let rom_fwid = firmware::rom_from_env(); + + let elf_bytes = caliptra_builder::build_firmware_elf(rom_fwid).unwrap(); + let mut rom = caliptra_builder::elf2rom(&elf_bytes).unwrap(); + let elf = ElfBytes::::minimal_parse(&elf_bytes).unwrap(); + let symbol_table = elf.symbol_table().unwrap().unwrap().0; + let string_table = elf.symbol_table().unwrap().unwrap().1; + let rom_entry_offset = symbol_table + .iter() + .find(|symbol| string_table.get(symbol.st_name as usize).unwrap() == "rom_entry") + .unwrap() + .st_value as usize; + println!("rom_entry_offset is {}", rom_entry_offset); + + // Write an instruction that causes a cpu fault to the rom_entry offset + let illegal_instruction = [0xFF, 0xFF, 0xFF, 0xFF]; + rom[rom_entry_offset..rom_entry_offset + illegal_instruction.len()] + .copy_from_slice(&illegal_instruction); + + let mut hw = caliptra_hw_model::new(BootParams { + init_params: InitParams { + rom: &rom, + ..Default::default() + }, + ..Default::default() + }) + .unwrap(); + + hw.step_until(|m| m.soc_ifc().cptra_fw_error_fatal().read() == GLOBAL_EXCEPTION); + + let mcause = hw.soc_ifc().cptra_fw_extended_error_info().at(0).read(); + let mscause = hw.soc_ifc().cptra_fw_extended_error_info().at(1).read(); + let mepc = hw.soc_ifc().cptra_fw_extended_error_info().at(2).read(); + let ra = hw.soc_ifc().cptra_fw_extended_error_info().at(3).read(); + + println!( + "ROM Global Exception mcause=0x{:08X} mscause=0x{:08X} mepc=0x{:08X} ra=0x{:08X}", + mcause, mscause, mepc, ra, + ); + + // mcause must be illegal instruction + assert_eq!(mcause, 0x2); + // no mscause + assert_eq!(mscause, 0); + // mepc must be the value of the program counter at the failing instruction at rom_entry_offset + assert_eq!(mepc as usize, rom_entry_offset); + // return address won't be 0 + assert_ne!(ra, 0); +}