Kernel/aarch64: Add Fault Address Register (FAR_EL1)

And use it for printing the virtual address when an exception has
happened that set the register, such as data aborts and instruction
aborts.
This commit is contained in:
Timon Kruiper 2022-12-20 19:03:10 +01:00 committed by Sam Atkins
parent 344ffda8cb
commit 0226390b21
Notes: sideshowbarker 2024-07-17 02:55:26 +09:00
2 changed files with 39 additions and 0 deletions

View file

@ -488,6 +488,22 @@ struct ESR_EL1 {
};
static_assert(sizeof(ESR_EL1) == 8);
// D17.2.40 FAR_EL1, Fault Address Register (EL1)
struct FAR_EL1 {
u64 virtual_address;
static inline FAR_EL1 read()
{
FAR_EL1 far_el1;
asm("mrs %[value], far_el1"
: [value] "=r"(far_el1));
return far_el1;
}
};
static_assert(sizeof(FAR_EL1) == 8);
// D17.2.37 ESR_EL1, Exception Syndrome Register (EL1)
static inline StringView exception_class_to_string(u8 exception_class)
{
@ -571,6 +587,27 @@ static inline StringView exception_class_to_string(u8 exception_class)
}
}
// D17.2.40 FAR_EL1, Fault Address Register (EL1)
static inline bool exception_class_has_set_far(u8 exception_class)
{
// Faulting Virtual Address for synchronous exceptions taken to EL1. Exceptions that set the
// FAR_EL1 are Instruction Aborts (EC 0x20 or 0x21), Data Aborts (EC 0x24 or 0x25), PC alignment
// faults (EC 0x22), and Watchpoints (EC 0x34 or 0x35). ESR_EL1.EC holds the EC value for the
// exception.
switch (exception_class) {
case 0x20:
case 0x21:
case 0x22:
case 0x24:
case 0x25:
case 0x34:
case 0x35:
return true;
default:
return false;
}
}
// https://developer.arm.com/documentation/ddi0601/2020-12/AArch64-Registers/DAIF--Interrupt-Mask-Bits?lang=en
// DAIF, Interrupt Mask Bits
struct DAIF {

View file

@ -52,6 +52,8 @@ extern "C" void exception_common(Kernel::TrapFrame const* const trap_frame)
auto esr_el1 = Kernel::Aarch64::ESR_EL1::read();
dbgln("esr_el1: EC({:#b}) IL({:#b}) ISS({:#b}) ISS2({:#b})", esr_el1.EC, esr_el1.IL, esr_el1.ISS, esr_el1.ISS2);
dbgln("Exception Class: {}", Aarch64::exception_class_to_string(esr_el1.EC));
if (Aarch64::exception_class_has_set_far(esr_el1.EC))
dbgln("Faulting Virtual Address: 0x{:x}", Aarch64::FAR_EL1::read().virtual_address);
dump_backtrace_from_base_pointer(regs->x[29]);
}