diff options
| author | Peter Zijlstra <a.p.zijlstra@chello.nl> | 2007-10-25 08:01:10 -0400 |
|---|---|---|
| committer | Peter Zijlstra <a.p.zijlstra@chello.nl> | 2007-10-25 08:01:10 -0400 |
| commit | 143a5d325d35efb1b29dcb8d6031cf27107e183a (patch) | |
| tree | def297c7608722df2b5a51e5e6acaacb1aeb1f97 | |
| parent | c9927c2bf4f45bb85e8b502ab3fb79ad6483c244 (diff) | |
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.c | 7 | ||||
| -rw-r--r-- | arch/x86/kernel/kprobes_64.c | 7 | ||||
| -rw-r--r-- | arch/x86/kernel/traps_32.c | 2 | ||||
| -rw-r--r-- | arch/x86/kernel/traps_64.c | 2 | ||||
| -rw-r--r-- | arch/x86/mm/fault_32.c | 5 | ||||
| -rw-r--r-- | arch/x86/mm/fault_64.c | 5 | ||||
| -rw-r--r-- | include/asm-x86/irqflags_32.h | 21 | ||||
| -rw-r--r-- | include/asm-x86/irqflags_64.h | 20 |
8 files changed, 57 insertions, 12 deletions
diff --git a/arch/x86/kernel/kprobes_32.c b/arch/x86/kernel/kprobes_32.c index 90f778c04b3f..d87a523070d1 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) | |||
| 564 | 564 | ||
| 565 | resume_execution(cur, regs, kcb); | 565 | resume_execution(cur, regs, kcb); |
| 566 | regs->eflags |= kcb->kprobe_saved_eflags; | 566 | regs->eflags |= kcb->kprobe_saved_eflags; |
| 567 | #ifdef CONFIG_TRACE_IRQFLAGS_SUPPORT | 567 | trace_hardirqs_fixup_flags(regs->eflags); |
| 568 | if (raw_irqs_disabled_flags(regs->eflags)) | ||
| 569 | trace_hardirqs_off(); | ||
| 570 | else | ||
| 571 | trace_hardirqs_on(); | ||
| 572 | #endif | ||
| 573 | 568 | ||
| 574 | /*Restore back the original saved kprobes variables and continue. */ | 569 | /*Restore back the original saved kprobes variables and continue. */ |
| 575 | if (kcb->kprobe_status == KPROBE_REENTER) { | 570 | if (kcb->kprobe_status == KPROBE_REENTER) { |
diff --git a/arch/x86/kernel/kprobes_64.c b/arch/x86/kernel/kprobes_64.c index 681b801c5e26..3db3611933d8 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) | |||
| 551 | 551 | ||
| 552 | resume_execution(cur, regs, kcb); | 552 | resume_execution(cur, regs, kcb); |
| 553 | regs->eflags |= kcb->kprobe_saved_rflags; | 553 | regs->eflags |= kcb->kprobe_saved_rflags; |
| 554 | #ifdef CONFIG_TRACE_IRQFLAGS_SUPPORT | 554 | trace_hardirqs_fixup_flags(regs->eflags); |
| 555 | if (raw_irqs_disabled_flags(regs->eflags)) | ||
| 556 | trace_hardirqs_off(); | ||
| 557 | else | ||
| 558 | trace_hardirqs_on(); | ||
| 559 | #endif | ||
| 560 | 555 | ||
| 561 | /* Restore the original saved kprobes variables and continue. */ | 556 | /* Restore the original saved kprobes variables and continue. */ |
| 562 | if (kcb->kprobe_status == KPROBE_REENTER) { | 557 | if (kcb->kprobe_status == KPROBE_REENTER) { |
diff --git a/arch/x86/kernel/traps_32.c b/arch/x86/kernel/traps_32.c index cc9acace7e23..298d13ed3ab3 100644 --- a/arch/x86/kernel/traps_32.c +++ b/arch/x86/kernel/traps_32.c | |||
| @@ -789,6 +789,8 @@ void restart_nmi(void) | |||
| 789 | #ifdef CONFIG_KPROBES | 789 | #ifdef CONFIG_KPROBES |
| 790 | fastcall void __kprobes do_int3(struct pt_regs *regs, long error_code) | 790 | fastcall void __kprobes do_int3(struct pt_regs *regs, long error_code) |
| 791 | { | 791 | { |
| 792 | trace_hardirqs_fixup(); | ||
| 793 | |||
| 792 | if (notify_die(DIE_INT3, "int3", regs, error_code, 3, SIGTRAP) | 794 | if (notify_die(DIE_INT3, "int3", regs, error_code, 3, SIGTRAP) |
| 793 | == NOTIFY_STOP) | 795 | == NOTIFY_STOP) |
| 794 | return; | 796 | return; |
diff --git a/arch/x86/kernel/traps_64.c b/arch/x86/kernel/traps_64.c index d0c2bc7ab2ec..4a6bd4965f56 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) | |||
| 807 | /* runs on IST stack. */ | 807 | /* runs on IST stack. */ |
| 808 | asmlinkage void __kprobes do_int3(struct pt_regs * regs, long error_code) | 808 | asmlinkage void __kprobes do_int3(struct pt_regs * regs, long error_code) |
| 809 | { | 809 | { |
| 810 | trace_hardirqs_fixup(); | ||
| 811 | |||
| 810 | if (notify_die(DIE_INT3, "int3", regs, error_code, 3, SIGTRAP) == NOTIFY_STOP) { | 812 | if (notify_die(DIE_INT3, "int3", regs, error_code, 3, SIGTRAP) == NOTIFY_STOP) { |
| 811 | return; | 813 | return; |
| 812 | } | 814 | } |
diff --git a/arch/x86/mm/fault_32.c b/arch/x86/mm/fault_32.c index 503dfc05111b..2e542e89a3e2 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, | |||
| 303 | int write, si_code; | 303 | int write, si_code; |
| 304 | int fault; | 304 | int fault; |
| 305 | 305 | ||
| 306 | /* | ||
| 307 | * We can fault from pretty much anywhere, with unknown IRQ state. | ||
| 308 | */ | ||
| 309 | trace_hardirqs_fixup(); | ||
| 310 | |||
| 306 | /* get the address */ | 311 | /* get the address */ |
| 307 | address = read_cr2(); | 312 | address = read_cr2(); |
| 308 | 313 | ||
diff --git a/arch/x86/mm/fault_64.c b/arch/x86/mm/fault_64.c index 644b4f7ece10..0e26230669ca 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, | |||
| 304 | unsigned long flags; | 304 | unsigned long flags; |
| 305 | siginfo_t info; | 305 | siginfo_t info; |
| 306 | 306 | ||
| 307 | /* | ||
| 308 | * We can fault from pretty much anywhere, with unknown IRQ state. | ||
| 309 | */ | ||
| 310 | trace_hardirqs_fixup(); | ||
| 311 | |||
| 307 | tsk = current; | 312 | tsk = current; |
| 308 | mm = tsk->mm; | 313 | mm = tsk->mm; |
| 309 | prefetchw(&mm->mmap_sem); | 314 | prefetchw(&mm->mmap_sem); |
diff --git a/include/asm-x86/irqflags_32.h b/include/asm-x86/irqflags_32.h index d058b04e0083..4c7720089cb5 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) | |||
| 129 | 129 | ||
| 130 | return raw_irqs_disabled_flags(flags); | 130 | return raw_irqs_disabled_flags(flags); |
| 131 | } | 131 | } |
| 132 | |||
| 133 | /* | ||
| 134 | * makes the traced hardirq state match with the machine state | ||
| 135 | * | ||
| 136 | * should be a rarely used function, only in places where its | ||
| 137 | * otherwise impossible to know the irq state, like in traps. | ||
| 138 | */ | ||
| 139 | static inline void trace_hardirqs_fixup_flags(unsigned long flags) | ||
| 140 | { | ||
| 141 | if (raw_irqs_disabled_flags(flags)) | ||
| 142 | trace_hardirqs_off(); | ||
| 143 | else | ||
| 144 | trace_hardirqs_on(); | ||
| 145 | } | ||
| 146 | |||
| 147 | static inline void trace_hardirqs_fixup(void) | ||
| 148 | { | ||
| 149 | unsigned long flags = __raw_local_save_flags(); | ||
| 150 | |||
| 151 | trace_hardirqs_fixup_flags(flags); | ||
| 152 | } | ||
| 132 | #endif /* __ASSEMBLY__ */ | 153 | #endif /* __ASSEMBLY__ */ |
| 133 | 154 | ||
| 134 | /* | 155 | /* |
diff --git a/include/asm-x86/irqflags_64.h b/include/asm-x86/irqflags_64.h index 5341ea1f815a..bb9163bb29d1 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) | |||
| 112 | } | 112 | } |
| 113 | 113 | ||
| 114 | /* | 114 | /* |
| 115 | * makes the traced hardirq state match with the machine state | ||
| 116 | * | ||
| 117 | * should be a rarely used function, only in places where its | ||
| 118 | * otherwise impossible to know the irq state, like in traps. | ||
| 119 | */ | ||
| 120 | static inline void trace_hardirqs_fixup_flags(unsigned long flags) | ||
| 121 | { | ||
| 122 | if (raw_irqs_disabled_flags(flags)) | ||
| 123 | trace_hardirqs_off(); | ||
| 124 | else | ||
| 125 | trace_hardirqs_on(); | ||
| 126 | } | ||
| 127 | |||
| 128 | static inline void trace_hardirqs_fixup(void) | ||
| 129 | { | ||
| 130 | unsigned long flags = __raw_local_save_flags(); | ||
| 131 | |||
| 132 | trace_hardirqs_fixup_flags(flags); | ||
| 133 | } | ||
| 134 | /* | ||
| 115 | * Used in the idle loop; sti takes one instruction cycle | 135 | * Used in the idle loop; sti takes one instruction cycle |
| 116 | * to complete: | 136 | * to complete: |
| 117 | */ | 137 | */ |
