Traps: print more detailed exception report
This commit is contained in:
parent
373f4753dc
commit
09003a7da2
|
@ -55,6 +55,7 @@ use {
|
|||
barrier,
|
||||
regs::{RegisterReadOnly, RegisterReadWrite, ESR_EL1, FAR_EL1, VBAR_EL1},
|
||||
},
|
||||
register::{register_bitfields, LocalRegisterCopy},
|
||||
snafu::Snafu,
|
||||
};
|
||||
|
||||
|
@ -151,6 +152,152 @@ unsafe extern "C" fn current_elx_serror(e: &mut ExceptionContext) {
|
|||
endless_sleep()
|
||||
}
|
||||
|
||||
fn cause_to_string(cause: u64) -> &'static str {
|
||||
if cause == ESR_EL1::EC::DataAbortCurrentEL.read(ESR_EL1::EC) {
|
||||
"Data Alignment Check"
|
||||
} else {
|
||||
"Unknown"
|
||||
}
|
||||
}
|
||||
|
||||
register_bitfields! {
|
||||
u64,
|
||||
/// ISS structure for Data Abort exceptions
|
||||
ISS_DA [
|
||||
/// Instruction Syndrome Valid. Indicates whether the syndrome information in ISS[23:14] is valid.
|
||||
/// (This includes SAS, SSE, SRT, SF, and AR)
|
||||
ISV OFFSET(24) NUMBITS(1) [],
|
||||
SAS OFFSET(22) NUMBITS(2) [
|
||||
Byte = 0b00,
|
||||
Halfword = 0b01,
|
||||
Word = 0b10,
|
||||
DoubleWord = 0b11
|
||||
],
|
||||
SSE OFFSET(21) NUMBITS(1) [],
|
||||
SRT OFFSET(16) NUMBITS(5) [],
|
||||
SF OFFSET(15) NUMBITS(1) [],
|
||||
AR OFFSET(14) NUMBITS(1) [],
|
||||
VNCR OFFSET(13) NUMBITS(1) [],
|
||||
SET OFFSET(11) NUMBITS(2) [
|
||||
UER = 0b00, // Recoverable state
|
||||
UC = 0b10, // Uncontainable
|
||||
UEO = 0b11 // Restartable state
|
||||
],
|
||||
FNV OFFSET(10) NUMBITS(1) [],
|
||||
EA OFFSET(9) NUMBITS(1) [],
|
||||
CM OFFSET(8) NUMBITS(1) [],
|
||||
S1PTW OFFSET(7) NUMBITS(1) [],
|
||||
WNR OFFSET(6) NUMBITS(1) [],
|
||||
DFSC OFFSET(0) NUMBITS(6) [
|
||||
/// Address size fault, level 0 of translation or translation table base register.
|
||||
AddressSizeTL0 = 0b000000,
|
||||
/// Address size fault, level 1.
|
||||
AddressSizeTL1 = 0b000001,
|
||||
///Address size fault, level 2.
|
||||
AddressSizeTL2 = 0b000010,
|
||||
/// Address size fault, level 3.
|
||||
AddressSizeTL3 = 0b000011,
|
||||
/// Translation fault, level 0.
|
||||
TranslationFaultTL0 = 0b000100,
|
||||
/// Translation fault, level 1.
|
||||
TranslationFaultTL1 = 0b000101,
|
||||
/// Translation fault, level 2.
|
||||
TranslationFaultTL2 = 0b000110,
|
||||
/// Translation fault, level 3.
|
||||
TranslationFaultTL3 = 0b000111,
|
||||
/// Access flag fault, level 1.
|
||||
AccessFaultTL1 = 0b001001,
|
||||
/// Access flag fault, level 2.
|
||||
AccessFaultTL2 = 0b001010,
|
||||
/// Access flag fault, level 3.
|
||||
AccessFaultTL3 = 0b001011,
|
||||
/// Permission fault, level 1.
|
||||
PermissionFaultTL1 = 0b001101,
|
||||
/// Permission fault, level 2.
|
||||
PermissionFaultTL2 = 0b001110,
|
||||
/// Permission fault, level 3.
|
||||
PermissionFaultTL3 = 0b001111,
|
||||
/// Synchronous External abort, not on translation table walk or hardware update of translation table.
|
||||
SyncExternalAbort = 0b010000,
|
||||
/// Synchronous Tag Check Fault.
|
||||
/// (When FEAT_MTE is implemented)
|
||||
SyncTagCheckFault = 0b010001,
|
||||
/// Synchronous External abort on translation table walk or hardware update of translation table, level 0.
|
||||
SyncAbortOnTranslationTL0 = 0b010100,
|
||||
/// Synchronous External abort on translation table walk or hardware update of translation table, level 1.
|
||||
SyncAbortOnTranslationTL1 = 0b010101,
|
||||
/// Synchronous External abort on translation table walk or hardware update of translation table, level 2.
|
||||
SyncAbortOnTranslationTL2 = 0b010110,
|
||||
/// Synchronous External abort on translation table walk or hardware update of translation table, level 3.
|
||||
SyncAbortOnTranslationTL3 = 0b010111,
|
||||
/// Synchronous parity or ECC error on memory access, not on translation table walk.
|
||||
/// (When FEAT_RAS is not implemented)
|
||||
SyncParityError = 0b011000,
|
||||
/// Synchronous parity or ECC error on memory access on translation table walk or hardware update of translation table, level 0.
|
||||
/// (When FEAT_RAS is not implemented)
|
||||
SyncParityErrorOnTranslationTL0 = 0b011100,
|
||||
/// Synchronous parity or ECC error on memory access on translation table walk or hardware update of translation table, level 1.
|
||||
/// (When FEAT_RAS is not implemented)
|
||||
SyncParityErrorOnTranslationTL1 = 0b011101,
|
||||
/// Synchronous parity or ECC error on memory access on translation table walk or hardware update of translation table, level 2.
|
||||
/// (When FEAT_RAS is not implemented)
|
||||
SyncParityErrorOnTranslationTL2 = 0b011110,
|
||||
/// Synchronous parity or ECC error on memory access on translation table walk or hardware update of translation table, level 3.
|
||||
/// (When FEAT_RAS is not implemented)
|
||||
SyncParityErrorOnTranslationTL3 = 0b011111,
|
||||
/// Alignment fault.
|
||||
AlignmentFault = 0b100001,
|
||||
/// TLB conflict abort.
|
||||
TlbConflictAbort = 0b110000,
|
||||
/// Unsupported atomic hardware update fault.
|
||||
/// (When FEAT_HAFDBS is implemented)
|
||||
UnsupportedAtomicUpdate = 0b110001,
|
||||
/// IMPLEMENTATION DEFINED fault (Lockdown).
|
||||
Lockdown = 0b110100,
|
||||
/// IMPLEMENTATION DEFINED fault (Unsupported Exclusive or Atomic access).
|
||||
UnsupportedAccess = 0b110101
|
||||
]
|
||||
]
|
||||
}
|
||||
|
||||
type IssForDataAbort = LocalRegisterCopy<u64, ISS_DA::Register>;
|
||||
|
||||
fn iss_dfsc_to_string(iss: IssForDataAbort) -> &'static str {
|
||||
match iss.read_as_enum(ISS_DA::DFSC) {
|
||||
Some(ISS_DA::DFSC::Value::AddressSizeTL0) => "Address size fault, level 0 of translation or translation table base register",
|
||||
Some(ISS_DA::DFSC::Value::AddressSizeTL1) => "Address size fault, level 1",
|
||||
Some(ISS_DA::DFSC::Value::AddressSizeTL2) => "Address size fault, level 2",
|
||||
Some(ISS_DA::DFSC::Value::AddressSizeTL3) => "Address size fault, level 3",
|
||||
Some(ISS_DA::DFSC::Value::TranslationFaultTL0) => "Translation fault, level 0",
|
||||
Some(ISS_DA::DFSC::Value::TranslationFaultTL1) => "Translation fault, level 1",
|
||||
Some(ISS_DA::DFSC::Value::TranslationFaultTL2) => "Translation fault, level 2",
|
||||
Some(ISS_DA::DFSC::Value::TranslationFaultTL3) => "Translation fault, level 3",
|
||||
Some(ISS_DA::DFSC::Value::AccessFaultTL1) => "Access flag fault, level 1",
|
||||
Some(ISS_DA::DFSC::Value::AccessFaultTL2) => "Access flag fault, level 2",
|
||||
Some(ISS_DA::DFSC::Value::AccessFaultTL3) => "Access flag fault, level 3",
|
||||
Some(ISS_DA::DFSC::Value::PermissionFaultTL1) => "Permission fault, level 1",
|
||||
Some(ISS_DA::DFSC::Value::PermissionFaultTL2) => "Permission fault, level 2",
|
||||
Some(ISS_DA::DFSC::Value::PermissionFaultTL3) => "Permission fault, level 3",
|
||||
Some(ISS_DA::DFSC::Value::SyncExternalAbort) => "Synchronous External abort, not on translation table walk or hardware update of translation table",
|
||||
Some(ISS_DA::DFSC::Value::SyncTagCheckFault) => "Synchronous Tag Check Fault",
|
||||
Some(ISS_DA::DFSC::Value::SyncAbortOnTranslationTL0) => "Synchronous External abort on translation table walk or hardware update of translation table, level 0",
|
||||
Some(ISS_DA::DFSC::Value::SyncAbortOnTranslationTL1) => "Synchronous External abort on translation table walk or hardware update of translation table, level 1",
|
||||
Some(ISS_DA::DFSC::Value::SyncAbortOnTranslationTL2) => "Synchronous External abort on translation table walk or hardware update of translation table, level 2",
|
||||
Some(ISS_DA::DFSC::Value::SyncAbortOnTranslationTL3) => "Synchronous External abort on translation table walk or hardware update of translation table, level 3",
|
||||
Some(ISS_DA::DFSC::Value::SyncParityError) => "Synchronous parity or ECC error on memory access, not on translation table walk",
|
||||
Some(ISS_DA::DFSC::Value::SyncParityErrorOnTranslationTL0) => "Synchronous parity or ECC error on memory access on translation table walk or hardware update of translation table, level 0",
|
||||
Some(ISS_DA::DFSC::Value::SyncParityErrorOnTranslationTL1) => "Synchronous parity or ECC error on memory access on translation table walk or hardware update of translation table, level 1",
|
||||
Some(ISS_DA::DFSC::Value::SyncParityErrorOnTranslationTL2) => "Synchronous parity or ECC error on memory access on translation table walk or hardware update of translation table, level 2",
|
||||
Some(ISS_DA::DFSC::Value::SyncParityErrorOnTranslationTL3) => "Synchronous parity or ECC error on memory access on translation table walk or hardware update of translation table, level 3",
|
||||
Some(ISS_DA::DFSC::Value::AlignmentFault) => "Alignment fault",
|
||||
Some(ISS_DA::DFSC::Value::TlbConflictAbort) => "TLB conflict abort",
|
||||
Some(ISS_DA::DFSC::Value::UnsupportedAtomicUpdate) => "Unsupported atomic hardware update fault",
|
||||
Some(ISS_DA::DFSC::Value::Lockdown) => "Lockdown (IMPLEMENTATION DEFINED fault)",
|
||||
Some(ISS_DA::DFSC::Value::UnsupportedAccess) => "Unsupported Exclusive or Atomic access (IMPLEMENTATION DEFINED fault)",
|
||||
_ => "Unknown",
|
||||
}
|
||||
}
|
||||
|
||||
// unsafe extern "C" fn lower_aarch64_synchronous(e: &mut ExceptionContext);
|
||||
// unsafe extern "C" fn lower_aarch64_irq(e: &mut ExceptionContext);
|
||||
// unsafe extern "C" fn lower_aarch64_serror(e: &mut ExceptionContext);
|
||||
|
@ -163,12 +310,62 @@ unsafe extern "C" fn current_elx_serror(e: &mut ExceptionContext) {
|
|||
/// Not for production use!
|
||||
fn synchronous_common(e: &mut ExceptionContext) {
|
||||
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);
|
||||
let cause = ESR_EL1.read(ESR_EL1::EC);
|
||||
println!(
|
||||
" EC: {:#06b} (cause) -- {}",
|
||||
cause,
|
||||
cause_to_string(cause)
|
||||
);
|
||||
|
||||
// Print more details about Data Alignment Check
|
||||
if cause == ESR_EL1::EC::DataAbortCurrentEL.read(ESR_EL1::EC) {
|
||||
let iss = ESR_EL1.read(ESR_EL1::ISS);
|
||||
let iss = IssForDataAbort::new(iss);
|
||||
if iss.is_set(ISS_DA::ISV) {
|
||||
println!(
|
||||
" Access size: {} bytes ({}signed) to {}{}",
|
||||
2u64.pow(iss.read(ISS_DA::SAS) as u32),
|
||||
if iss.is_set(ISS_DA::SSE) { "" } else { "un" },
|
||||
if iss.is_set(ISS_DA::SF) { "x" } else { "r" },
|
||||
iss.read(ISS_DA::SRT)
|
||||
);
|
||||
println!(
|
||||
" Acq/Rel semantics: {}present",
|
||||
if iss.is_set(ISS_DA::AR) { "" } else { "not " }
|
||||
);
|
||||
}
|
||||
// data abort specific encoding
|
||||
println!(
|
||||
" {} address {:#016x} ({}valid)",
|
||||
if iss.is_set(ISS_DA::WNR) {
|
||||
"Writing to"
|
||||
} else {
|
||||
"Reading from"
|
||||
},
|
||||
FAR_EL1.get(),
|
||||
if iss.is_set(ISS_DA::FNV) { "not " } else { "" }
|
||||
);
|
||||
println!(" Specific fault: {}", iss_dfsc_to_string(iss));
|
||||
} else {
|
||||
println!(" FAR_EL1: {:#016x} (location)", FAR_EL1.get());
|
||||
println!(" Stack: {:#016x}", e.spsr_el1);
|
||||
println!(" ELR_EL1: {:#010x}", e.elr_el1);
|
||||
}
|
||||
|
||||
println!(" x00: 0000000000000000 x01: {:016x}", e.gpr.x[0]);
|
||||
|
||||
for index in 0..15 {
|
||||
println!(
|
||||
" x{:02}: {:016x} x{:02}: {:016x}",
|
||||
index * 2 + 2,
|
||||
e.gpr.x[index * 2 + 1],
|
||||
index * 2 + 3,
|
||||
e.gpr.x[index * 2 + 2]
|
||||
);
|
||||
}
|
||||
|
||||
println!(
|
||||
" Incrementing ELR_EL1 by 4 now to continue with the first \
|
||||
" Incrementing ELR_EL1 by 4 to continue with the first \
|
||||
instruction after the exception!"
|
||||
);
|
||||
|
||||
|
|
Loading…
Reference in New Issue