Commit 28a59cb0 authored by Jamie Lokier's avatar Jamie Lokier Committed by Linus Torvalds

[PATCH] CONFIG_PREEMPT fix of do_debug()

If CONFIG_PREEMPT is enabled, and the kernel is preempted just before
do_debug() has a chance to save the debug register values, DR6 could be
read from the wrong CPU.

It is exactly the same problem as reading %cr2 in the page fault
handler.  Same fix: make the handler a interrupt gate, and enable
interrupts only once safe.
parent 167b1210
...@@ -514,6 +514,10 @@ asmlinkage void do_debug(struct pt_regs * regs, long error_code) ...@@ -514,6 +514,10 @@ asmlinkage void do_debug(struct pt_regs * regs, long error_code)
__asm__ __volatile__("movl %%db6,%0" : "=r" (condition)); __asm__ __volatile__("movl %%db6,%0" : "=r" (condition));
/* It's safe to allow irq's after DR6 has been saved */
if (regs->eflags & X86_EFLAGS_IF)
local_irq_enable();
/* Mask out spurious debug traps due to lazy DR7 setting */ /* Mask out spurious debug traps due to lazy DR7 setting */
if (condition & (DR_TRAP0|DR_TRAP1|DR_TRAP2|DR_TRAP3)) { if (condition & (DR_TRAP0|DR_TRAP1|DR_TRAP2|DR_TRAP3)) {
if (!tsk->thread.debugreg[7]) if (!tsk->thread.debugreg[7])
...@@ -831,7 +835,7 @@ void __init trap_init(void) ...@@ -831,7 +835,7 @@ void __init trap_init(void)
#endif #endif
set_trap_gate(0,&divide_error); set_trap_gate(0,&divide_error);
set_trap_gate(1,&debug); set_intr_gate(1,&debug);
set_intr_gate(2,&nmi); set_intr_gate(2,&nmi);
set_system_gate(3,&int3); /* int3-5 can be called from all */ set_system_gate(3,&int3); /* int3-5 can be called from all */
set_system_gate(4,&overflow); set_system_gate(4,&overflow);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment