The link register is at a different offset depending on processor
mode, so ensure it applies the correct adjustment.

Signed-off-by: Jim Posen <jim.po...@gmail.com>
---

 arch/arm/include/asm/u-boot-arm.h | 14 +++++++-------
 arch/arm/lib/interrupts.c         | 26 +++++++++++++-------------
 arch/arm/lib/vectors.S            |  4 +++-
 3 files changed, 23 insertions(+), 21 deletions(-)

diff --git a/arch/arm/include/asm/u-boot-arm.h 
b/arch/arm/include/asm/u-boot-arm.h
index 0b93cc48c5..6ebefa7c86 100644
--- a/arch/arm/include/asm/u-boot-arm.h
+++ b/arch/arm/include/asm/u-boot-arm.h
@@ -41,17 +41,17 @@ int board_init(void);
 struct pt_regs;
 
 void bad_mode(void);
-void do_undefined_instruction(struct pt_regs *pt_regs);
-void do_software_interrupt(struct pt_regs *pt_regs);
-void do_prefetch_abort(struct pt_regs *pt_regs);
-void do_data_abort(struct pt_regs *pt_regs);
-void do_not_used(struct pt_regs *pt_regs);
+void do_undefined_instruction(struct pt_regs *pt_regs, bool hyp_mode);
+void do_software_interrupt(struct pt_regs *pt_regs, bool hyp_mode);
+void do_prefetch_abort(struct pt_regs *pt_regs, bool hyp_mode);
+void do_data_abort(struct pt_regs *pt_regs, bool hyp_mode);
+void do_not_used(struct pt_regs *pt_regs, bool hyp_mode);
 #ifdef CONFIG_ARM64
 void do_fiq(struct pt_regs *pt_regs, unsigned int esr);
 void do_irq(struct pt_regs *pt_regs, unsigned int esr);
 #else
-void do_fiq(struct pt_regs *pt_regs);
-void do_irq(struct pt_regs *pt_regswq);
+void do_fiq(struct pt_regs *pt_regs, bool hyp_mode);
+void do_irq(struct pt_regs *pt_regswq, bool hyp_mode);
 #endif
 
 void reset_misc(void);
diff --git a/arch/arm/lib/interrupts.c b/arch/arm/lib/interrupts.c
index 6dc27d1d58..498401cdc5 100644
--- a/arch/arm/lib/interrupts.c
+++ b/arch/arm/lib/interrupts.c
@@ -135,17 +135,17 @@ static inline void fixup_pc(struct pt_regs *regs, int 
offset)
        regs->ARM_pc = pc | (regs->ARM_pc & PCMASK);
 }
 
-void do_undefined_instruction (struct pt_regs *pt_regs)
+void do_undefined_instruction(struct pt_regs *pt_regs, bool hyp_mode)
 {
        efi_restore_gd();
        printf ("undefined instruction\n");
-       fixup_pc(pt_regs, -4);
+       fixup_pc(pt_regs, hyp_mode ? 0 : thumb_mode(regs) ? -2 : -4);
        show_regs (pt_regs);
        show_efi_loaded_images(pt_regs);
        bad_mode ();
 }
 
-void do_software_interrupt (struct pt_regs *pt_regs)
+void do_software_interrupt(struct pt_regs *pt_regs, bool _hyp_mode)
 {
        efi_restore_gd();
        printf ("software interrupt\n");
@@ -155,51 +155,51 @@ void do_software_interrupt (struct pt_regs *pt_regs)
        bad_mode ();
 }
 
-void do_prefetch_abort (struct pt_regs *pt_regs)
+void do_prefetch_abort(struct pt_regs *pt_regs, bool hyp_mode)
 {
        efi_restore_gd();
        printf ("prefetch abort\n");
-       fixup_pc(pt_regs, -8);
+       fixup_pc(pt_regs, hyp_mode ? 0 : -4);
        show_regs (pt_regs);
        show_efi_loaded_images(pt_regs);
        bad_mode ();
 }
 
-void do_data_abort (struct pt_regs *pt_regs)
+void do_data_abort(struct pt_regs *pt_regs, bool hyp_mode)
 {
        efi_restore_gd();
        printf ("data abort\n");
-       fixup_pc(pt_regs, -8);
+       fixup_pc(pt_regs, hyp_mode ? 0 : -8);
        show_regs (pt_regs);
        show_efi_loaded_images(pt_regs);
        bad_mode ();
 }
 
-void do_not_used (struct pt_regs *pt_regs)
+void do_not_used(struct pt_regs *pt_regs, bool hyp_mode)
 {
        efi_restore_gd();
        printf ("not used\n");
-       fixup_pc(pt_regs, -8);
+       fixup_pc(pt_regs, hyp_mode ? 0 : -8);
        show_regs (pt_regs);
        show_efi_loaded_images(pt_regs);
        bad_mode ();
 }
 
-void do_fiq (struct pt_regs *pt_regs)
+void do_fiq(struct pt_regs *pt_regs, bool hyp_mode)
 {
        efi_restore_gd();
        printf ("fast interrupt request\n");
-       fixup_pc(pt_regs, -8);
+       fixup_pc(pt_regs, hyp_mode ? 0 : -4);
        show_regs (pt_regs);
        show_efi_loaded_images(pt_regs);
        bad_mode ();
 }
 
-void do_irq (struct pt_regs *pt_regs)
+void do_irq(struct pt_regs *pt_regs, bool hyp_mode)
 {
        efi_restore_gd();
        printf ("interrupt request\n");
-       fixup_pc(pt_regs, -8);
+       fixup_pc(pt_regs, hyp_mode ? 0 : -4);
        show_regs (pt_regs);
        show_efi_loaded_images(pt_regs);
        bad_mode ();
diff --git a/arch/arm/lib/vectors.S b/arch/arm/lib/vectors.S
index a36e3b7a43..dff2155dad 100644
--- a/arch/arm/lib/vectors.S
+++ b/arch/arm/lib/vectors.S
@@ -239,6 +239,7 @@ IRQ_STACK_START_IN:
        mov     r1, lr
        stmia   r5, {r0 - r3}   @ save sp_SVC, lr_SVC, pc, cpsr
        mov     r0, sp          @ save current stack into r0 (param register)
+       mov     r1, #0      @ set r1 param to 0, not hypervisor mode
        .endm
 
        .macro get_bad_stack
@@ -321,7 +322,8 @@ fiq:
        str     r1, [sp, #S_PC]
        str     r2, [sp, #S_PSR]
        str     r0, [sp, #S_OLD_R0]
-       mov     r0, sp
+       mov     r0, sp          @ set r0 param to struct pt_regs on stack
+       mov     r1, #1      @ set r1 param to 1, hypervisor mode
        .endm
 
 hyp_undefined_instruction:
-- 
2.25.1

Reply via email to