summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPavel Skripkin <paskripkin@gmail.com>2023-04-02 19:27:34 +0300
committerTom Rini <trini@konsulko.com>2023-04-25 22:31:27 +0300
commitde0095b4009b9d75d0c101643c3de60cb26d456d (patch)
treec9b1404deeaa285005a12023a63ede78fc35a0f9
parent23ff3e7b15d3734d349e2f80ca063ae2d0b53159 (diff)
downloadu-boot-de0095b4009b9d75d0c101643c3de60cb26d456d.tar.xz
arm64: interrupts: print FAR_ELx on sync exceptions
Default synchronous exceptions handler prints only esr and register dump. Sometimes it requiers to see an address which caused exceptions to understand what's going on ARM ARM in section D13.2.41 states that FAR_EL2 will contain meanfull value in case of ESR.EC holds 0x20, 0x21, 0x24, 0x25, 0x22, 0x34 or 0x35. Same applies for EL1. This patch adds function whivh determine current EL, gets correct FAR register and prints it on panic. Signed-off-by: Pavel Skripkin <paskripkin@gmail.com>
-rw-r--r--arch/arm/lib/interrupts_64.c38
1 files changed, 37 insertions, 1 deletions
diff --git a/arch/arm/lib/interrupts_64.c b/arch/arm/lib/interrupts_64.c
index 2e091415a4..125dc0bb39 100644
--- a/arch/arm/lib/interrupts_64.c
+++ b/arch/arm/lib/interrupts_64.c
@@ -37,6 +37,40 @@ static void show_efi_loaded_images(struct pt_regs *regs)
efi_print_image_infos((void *)regs->elr);
}
+static void dump_far(unsigned long esr)
+{
+ unsigned long el, far;
+
+ switch ((esr >> 26) & 0b111111) {
+ case 0x20:
+ case 0x21:
+ case 0x24:
+ case 0x25:
+ case 0x22:
+ case 0x34:
+ case 0x35:
+ break;
+ default:
+ return;
+ }
+
+ asm("mrs %0, CurrentEl": "=r" (el));
+
+ switch (el >> 2) {
+ case 1:
+ asm("mrs %0, FAR_EL1": "=r" (far));
+ break;
+ case 2:
+ asm("mrs %0, FAR_EL2": "=r" (far));
+ break;
+ default:
+ /* don't print anything to make output pretty */
+ return;
+ }
+
+ printf(", far 0x%lx", far);
+}
+
static void dump_instr(struct pt_regs *regs)
{
u32 *addr = (u32 *)(regs->elr & ~3UL);
@@ -165,7 +199,9 @@ void do_sync(struct pt_regs *pt_regs)
smh_emulate_trap(pt_regs))
return;
efi_restore_gd();
- printf("\"Synchronous Abort\" handler, esr 0x%08lx\n", pt_regs->esr);
+ printf("\"Synchronous Abort\" handler, esr 0x%08lx", pt_regs->esr);
+ dump_far(pt_regs->esr);
+ printf("\n");
show_regs(pt_regs);
show_efi_loaded_images(pt_regs);
panic("Resetting CPU ...\n");