lockdep: fixup irq tracing
authorPeter Zijlstra <a.p.zijlstra@chello.nl>
Thu, 25 Oct 2007 12:01:10 +0000 (14:01 +0200)
committerPeter Zijlstra <a.p.zijlstra@chello.nl>
Thu, 25 Oct 2007 12:01:10 +0000 (14:01 +0200)
Ensure we fixup the IRQ state before we hit any locking code.

Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
arch/x86/kernel/kprobes_32.c
arch/x86/kernel/kprobes_64.c
arch/x86/kernel/traps_32.c
arch/x86/kernel/traps_64.c
arch/x86/mm/fault_32.c
arch/x86/mm/fault_64.c
include/asm-x86/irqflags_32.h
include/asm-x86/irqflags_64.h

index 90f778c..d87a523 100644 (file)
@@ -564,12 +564,7 @@ static int __kprobes post_kprobe_handler(struct pt_regs *regs)
 
        resume_execution(cur, regs, kcb);
        regs->eflags |= kcb->kprobe_saved_eflags;
-#ifdef CONFIG_TRACE_IRQFLAGS_SUPPORT
-       if (raw_irqs_disabled_flags(regs->eflags))
-               trace_hardirqs_off();
-       else
-               trace_hardirqs_on();
-#endif
+       trace_hardirqs_fixup_flags(regs->eflags);
 
        /*Restore back the original saved kprobes variables and continue. */
        if (kcb->kprobe_status == KPROBE_REENTER) {
index 681b801..3db3611 100644 (file)
@@ -551,12 +551,7 @@ int __kprobes post_kprobe_handler(struct pt_regs *regs)
 
        resume_execution(cur, regs, kcb);
        regs->eflags |= kcb->kprobe_saved_rflags;
-#ifdef CONFIG_TRACE_IRQFLAGS_SUPPORT
-       if (raw_irqs_disabled_flags(regs->eflags))
-               trace_hardirqs_off();
-       else
-               trace_hardirqs_on();
-#endif
+       trace_hardirqs_fixup_flags(regs->eflags);
 
        /* Restore the original saved kprobes variables and continue. */
        if (kcb->kprobe_status == KPROBE_REENTER) {
index cc9acac..298d13e 100644 (file)
@@ -789,6 +789,8 @@ void restart_nmi(void)
 #ifdef CONFIG_KPROBES
 fastcall void __kprobes do_int3(struct pt_regs *regs, long error_code)
 {
+       trace_hardirqs_fixup();
+
        if (notify_die(DIE_INT3, "int3", regs, error_code, 3, SIGTRAP)
                        == NOTIFY_STOP)
                return;
index d0c2bc7..4a6bd49 100644 (file)
@@ -807,6 +807,8 @@ asmlinkage __kprobes void default_do_nmi(struct pt_regs *regs)
 /* runs on IST stack. */
 asmlinkage void __kprobes do_int3(struct pt_regs * regs, long error_code)
 {
+       trace_hardirqs_fixup();
+
        if (notify_die(DIE_INT3, "int3", regs, error_code, 3, SIGTRAP) == NOTIFY_STOP) {
                return;
        }
index 503dfc0..2e542e8 100644 (file)
@@ -303,6 +303,11 @@ fastcall void __kprobes do_page_fault(struct pt_regs *regs,
        int write, si_code;
        int fault;
 
+       /*
+        * We can fault from pretty much anywhere, with unknown IRQ state.
+        */
+       trace_hardirqs_fixup();
+
        /* get the address */
         address = read_cr2();
 
index 644b4f7..0e26230 100644 (file)
@@ -304,6 +304,11 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
        unsigned long flags;
        siginfo_t info;
 
+       /*
+        * We can fault from pretty much anywhere, with unknown IRQ state.
+        */
+       trace_hardirqs_fixup();
+
        tsk = current;
        mm = tsk->mm;
        prefetchw(&mm->mmap_sem);
index d058b04..4c77200 100644 (file)
@@ -129,6 +129,27 @@ static inline int raw_irqs_disabled(void)
 
        return raw_irqs_disabled_flags(flags);
 }
+
+/*
+ * makes the traced hardirq state match with the machine state
+ *
+ * should be a rarely used function, only in places where its
+ * otherwise impossible to know the irq state, like in traps.
+ */
+static inline void trace_hardirqs_fixup_flags(unsigned long flags)
+{
+       if (raw_irqs_disabled_flags(flags))
+               trace_hardirqs_off();
+       else
+               trace_hardirqs_on();
+}
+
+static inline void trace_hardirqs_fixup(void)
+{
+       unsigned long flags = __raw_local_save_flags();
+
+       trace_hardirqs_fixup_flags(flags);
+}
 #endif /* __ASSEMBLY__ */
 
 /*
index 5341ea1..bb9163b 100644 (file)
@@ -111,6 +111,26 @@ static inline int raw_irqs_disabled(void)
        return raw_irqs_disabled_flags(flags);
 }
 
+/*
+ * makes the traced hardirq state match with the machine state
+ *
+ * should be a rarely used function, only in places where its
+ * otherwise impossible to know the irq state, like in traps.
+ */
+static inline void trace_hardirqs_fixup_flags(unsigned long flags)
+{
+       if (raw_irqs_disabled_flags(flags))
+               trace_hardirqs_off();
+       else
+               trace_hardirqs_on();
+}
+
+static inline void trace_hardirqs_fixup(void)
+{
+       unsigned long flags = __raw_local_save_flags();
+
+       trace_hardirqs_fixup_flags(flags);
+}
 /*
  * Used in the idle loop; sti takes one instruction cycle
  * to complete: