Complete irq tracing support for ARM
Before this patch enabling and disabling irqs in assembler code and by the hardware wasn't tracked completly. I had to transpose two instructions in arch/arm/lib/bitops.h because restore_irqs doesn't preserve the flags with CONFIG_TRACE_IRQFLAGS=y Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> Cc: Russell King <linux@arm.linux.org.uk> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Ingo Molnar <mingo@redhat.com> Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
This commit is contained in:
@@ -74,23 +74,56 @@
|
|||||||
* Enable and disable interrupts
|
* Enable and disable interrupts
|
||||||
*/
|
*/
|
||||||
#if __LINUX_ARM_ARCH__ >= 6
|
#if __LINUX_ARM_ARCH__ >= 6
|
||||||
.macro disable_irq
|
.macro disable_irq_notrace
|
||||||
cpsid i
|
cpsid i
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
.macro enable_irq
|
.macro enable_irq_notrace
|
||||||
cpsie i
|
cpsie i
|
||||||
.endm
|
.endm
|
||||||
#else
|
#else
|
||||||
.macro disable_irq
|
.macro disable_irq_notrace
|
||||||
msr cpsr_c, #PSR_I_BIT | SVC_MODE
|
msr cpsr_c, #PSR_I_BIT | SVC_MODE
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
.macro enable_irq
|
.macro enable_irq_notrace
|
||||||
msr cpsr_c, #SVC_MODE
|
msr cpsr_c, #SVC_MODE
|
||||||
.endm
|
.endm
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
.macro asm_trace_hardirqs_off
|
||||||
|
#if defined(CONFIG_TRACE_IRQFLAGS)
|
||||||
|
stmdb sp!, {r0-r3, ip, lr}
|
||||||
|
bl trace_hardirqs_off
|
||||||
|
ldmia sp!, {r0-r3, ip, lr}
|
||||||
|
#endif
|
||||||
|
.endm
|
||||||
|
|
||||||
|
.macro asm_trace_hardirqs_on_cond, cond
|
||||||
|
#if defined(CONFIG_TRACE_IRQFLAGS)
|
||||||
|
/*
|
||||||
|
* actually the registers should be pushed and pop'd conditionally, but
|
||||||
|
* after bl the flags are certainly clobbered
|
||||||
|
*/
|
||||||
|
stmdb sp!, {r0-r3, ip, lr}
|
||||||
|
bl\cond trace_hardirqs_on
|
||||||
|
ldmia sp!, {r0-r3, ip, lr}
|
||||||
|
#endif
|
||||||
|
.endm
|
||||||
|
|
||||||
|
.macro asm_trace_hardirqs_on
|
||||||
|
asm_trace_hardirqs_on_cond al
|
||||||
|
.endm
|
||||||
|
|
||||||
|
.macro disable_irq
|
||||||
|
disable_irq_notrace
|
||||||
|
asm_trace_hardirqs_off
|
||||||
|
.endm
|
||||||
|
|
||||||
|
.macro enable_irq
|
||||||
|
asm_trace_hardirqs_on
|
||||||
|
enable_irq_notrace
|
||||||
|
.endm
|
||||||
/*
|
/*
|
||||||
* Save the current IRQ state and disable IRQs. Note that this macro
|
* Save the current IRQ state and disable IRQs. Note that this macro
|
||||||
* assumes FIQs are enabled, and that the processor is in SVC mode.
|
* assumes FIQs are enabled, and that the processor is in SVC mode.
|
||||||
@@ -104,10 +137,16 @@
|
|||||||
* Restore interrupt state previously stored in a register. We don't
|
* Restore interrupt state previously stored in a register. We don't
|
||||||
* guarantee that this will preserve the flags.
|
* guarantee that this will preserve the flags.
|
||||||
*/
|
*/
|
||||||
.macro restore_irqs, oldcpsr
|
.macro restore_irqs_notrace, oldcpsr
|
||||||
msr cpsr_c, \oldcpsr
|
msr cpsr_c, \oldcpsr
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
|
.macro restore_irqs, oldcpsr
|
||||||
|
tst \oldcpsr, #PSR_I_BIT
|
||||||
|
asm_trace_hardirqs_on_cond eq
|
||||||
|
restore_irqs_notrace \oldcpsr
|
||||||
|
.endm
|
||||||
|
|
||||||
#define USER(x...) \
|
#define USER(x...) \
|
||||||
9999: x; \
|
9999: x; \
|
||||||
.section __ex_table,"a"; \
|
.section __ex_table,"a"; \
|
||||||
|
@@ -151,6 +151,8 @@ ENDPROC(__und_invalid)
|
|||||||
@ r4 - orig_r0 (see pt_regs definition in ptrace.h)
|
@ r4 - orig_r0 (see pt_regs definition in ptrace.h)
|
||||||
@
|
@
|
||||||
stmia r5, {r0 - r4}
|
stmia r5, {r0 - r4}
|
||||||
|
|
||||||
|
asm_trace_hardirqs_off
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
.align 5
|
.align 5
|
||||||
@@ -206,9 +208,6 @@ ENDPROC(__dabt_svc)
|
|||||||
__irq_svc:
|
__irq_svc:
|
||||||
svc_entry
|
svc_entry
|
||||||
|
|
||||||
#ifdef CONFIG_TRACE_IRQFLAGS
|
|
||||||
bl trace_hardirqs_off
|
|
||||||
#endif
|
|
||||||
#ifdef CONFIG_PREEMPT
|
#ifdef CONFIG_PREEMPT
|
||||||
get_thread_info tsk
|
get_thread_info tsk
|
||||||
ldr r8, [tsk, #TI_PREEMPT] @ get preempt count
|
ldr r8, [tsk, #TI_PREEMPT] @ get preempt count
|
||||||
@@ -383,6 +382,8 @@ ENDPROC(__pabt_svc)
|
|||||||
@ Clear FP to mark the first stack frame
|
@ Clear FP to mark the first stack frame
|
||||||
@
|
@
|
||||||
zero_fp
|
zero_fp
|
||||||
|
|
||||||
|
asm_trace_hardirqs_off
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
.macro kuser_cmpxchg_check
|
.macro kuser_cmpxchg_check
|
||||||
@@ -437,9 +438,6 @@ __irq_usr:
|
|||||||
usr_entry
|
usr_entry
|
||||||
kuser_cmpxchg_check
|
kuser_cmpxchg_check
|
||||||
|
|
||||||
#ifdef CONFIG_TRACE_IRQFLAGS
|
|
||||||
bl trace_hardirqs_off
|
|
||||||
#endif
|
|
||||||
get_thread_info tsk
|
get_thread_info tsk
|
||||||
#ifdef CONFIG_PREEMPT
|
#ifdef CONFIG_PREEMPT
|
||||||
ldr r8, [tsk, #TI_PREEMPT] @ get preempt count
|
ldr r8, [tsk, #TI_PREEMPT] @ get preempt count
|
||||||
|
@@ -60,8 +60,8 @@
|
|||||||
tst r2, r0, lsl r3
|
tst r2, r0, lsl r3
|
||||||
\instr r2, r2, r0, lsl r3
|
\instr r2, r2, r0, lsl r3
|
||||||
\store r2, [r1]
|
\store r2, [r1]
|
||||||
restore_irqs ip
|
|
||||||
moveq r0, #0
|
moveq r0, #0
|
||||||
|
restore_irqs ip
|
||||||
mov pc, lr
|
mov pc, lr
|
||||||
.endm
|
.endm
|
||||||
#endif
|
#endif
|
||||||
|
Reference in New Issue
Block a user