diff options
author | Chris Dearman <chris@mips.com> | 2007-03-26 14:48:50 +0100 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2007-03-29 23:46:35 +0100 |
commit | fe99f1b184efb75c50dd8cbdfff99b559c2cb3b3 (patch) | |
tree | 7baefefa620815b1d585af092e87c03a5ffdda17 | |
parent | cbde5ebc972c0577741a69c85d5e5afad19d813b (diff) |
[MIPS] lockdep: Deal with interrupt disable hazard in TRACE_IRQFLAGS
Between the mtc0 or di instruction that disables interrupts and the
following hazard barrier a processor may still take interrupts. If an
interrupt is taken after interrupts are disabled but before the state
is updated it will appear to restore_all that it is incorrectly returning
with interrupts disabled.
Signed-off-by: Chris Dearman <chris@mips.com>
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
-rw-r--r-- | arch/mips/kernel/genex.S | 31 |
1 files changed, 31 insertions, 0 deletions
diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S index 83843a229be..297bd56c234 100644 --- a/arch/mips/kernel/genex.S +++ b/arch/mips/kernel/genex.S @@ -128,6 +128,37 @@ handle_vcei: .align 5 NESTED(handle_int, PT_SIZE, sp) +#ifdef CONFIG_TRACE_IRQFLAGS + /* + * Check to see if the interrupted code has just disabled + * interrupts and ignore this interrupt for now if so. + * + * local_irq_disable() disables interrupts and then calls + * trace_hardirqs_off() to track the state. If an interrupt is taken + * after interrupts are disabled but before the state is updated + * it will appear to restore_all that it is incorrectly returning with + * interrupts disabled + */ + .set push + .set noat + mfc0 k0, CP0_STATUS +#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX) + and k0, ST0_IEP + bnez k0, 1f + + mfc0 k0, EP0_EPC + .set noreorder + j k0 + rfe +#else + and k0, ST0_IE + bnez k0, 1f + + eret +#endif +1: + .set pop +#endif SAVE_ALL CLI TRACE_IRQS_OFF |