Add debug registers output in exception handler

This commit is contained in:
Berkus Decker 2019-03-03 22:06:58 +02:00
parent 673edf2261
commit 3923e7c838
1 changed files with 145 additions and 2 deletions
src/arch/aarch64

View File

@ -84,6 +84,145 @@ unsafe extern "C" fn default_exception_handler() -> ! {
endless_sleep()
}
mod esr_el1 {
// use cortex_a::{sys_coproc_read_raw, sys_coproc_write_raw};
use register::{cpu::RegisterReadWrite, register_bitfields};
pub struct Reg;
register_bitfields! {
u64,
ESR_EL1 [
ISS OFFSET(0) NUMBITS(25) [], // @todo Additional ISS encodings
IL OFFSET(25) NUMBITS(1) [], // Instruction Length
EC OFFSET(26) NUMBITS(6) [
Unknown = 0b000_000,
TrappedWfiOrWfe = 0b000_001,
TrappedMcrOrMrc = 0b000_011,
TrappedMcrrOrMrrc = 0b000_100,
TrappedMcrOrMrc2 = 0b000_101,
TrappedLdcOrStc = 0b000_110,
TrappedAdvSIMD = 0b000_111,
TrappedMrrc = 0b001_100,
IllegalExecState = 0b001_110,
SvcInAArch32 = 0b010_001,
SvcInAArch64 = 0b010_101,
TrappedMrsOrMsr = 0b011_000,
TrappedSve = 0b011_001,
InsnAbortFromLowerEL = 0b100_000,
InsnAbortFromSameEL = 0b100_001,
PcAlignmentFault = 0b100_010,
DataAbortFromLowerEL = 0b100_100,
DataAbortFromSameEL = 0b100_101,
SpAlignmentFault = 0b100_110,
TrappedFpuFromAArch32 = 0b101_000,
TrappedFpuFromAArch64 = 0b101_100,
SError = 0b101_111,
BreakpointFromLowerEL = 0b110_000,
BreakpointFromSameEL = 0b110_001,
SoftwareStepFromLowerEL = 0b110_010,
SoftwareStepFromSameEL = 0b110_011,
WatchpointFromLowerEL = 0b110_100,
WatchpointFromSameEL = 0b110_101,
BrkptInAArch32 = 0b111_000,
BrkInAArch64 = 0b111_100
]
]
}
impl RegisterReadWrite<u64, ESR_EL1::Register> for Reg {
// sys_coproc_read_raw!(u64, "ESR_EL1");
// sys_coproc_write_raw!(u64, "ESR_EL1");
// Manually unmacroed
/// Reads the raw bits of the CPU register.
#[inline]
fn get(&self) -> u64 {
match () {
#[cfg(target_arch = "aarch64")]
() => {
let reg;
unsafe {
asm!(concat!("mrs", " $0, ", "ESR_EL1") : "=r"(reg) ::: "volatile");
}
reg
}
#[cfg(not(target_arch = "aarch64"))]
() => unimplemented!(),
}
}
/// Writes raw bits to the CPU register.
#[cfg_attr(not(target_arch = "aarch64"), allow(unused_variables))]
#[inline]
fn set(&self, value: u64) {
match () {
#[cfg(target_arch = "aarch64")]
() => unsafe {
asm!(concat!("msr", " ", "ESR_EL1", ", $0") :: "r"(value) :: "volatile")
},
#[cfg(not(target_arch = "aarch64"))]
() => unimplemented!(),
}
}
}
pub static ESR_EL1: Reg = Reg {};
}
mod far_el1 {
use register::cpu::RegisterReadWrite;
pub struct Reg;
impl RegisterReadWrite<u64, ()> for Reg {
// sys_coproc_read_raw!(u64, "FAR_EL1");
// sys_coproc_write_raw!(u64, "FAR_EL1");
// Manually unmacroed
/// Reads the raw bits of the CPU register.
#[inline]
fn get(&self) -> u64 {
match () {
#[cfg(target_arch = "aarch64")]
() => {
let reg;
unsafe {
asm!(concat!("mrs", " $0, ", "FAR_EL1") : "=r"(reg) ::: "volatile");
}
reg
}
#[cfg(not(target_arch = "aarch64"))]
() => unimplemented!(),
}
}
/// Writes raw bits to the CPU register.
#[cfg_attr(not(target_arch = "aarch64"), allow(unused_variables))]
#[inline]
fn set(&self, value: u64) {
match () {
#[cfg(target_arch = "aarch64")]
() => unsafe {
asm!(concat!("msr", " ", "FAR_EL1", ", $0") :: "r"(value) :: "volatile")
},
#[cfg(not(target_arch = "aarch64"))]
() => unimplemented!(),
}
}
}
pub static FAR_EL1: Reg = Reg {};
}
use esr_el1::ESR_EL1;
use far_el1::FAR_EL1;
// To implement an exception handler, overwrite it by defining the respective
// function below.
// Don't forget the #[no_mangle] attribute.
@ -107,7 +246,11 @@ unsafe extern "C" fn default_exception_handler() -> ! {
#[no_mangle]
unsafe extern "C" fn current_elx_synchronous(e: &mut ExceptionContext) {
println!("[!] A synchronous exception happened.");
println!(" ELR_EL1: {:#010X}", e.elr_el1);
println!(" ESR_EL1: {:#010x} (syndrome)", ESR_EL1.get());
println!(" EC: {:#06b} (cause)", ESR_EL1.read(ESR_EL1::EC));
println!(" FAR_EL1: {:#016x} (location)", FAR_EL1.get());
println!(" ELR_EL1: {:#010x}", e.elr_el1);
println!(
" Incrementing ELR_EL1 by 4 now to continue with the first \
instruction after the exception!"
@ -115,6 +258,6 @@ unsafe extern "C" fn current_elx_synchronous(e: &mut ExceptionContext) {
e.elr_el1 += 4;
println!(" ELR_EL1 modified: {:#010X}", e.elr_el1);
println!(" ELR_EL1 modified: {:#010x}", e.elr_el1);
println!(" Returning from exception...\n");
}