aboutsummaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorLothar Waßmann <LW@KARO-electronics.de>2017-06-08 09:52:33 +0200
committerTom Rini <trini@konsulko.com>2017-06-12 08:38:39 -0400
commitc88823612d6ff69a64a86456eb56a9576911466b (patch)
tree7eead6bcd8baf583efa19a5589401c38a077fc61 /arch
parent53d4ed704b43a5ffbfe9784544a722edb7a7edf5 (diff)
downloadu-boot-c88823612d6ff69a64a86456eb56a9576911466b.zip
u-boot-c88823612d6ff69a64a86456eb56a9576911466b.tar.gz
u-boot-c88823612d6ff69a64a86456eb56a9576911466b.tar.bz2
arm: adjust PC displayed in exception handlers to point to the failing instruction
Adjust the program counter register to point to the failing instruction depending on the exeption type. This makes it easier to localize the offending instruction leading to a fatal exception. Signed-off-by: Lothar Waßmann <LW@KARO-electronics.de>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/lib/interrupts.c14
1 files changed, 14 insertions, 0 deletions
diff --git a/arch/arm/lib/interrupts.c b/arch/arm/lib/interrupts.c
index 066c172..80869ad 100644
--- a/arch/arm/lib/interrupts.c
+++ b/arch/arm/lib/interrupts.c
@@ -93,10 +93,18 @@ void show_regs (struct pt_regs *regs)
thumb_mode (regs) ? " (T)" : "");
}
+/* fixup PC to point to the instruction leading to the exception */
+static inline void fixup_pc(struct pt_regs *regs, int offset)
+{
+ uint32_t pc = instruction_pointer(regs) + offset;
+ regs->ARM_pc = pc | (regs->ARM_pc & PCMASK);
+}
+
void do_undefined_instruction (struct pt_regs *pt_regs)
{
efi_restore_gd();
printf ("undefined instruction\n");
+ fixup_pc(pt_regs, -4);
show_regs (pt_regs);
bad_mode ();
}
@@ -105,6 +113,7 @@ void do_software_interrupt (struct pt_regs *pt_regs)
{
efi_restore_gd();
printf ("software interrupt\n");
+ fixup_pc(pt_regs, -4);
show_regs (pt_regs);
bad_mode ();
}
@@ -113,6 +122,7 @@ void do_prefetch_abort (struct pt_regs *pt_regs)
{
efi_restore_gd();
printf ("prefetch abort\n");
+ fixup_pc(pt_regs, -8);
show_regs (pt_regs);
bad_mode ();
}
@@ -121,6 +131,7 @@ void do_data_abort (struct pt_regs *pt_regs)
{
efi_restore_gd();
printf ("data abort\n");
+ fixup_pc(pt_regs, -8);
show_regs (pt_regs);
bad_mode ();
}
@@ -129,6 +140,7 @@ void do_not_used (struct pt_regs *pt_regs)
{
efi_restore_gd();
printf ("not used\n");
+ fixup_pc(pt_regs, -8);
show_regs (pt_regs);
bad_mode ();
}
@@ -137,6 +149,7 @@ void do_fiq (struct pt_regs *pt_regs)
{
efi_restore_gd();
printf ("fast interrupt request\n");
+ fixup_pc(pt_regs, -8);
show_regs (pt_regs);
bad_mode ();
}
@@ -145,6 +158,7 @@ void do_irq (struct pt_regs *pt_regs)
{
efi_restore_gd();
printf ("interrupt request\n");
+ fixup_pc(pt_regs, -8);
show_regs (pt_regs);
bad_mode ();
}