summaryrefslogtreecommitdiff
path: root/arch/arm/lib
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/lib')
-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 066c172bb3..80869adb61 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 ();
}