aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/include/asm/desc.h
diff options
context:
space:
mode:
authorSteven Rostedt (Red Hat) <rostedt@goodmis.org>2013-06-22 13:16:19 -0400
committerSteven Rostedt <rostedt@goodmis.org>2013-06-22 13:16:19 -0400
commit2b4bc78956bdcc2bb4c49b3af955be776817e897 (patch)
tree5a16679e19b03c128f48d3dfe5bed181a38c1317 /arch/x86/include/asm/desc.h
parent83ab85140bc1492f92de263a1c30ea04a0f465f7 (diff)
trace,x86: Do not call local_irq_save() in load_current_idt()
As load_current_idt() is now what is used to update the IDT for the switches needed for NMI, lockdep debug, and for tracing, it must not call local_irq_save(). This is because one of the users of this is lockdep, which does tracing of local_irq_save() and when the debug trap is hit, we need to update the IDT before tracing interrupts being disabled. As load_current_idt() is used to do this, calling local_irq_save() which lockdep traces, defeats the point of calling load_current_idt(). As interrupts are already disabled when used by lockdep and NMI, the only other user is tracing that can disable interrupts itself. Simply have the tracing update disable interrupts before calling load_current_idt() instead of breaking the other users. Here's the dump that happened: ------------[ cut here ]------------ WARNING: at /work/autotest/nobackup/linux-test.git/kernel/fork.c:1196 copy_process+0x2c3/0x1398() DEBUG_LOCKS_WARN_ON(!p->hardirqs_enabled) Modules linked in: CPU: 1 PID: 4570 Comm: gdm-simple-gree Not tainted 3.10.0-rc3-test+ #5 Hardware name: /DG965MQ, BIOS MQ96510J.86A.0372.2006.0605.1717 06/05/2006 ffffffff81d2a7a5 ffff88006ed13d50 ffffffff8192822b ffff88006ed13d90 ffffffff81035f25 ffff8800721c6000 ffff88006ed13da0 0000000001200011 0000000000000000 ffff88006ed5e000 ffff8800721c6000 ffff88006ed13df0 Call Trace: [<ffffffff8192822b>] dump_stack+0x19/0x1b [<ffffffff81035f25>] warn_slowpath_common+0x67/0x80 [<ffffffff81035fe1>] warn_slowpath_fmt+0x46/0x48 [<ffffffff812bfc5d>] ? __raw_spin_lock_init+0x31/0x52 [<ffffffff810341f7>] copy_process+0x2c3/0x1398 [<ffffffff8103539d>] do_fork+0xa8/0x260 [<ffffffff810ca7b1>] ? trace_preempt_on+0x2a/0x2f [<ffffffff812afb3e>] ? trace_hardirqs_on_thunk+0x3a/0x3f [<ffffffff81937fe7>] ? sysret_check+0x1b/0x56 [<ffffffff81937fe7>] ? sysret_check+0x1b/0x56 [<ffffffff810355cf>] SyS_clone+0x16/0x18 [<ffffffff81938369>] stub_clone+0x69/0x90 [<ffffffff81937fc2>] ? system_call_fastpath+0x16/0x1b ---[ end trace 8b157a9d20ca1aa2 ]--- in fork.c: #ifdef CONFIG_PROVE_LOCKING DEBUG_LOCKS_WARN_ON(!p->hardirqs_enabled); <-- bug here DEBUG_LOCKS_WARN_ON(!p->softirqs_enabled); #endif Cc: Seiji Aguchi <seiji.aguchi@hds.com> Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Diffstat (limited to 'arch/x86/include/asm/desc.h')
-rw-r--r--arch/x86/include/asm/desc.h10
1 files changed, 4 insertions, 6 deletions
diff --git a/arch/x86/include/asm/desc.h b/arch/x86/include/asm/desc.h
index 1377ecb29d8d..b90e5dfeee46 100644
--- a/arch/x86/include/asm/desc.h
+++ b/arch/x86/include/asm/desc.h
@@ -497,21 +497,19 @@ static inline void load_trace_idt(void)
497#endif 497#endif
498 498
499/* 499/*
500 * the load_current_idt() is called with interrupt disabled by local_irq_save() 500 * The load_current_idt() must be called with interrupts disabled
501 * to avoid races. That way the IDT will always be set back to the expected 501 * to avoid races. That way the IDT will always be set back to the expected
502 * descriptor. 502 * descriptor. It's also called when a CPU is being initialized, and
503 * that doesn't need to disable interrupts, as nothing should be
504 * bothering the CPU then.
503 */ 505 */
504static inline void load_current_idt(void) 506static inline void load_current_idt(void)
505{ 507{
506 unsigned long flags;
507
508 local_irq_save(flags);
509 if (is_debug_idt_enabled()) 508 if (is_debug_idt_enabled())
510 load_debug_idt(); 509 load_debug_idt();
511 else if (is_trace_idt_enabled()) 510 else if (is_trace_idt_enabled())
512 load_trace_idt(); 511 load_trace_idt();
513 else 512 else
514 load_idt((const struct desc_ptr *)&idt_descr); 513 load_idt((const struct desc_ptr *)&idt_descr);
515 local_irq_restore(flags);
516} 514}
517#endif /* _ASM_X86_DESC_H */ 515#endif /* _ASM_X86_DESC_H */