]> git.hungrycats.org Git - linux/commitdiff
[PATCH] CONFIG_PREEMPT fix of do_debug()
authorJamie Lokier <jamie@shareable.org>
Sat, 8 Feb 2003 18:41:34 +0000 (10:41 -0800)
committerLinus Torvalds <torvalds@home.transmeta.com>
Sat, 8 Feb 2003 18:41:34 +0000 (10:41 -0800)
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.

arch/i386/kernel/traps.c

index 81a09464e4d79c6801825eddf449e2d6636ddb4a..234ced527110e4a6f1a990d2e7f056fe0a510de4 100644 (file)
@@ -514,6 +514,10 @@ asmlinkage void do_debug(struct pt_regs * regs, long error_code)
 
        __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 */
        if (condition & (DR_TRAP0|DR_TRAP1|DR_TRAP2|DR_TRAP3)) {
                if (!tsk->thread.debugreg[7])
@@ -831,7 +835,7 @@ void __init trap_init(void)
 #endif
 
        set_trap_gate(0,&divide_error);
-       set_trap_gate(1,&debug);
+       set_intr_gate(1,&debug);
        set_intr_gate(2,&nmi);
        set_system_gate(3,&int3);       /* int3-5 can be called from all */
        set_system_gate(4,&overflow);