Merge tag 'sound-4.15-rc1' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git...
[sfrench/cifs-2.6.git] / arch / openrisc / kernel / entry.S
index 1b7160c79646be4e136d0f813b4b55c0bfd63827..690d55272ba688a2adc88bca00e66cc61903c711 100644 (file)
 
 /* =========================================================[ macros ]=== */
 
+#ifdef CONFIG_TRACE_IRQFLAGS
+/*
+ * Trace irq on/off creating a stack frame.
+ */
+#define TRACE_IRQS_OP(trace_op)                                        \
+       l.sw    -8(r1),r2       /* store frame pointer */               ;\
+       l.sw    -4(r1),r9       /* store return address */              ;\
+       l.addi  r2,r1,0         /* move sp to fp */                     ;\
+       l.jal   trace_op                                                ;\
+        l.addi r1,r1,-8                                                ;\
+       l.ori   r1,r2,0         /* restore sp */                        ;\
+       l.lwz   r9,-4(r1)       /* restore return address */            ;\
+       l.lwz   r2,-8(r1)       /* restore fp */                        ;\
+/*
+ * Trace irq on/off and save registers we need that would otherwise be
+ * clobbered.
+ */
+#define TRACE_IRQS_SAVE(t1,trace_op)                                   \
+       l.sw    -12(r1),t1      /* save extra reg */                    ;\
+       l.sw    -8(r1),r2       /* store frame pointer */               ;\
+       l.sw    -4(r1),r9       /* store return address */              ;\
+       l.addi  r2,r1,0         /* move sp to fp */                     ;\
+       l.jal   trace_op                                                ;\
+        l.addi r1,r1,-12                                               ;\
+       l.ori   r1,r2,0         /* restore sp */                        ;\
+       l.lwz   r9,-4(r1)       /* restore return address */            ;\
+       l.lwz   r2,-8(r1)       /* restore fp */                        ;\
+       l.lwz   t1,-12(r1)      /* restore extra reg */
+
+#define TRACE_IRQS_OFF TRACE_IRQS_OP(trace_hardirqs_off)
+#define TRACE_IRQS_ON  TRACE_IRQS_OP(trace_hardirqs_on)
+#define TRACE_IRQS_ON_SYSCALL                                          \
+       TRACE_IRQS_SAVE(r10,trace_hardirqs_on)                          ;\
+       l.lwz   r3,PT_GPR3(r1)                                          ;\
+       l.lwz   r4,PT_GPR4(r1)                                          ;\
+       l.lwz   r5,PT_GPR5(r1)                                          ;\
+       l.lwz   r6,PT_GPR6(r1)                                          ;\
+       l.lwz   r7,PT_GPR7(r1)                                          ;\
+       l.lwz   r8,PT_GPR8(r1)                                          ;\
+       l.lwz   r11,PT_GPR11(r1)
+#define TRACE_IRQS_OFF_ENTRY                                           \
+       l.lwz   r5,PT_SR(r1)                                            ;\
+       l.andi  r3,r5,(SPR_SR_IEE|SPR_SR_TEE)                           ;\
+       l.sfeq  r5,r0           /* skip trace if irqs were already off */;\
+       l.bf    1f                                                      ;\
+        l.nop                                                          ;\
+       TRACE_IRQS_SAVE(r4,trace_hardirqs_off)                          ;\
+1:
+#else
+#define TRACE_IRQS_OFF
+#define TRACE_IRQS_ON
+#define TRACE_IRQS_OFF_ENTRY
+#define TRACE_IRQS_ON_SYSCALL
+#endif
+
 /*
  * We need to disable interrupts at beginning of RESTORE_ALL
  * since interrupt might come in after we've loaded EPC return address
@@ -124,6 +179,7 @@ handler:                                                    ;\
        /* r30 already save */                                  ;\
 /*        l.sw    PT_GPR30(r1),r30*/                                   ;\
        l.sw    PT_GPR31(r1),r31                                        ;\
+       TRACE_IRQS_OFF_ENTRY                                            ;\
        /* Store -1 in orig_gpr11 for non-syscall exceptions */ ;\
        l.addi  r30,r0,-1                                       ;\
        l.sw    PT_ORIG_GPR11(r1),r30
@@ -557,9 +613,6 @@ _string_syscall_return:
        .align 4
 
 ENTRY(_sys_call_handler)
-       /* syscalls run with interrupts enabled */
-       ENABLE_INTERRUPTS(r29)          // enable interrupts, r29 is temp
-
        /* r1, EPCR, ESR a already saved */
        l.sw    PT_GPR2(r1),r2
        /* r3-r8 must be saved because syscall restart relies
@@ -597,6 +650,10 @@ ENTRY(_sys_call_handler)
 /*     l.sw    PT_GPR30(r1),r30 */
 
 _syscall_check_trace_enter:
+       /* syscalls run with interrupts enabled */
+       TRACE_IRQS_ON_SYSCALL
+       ENABLE_INTERRUPTS(r29)          // enable interrupts, r29 is temp
+
        /* If TIF_SYSCALL_TRACE is set, then we want to do syscall tracing */
        l.lwz   r30,TI_FLAGS(r10)
        l.andi  r30,r30,_TIF_SYSCALL_TRACE
@@ -657,6 +714,7 @@ _syscall_check_trace_leave:
 _syscall_check_work:
        /* Here we need to disable interrupts */
        DISABLE_INTERRUPTS(r27,r29)
+       TRACE_IRQS_OFF
        l.lwz   r30,TI_FLAGS(r10)
        l.andi  r30,r30,_TIF_WORK_MASK
        l.sfne  r30,r0
@@ -871,6 +929,7 @@ UNHANDLED_EXCEPTION(_vector_0x1f00,0x1f00)
 
 _resume_userspace:
        DISABLE_INTERRUPTS(r3,r4)
+       TRACE_IRQS_OFF
        l.lwz   r4,TI_FLAGS(r10)
        l.andi  r13,r4,_TIF_WORK_MASK
        l.sfeqi r13,0
@@ -909,6 +968,15 @@ _work_pending:
         l.lwz  r8,PT_GPR8(r1)
 
 _restore_all:
+#ifdef CONFIG_TRACE_IRQFLAGS
+       l.lwz   r4,PT_SR(r1)
+       l.andi  r3,r4,(SPR_SR_IEE|SPR_SR_TEE)
+       l.sfeq  r3,r0           /* skip trace if irqs were off */
+       l.bf    skip_hardirqs_on
+        l.nop
+       TRACE_IRQS_ON
+skip_hardirqs_on:
+#endif
        RESTORE_ALL
        /* This returns to userspace code */