Merge branch 'for-linus' of git://git.armlinux.org.uk/~rmk/linux-arm
[muen/linux.git] / arch / arm / kernel / entry-common.S
index e33c32d561934c36b84d294d85ff27fa05aa0ec2..ca3614dc6938e1595f71a095f53456eb26701bec 100644 (file)
 
 #include "entry-header.S"
 
+saved_psr      .req    r8
+#if defined(CONFIG_TRACE_IRQFLAGS) || defined(CONFIG_CONTEXT_TRACKING)
+saved_pc       .req    r9
+#define TRACE(x...) x
+#else
+saved_pc       .req    lr
+#define TRACE(x...)
+#endif
 
        .align  5
 #if !(IS_ENABLED(CONFIG_TRACE_IRQFLAGS) || IS_ENABLED(CONFIG_CONTEXT_TRACKING))
@@ -146,16 +154,17 @@ ENTRY(vector_swi)
  ARM(  stmdb   r8, {sp, lr}^           )       @ Calling sp, lr
  THUMB(        mov     r8, sp                  )
  THUMB(        store_user_sp_lr r8, r10, S_SP  )       @ calling sp, lr
-       mrs     r8, spsr                        @ called from non-FIQ mode, so ok.
-       str     lr, [sp, #S_PC]                 @ Save calling PC
-       str     r8, [sp, #S_PSR]                @ Save CPSR
+       mrs     saved_psr, spsr                 @ called from non-FIQ mode, so ok.
+ TRACE(        mov     saved_pc, lr            )
+       str     saved_pc, [sp, #S_PC]           @ Save calling PC
+       str     saved_psr, [sp, #S_PSR]         @ Save CPSR
        str     r0, [sp, #S_OLD_R0]             @ Save OLD_R0
 #endif
        zero_fp
        alignment_trap r10, ip, __cr_alignment
-       enable_irq
-       ct_user_exit
-       get_thread_info tsk
+       asm_trace_hardirqs_on save=0
+       enable_irq_notrace
+       ct_user_exit save=0
 
        /*
         * Get the system call number.
@@ -168,11 +177,11 @@ ENTRY(vector_swi)
         * value to determine if it is an EABI or an old ABI call.
         */
 #ifdef CONFIG_ARM_THUMB
-       tst     r8, #PSR_T_BIT
+       tst     saved_psr, #PSR_T_BIT
        movne   r10, #0                         @ no thumb OABI emulation
- USER( ldreq   r10, [lr, #-4]          )       @ get SWI instruction
+ USER( ldreq   r10, [saved_pc, #-4]    )       @ get SWI instruction
 #else
- USER( ldr     r10, [lr, #-4]          )       @ get SWI instruction
+ USER( ldr     r10, [saved_pc, #-4]    )       @ get SWI instruction
 #endif
  ARM_BE8(rev   r10, r10)                       @ little endian instruction
 
@@ -183,15 +192,17 @@ ENTRY(vector_swi)
         */
 #elif defined(CONFIG_ARM_THUMB)
        /* Legacy ABI only, possibly thumb mode. */
-       tst     r8, #PSR_T_BIT                  @ this is SPSR from save_user_regs
+       tst     saved_psr, #PSR_T_BIT           @ this is SPSR from save_user_regs
        addne   scno, r7, #__NR_SYSCALL_BASE    @ put OS number in
- USER( ldreq   scno, [lr, #-4]         )
+ USER( ldreq   scno, [saved_pc, #-4]   )
 
 #else
        /* Legacy ABI only. */
- USER( ldr     scno, [lr, #-4]         )       @ get SWI instruction
+ USER( ldr     scno, [saved_pc, #-4]   )       @ get SWI instruction
 #endif
 
+       /* saved_psr and saved_pc are now dead */
+
        uaccess_disable tbl
 
        adr     tbl, sys_call_table             @ load syscall table pointer
@@ -210,6 +221,12 @@ ENTRY(vector_swi)
        bic     scno, scno, #0xff000000         @ mask off SWI op-code
        eor     scno, scno, #__NR_SYSCALL_BASE  @ check OS number
 #endif
+       get_thread_info tsk
+       /*
+        * Reload the registers that may have been corrupted on entry to
+        * the syscall assembly (by tracing or context tracking.)
+        */
+ TRACE(        ldmia   sp, {r0 - r3}           )
 
 local_restart:
        ldr     r10, [tsk, #TI_FLAGS]           @ check for syscall tracing
@@ -239,8 +256,9 @@ local_restart:
         * current task.
         */
 9001:
-       sub     lr, lr, #4
+       sub     lr, saved_pc, #4
        str     lr, [sp, #S_PC]
+       get_thread_info tsk
        b       ret_fast_syscall
 #endif
 ENDPROC(vector_swi)