]> git.karo-electronics.de Git - mv-sheeva.git/commitdiff
ARM: entry: avoid enabling interrupts in prefetch/data abort handlers
authorRussell King <rmk+kernel@arm.linux.org.uk>
Sat, 25 Jun 2011 10:44:06 +0000 (11:44 +0100)
committerRussell King <rmk+kernel@arm.linux.org.uk>
Sat, 2 Jul 2011 09:56:00 +0000 (10:56 +0100)
Avoid enabling interrupts if the parent context had interrupts enabled
in the abort handler assembly code, and move this into the breakpoint/
page/alignment fault handlers instead.

This gets rid of some special-casing for the breakpoint fault handlers
from the low level abort handler path.

Acked-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
arch/arm/kernel/entry-armv.S
arch/arm/kernel/entry-header.S
arch/arm/kernel/hw_breakpoint.c
arch/arm/mm/alignment.c
arch/arm/mm/fault.c

index d644d0240ad33b49cc7a21014f38e0d076178448..c46bafa2f6dc094d4df2d37d968f4f2d70ad96d5 100644 (file)
@@ -185,20 +185,15 @@ ENDPROC(__und_invalid)
 __dabt_svc:
        svc_entry
 
-       @
-       @ get ready to re-enable interrupts if appropriate
-       @
-       mrs     r9, cpsr
-       tst     r5, #PSR_I_BIT
-       biceq   r9, r9, #PSR_I_BIT
+#ifdef CONFIG_TRACE_IRQFLAGS
+       bl      trace_hardirqs_off
+#endif
 
        dabt_helper
 
        @
-       @ set desired IRQ state, then call main handler
+       @ call main handler
        @
-       debug_entry r1
-       msr     cpsr_c, r9
        mov     r2, sp
        bl      do_DataAbort
 
@@ -211,6 +206,12 @@ __dabt_svc:
        @ restore SPSR and restart the instruction
        @
        ldr     r5, [sp, #S_PSR]
+#ifdef CONFIG_TRACE_IRQFLAGS
+       tst     r5, #PSR_I_BIT
+       bleq    trace_hardirqs_on
+       tst     r5, #PSR_I_BIT
+       blne    trace_hardirqs_off
+#endif
        svc_exit r5                             @ return from exception
  UNWIND(.fnend         )
 ENDPROC(__dabt_svc)
@@ -307,16 +308,11 @@ ENDPROC(__und_svc)
 __pabt_svc:
        svc_entry
 
-       @
-       @ re-enable interrupts if appropriate
-       @
-       mrs     r9, cpsr
-       tst     r5, #PSR_I_BIT
-       biceq   r9, r9, #PSR_I_BIT
+#ifdef CONFIG_TRACE_IRQFLAGS
+       bl      trace_hardirqs_off
+#endif
 
        pabt_helper
-       debug_entry r1
-       msr     cpsr_c, r9                      @ Maybe enable interrupts
        mov     r2, sp                          @ regs
        bl      do_PrefetchAbort                @ call abort handler
 
@@ -329,6 +325,12 @@ __pabt_svc:
        @ restore SPSR and restart the instruction
        @
        ldr     r5, [sp, #S_PSR]
+#ifdef CONFIG_TRACE_IRQFLAGS
+       tst     r5, #PSR_I_BIT
+       bleq    trace_hardirqs_on
+       tst     r5, #PSR_I_BIT
+       blne    trace_hardirqs_off
+#endif
        svc_exit r5                             @ return from exception
  UNWIND(.fnend         )
 ENDPROC(__pabt_svc)
@@ -412,11 +414,6 @@ __dabt_usr:
        kuser_cmpxchg_check
        dabt_helper
 
-       @
-       @ IRQs on, then call the main handler
-       @
-       debug_entry r1
-       enable_irq
        mov     r2, sp
        adr     lr, BSYM(ret_from_exception)
        b       do_DataAbort
@@ -663,8 +660,6 @@ ENDPROC(__und_usr_unknown)
 __pabt_usr:
        usr_entry
        pabt_helper
-       debug_entry r1
-       enable_irq                              @ Enable interrupts
        mov     r2, sp                          @ regs
        bl      do_PrefetchAbort                @ call abort handler
  UNWIND(.fnend         )
index 051166c2a932cfed1620bb3a5612383ffff12149..4d6ad8348e892157fb6642e55a551f943d3eb338 100644 (file)
        .endm
 #endif /* !CONFIG_THUMB2_KERNEL */
 
-       @
-       @ Debug exceptions are taken as prefetch or data aborts.
-       @ We must disable preemption during the handler so that
-       @ we can access the debug registers safely.
-       @
-       .macro  debug_entry, fsr
-#if defined(CONFIG_HAVE_HW_BREAKPOINT) && defined(CONFIG_PREEMPT)
-       ldr     r4, =0x40f              @ mask out fsr.fs
-       and     r5, r4, \fsr
-       cmp     r5, #2                  @ debug exception
-       bne     1f
-       get_thread_info r10
-       ldr     r6, [r10, #TI_PREEMPT]  @ get preempt count
-       add     r11, r6, #1             @ increment it
-       str     r11, [r10, #TI_PREEMPT]
-1:
-#endif
-       .endm
-
 /*
  * These are the registers used in the syscall handler, and allow us to
  * have in theory up to 7 arguments to a function - r0 to r6.
index 87acc25d7a3e203646f2ee71f1d7c711304d52f2..a927ca1f5566ce67055296f9a45f9e8714dcda51 100644 (file)
@@ -796,7 +796,7 @@ unlock:
 
 /*
  * Called from either the Data Abort Handler [watchpoint] or the
- * Prefetch Abort Handler [breakpoint] with preemption disabled.
+ * Prefetch Abort Handler [breakpoint] with interrupts disabled.
  */
 static int hw_breakpoint_pending(unsigned long addr, unsigned int fsr,
                                 struct pt_regs *regs)
@@ -804,8 +804,10 @@ static int hw_breakpoint_pending(unsigned long addr, unsigned int fsr,
        int ret = 0;
        u32 dscr;
 
-       /* We must be called with preemption disabled. */
-       WARN_ON(preemptible());
+       preempt_disable();
+
+       if (interrupts_enabled(regs))
+               local_irq_enable();
 
        /* We only handle watchpoints and hardware breakpoints. */
        ARM_DBG_READ(c1, 0, dscr);
@@ -824,10 +826,6 @@ static int hw_breakpoint_pending(unsigned long addr, unsigned int fsr,
                ret = 1; /* Unhandled fault. */
        }
 
-       /*
-        * Re-enable preemption after it was disabled in the
-        * low-level exception handling code.
-        */
        preempt_enable();
 
        return ret;
index 724ba3bce72c952ff44645d2a50e5566b568c943..be7c638b648bb9771665719adbb2c7e74b5aafef 100644 (file)
@@ -727,6 +727,9 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
        int isize = 4;
        int thumb2_32b = 0;
 
+       if (interrupts_enabled(regs))
+               local_irq_enable();
+
        instrptr = instruction_pointer(regs);
 
        fs = get_fs();
index bc0e1d88fd3ba8b7863edfc9eca9cb11d90413dd..20e5d5120609103376d3a041e33d7b6475fc0a65 100644 (file)
@@ -285,6 +285,10 @@ do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
        tsk = current;
        mm  = tsk->mm;
 
+       /* Enable interrupts if they were enabled in the parent context. */
+       if (interrupts_enabled(regs))
+               local_irq_enable();
+
        /*
         * If we're in an interrupt or have no user
         * context, we must not take the fault..