The issue was that the service routine was sometimes
returning with the wrong flags set in the MSR.

In this case, EIP bit was set while returning to User Mode
which is an illegal combination since exceptions are always
handled in privileged mode.

In order for MicroBlaze to take an interrupt, the MSR must have IE=1,
BIP=0 and EIP=0.

Signed-off-by: Stefan Asserhall <[email protected]>
Signed-off-by: Goran Bilski <[email protected]>
Signed-off-by: Michal Simek <[email protected]>
---

 arch/microblaze/kernel/entry.S | 19 +++++++++++++------
 1 file changed, 13 insertions(+), 6 deletions(-)

diff --git a/arch/microblaze/kernel/entry.S b/arch/microblaze/kernel/entry.S
index 285e8880e274..4e1b567becd6 100644
--- a/arch/microblaze/kernel/entry.S
+++ b/arch/microblaze/kernel/entry.S
@@ -245,6 +245,13 @@ syscall_debug_table:
        mts     rmsr , r11;                                             \
        RESTORE_REGS_GP
 
+#define RESTORE_REGS_RTBD \
+       lwi     r11, r1, PT_MSR;                                        \
+       andni   r11, r11, MSR_EIP;          /* clear EIP */             \
+       ori     r11, r11, MSR_EE | MSR_BIP; /* set EE and BIP */        \
+       mts     rmsr , r11;                                             \
+       RESTORE_REGS_GP
+
 #define SAVE_STATE     \
        swi     r1, r0, TOPHYS(PER_CPU(ENTRY_SP)); /* save stack */     \
        /* See if already in kernel mode.*/                             \
@@ -430,7 +437,7 @@ C_ENTRY(ret_from_trap):
        swi     CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE); /* save current */
        VM_OFF;
        tophys(r1,r1);
-       RESTORE_REGS;
+       RESTORE_REGS_RTBD;
        addik   r1, r1, PT_SIZE         /* Clean up stack space.  */
        lwi     r1, r1, PT_R1 - PT_SIZE;/* Restore user stack pointer. */
        bri     6f;
@@ -439,7 +446,7 @@ C_ENTRY(ret_from_trap):
 2:     set_bip;                        /*  Ints masked for state restore */
        VM_OFF;
        tophys(r1,r1);
-       RESTORE_REGS;
+       RESTORE_REGS_RTBD;
        addik   r1, r1, PT_SIZE         /* Clean up stack space.  */
        tovirt(r1,r1);
 6:
@@ -615,7 +622,7 @@ C_ENTRY(ret_from_exc):
        VM_OFF;
        tophys(r1,r1);
 
-       RESTORE_REGS;
+       RESTORE_REGS_RTBD;
        addik   r1, r1, PT_SIZE         /* Clean up stack space.  */
 
        lwi     r1, r1, PT_R1 - PT_SIZE; /* Restore user stack pointer. */
@@ -624,7 +631,7 @@ C_ENTRY(ret_from_exc):
 2:     set_bip;                        /* Ints masked for state restore */
        VM_OFF;
        tophys(r1,r1);
-       RESTORE_REGS;
+       RESTORE_REGS_RTBD;
        addik   r1, r1, PT_SIZE         /* Clean up stack space.  */
 
        tovirt(r1,r1);
@@ -850,7 +857,7 @@ dbtrap_call: /* Return point for kernel/user entry + 8 
because of rtsd r15, 8 */
        VM_OFF;
        tophys(r1,r1);
        /* MS: Restore all regs */
-       RESTORE_REGS
+       RESTORE_REGS_RTBD
        addik   r1, r1, PT_SIZE  /* Clean up stack space */
        lwi     r1, r1, PT_R1 - PT_SIZE; /* Restore user stack pointer */
 DBTRAP_return_user: /* MS: Make global symbol for debugging */
@@ -861,7 +868,7 @@ DBTRAP_return_user: /* MS: Make global symbol for debugging 
*/
 2:     VM_OFF;
        tophys(r1,r1);
        /* MS: Restore all regs */
-       RESTORE_REGS
+       RESTORE_REGS_RTBD
        lwi     r14, r1, PT_R14;
        lwi     r16, r1, PT_PC;
        addik   r1, r1, PT_SIZE; /* MS: Clean up stack space */
-- 
1.9.1

Reply via email to