summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Zijlstra <a.p.zijlstra@chello.nl>2007-10-25 14:01:10 +0200
committerPeter Zijlstra <a.p.zijlstra@chello.nl>2007-10-25 14:01:10 +0200
commit143a5d325d35efb1b29dcb8d6031cf27107e183a (patch)
treedef297c7608722df2b5a51e5e6acaacb1aeb1f97
parentc9927c2bf4f45bb85e8b502ab3fb79ad6483c244 (diff)
downloadop-kernel-dev-143a5d325d35efb1b29dcb8d6031cf27107e183a.zip
op-kernel-dev-143a5d325d35efb1b29dcb8d6031cf27107e183a.tar.gz
lockdep: fixup irq tracing
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>
-rw-r--r--arch/x86/kernel/kprobes_32.c7
-rw-r--r--arch/x86/kernel/kprobes_64.c7
-rw-r--r--arch/x86/kernel/traps_32.c2
-rw-r--r--arch/x86/kernel/traps_64.c2
-rw-r--r--arch/x86/mm/fault_32.c5
-rw-r--r--arch/x86/mm/fault_64.c5
-rw-r--r--include/asm-x86/irqflags_32.h21
-rw-r--r--include/asm-x86/irqflags_64.h20
8 files changed, 57 insertions, 12 deletions
diff --git a/arch/x86/kernel/kprobes_32.c b/arch/x86/kernel/kprobes_32.c
index 90f778c..d87a523 100644
--- a/arch/x86/kernel/kprobes_32.c
+++ b/arch/x86/kernel/kprobes_32.c
@@ -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) {
diff --git a/arch/x86/kernel/kprobes_64.c b/arch/x86/kernel/kprobes_64.c
index 681b801..3db36119 100644
--- a/arch/x86/kernel/kprobes_64.c
+++ b/arch/x86/kernel/kprobes_64.c
@@ -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) {
diff --git a/arch/x86/kernel/traps_32.c b/arch/x86/kernel/traps_32.c
index cc9acac..298d13e 100644
--- a/arch/x86/kernel/traps_32.c
+++ b/arch/x86/kernel/traps_32.c
@@ -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;
diff --git a/arch/x86/kernel/traps_64.c b/arch/x86/kernel/traps_64.c
index d0c2bc7..4a6bd49 100644
--- a/arch/x86/kernel/traps_64.c
+++ b/arch/x86/kernel/traps_64.c
@@ -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;
}
diff --git a/arch/x86/mm/fault_32.c b/arch/x86/mm/fault_32.c
index 503dfc0..2e542e8 100644
--- a/arch/x86/mm/fault_32.c
+++ b/arch/x86/mm/fault_32.c
@@ -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();
diff --git a/arch/x86/mm/fault_64.c b/arch/x86/mm/fault_64.c
index 644b4f7..0e262306 100644
--- a/arch/x86/mm/fault_64.c
+++ b/arch/x86/mm/fault_64.c
@@ -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);
diff --git a/include/asm-x86/irqflags_32.h b/include/asm-x86/irqflags_32.h
index d058b04..4c77200 100644
--- a/include/asm-x86/irqflags_32.h
+++ b/include/asm-x86/irqflags_32.h
@@ -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__ */
/*
diff --git a/include/asm-x86/irqflags_64.h b/include/asm-x86/irqflags_64.h
index 5341ea1..bb9163b 100644
--- a/include/asm-x86/irqflags_64.h
+++ b/include/asm-x86/irqflags_64.h
@@ -112,6 +112,26 @@ static inline int raw_irqs_disabled(void)
}
/*
+ * 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:
*/
OpenPOWER on IntegriCloud