local_irq_enable();
 }
 
+static inline void preempt_conditional_sti(struct pt_regs *regs)
+{
+       inc_preempt_count();
+       if (regs->flags & X86_EFLAGS_IF)
+               local_irq_enable();
+}
+
+static inline void preempt_conditional_cli(struct pt_regs *regs)
+{
+       if (regs->flags & X86_EFLAGS_IF)
+               local_irq_disable();
+       dec_preempt_count();
+}
+
 static inline void
 die_if_kernel(const char *str, struct pt_regs *regs, long err)
 {
 dotraplinkage void __kprobes do_debug(struct pt_regs *regs, long error_code)
 {
        struct task_struct *tsk = current;
-       unsigned int condition;
+       unsigned long condition;
        int si_code;
 
        get_debugreg(condition, 6);
        if (notify_die(DIE_DEBUG, "debug", regs, condition, error_code,
                                                SIGTRAP) == NOTIFY_STOP)
                return;
+
        /* It's safe to allow irq's after DR6 has been saved */
-       if (regs->flags & X86_EFLAGS_IF)
-               local_irq_enable();
+       preempt_conditional_sti(regs);
 
        /* Mask out spurious debug traps due to lazy DR7 setting */
        if (condition & (DR_TRAP0|DR_TRAP1|DR_TRAP2|DR_TRAP3)) {
         * kernel space (but re-enable TF when returning to user mode).
         */
        if (condition & DR_STEP) {
-               /*
-                * We already checked v86 mode above, so we can
-                * check for kernel mode by just checking the CPL
-                * of CS.
-                */
                if (!user_mode(regs))
                        goto clear_TF_reenable;
        }
 
-       si_code = get_si_code((unsigned long)condition);
+       si_code = get_si_code(condition);
        /* Ok, finally something we can handle */
        send_sigtrap(tsk, regs, error_code, si_code);
 
         */
 clear_dr7:
        set_debugreg(0, 7);
+       preempt_conditional_cli(regs);
        return;
 
 debug_vm86:
        handle_vm86_trap((struct kernel_vm86_regs *) regs, error_code, 1);
+       preempt_conditional_cli(regs);
        return;
 
 clear_TF_reenable:
        set_tsk_thread_flag(tsk, TIF_SINGLESTEP);
        regs->flags &= ~X86_EFLAGS_TF;
+       preempt_conditional_cli(regs);
        return;
 }
 
 
 {
        struct task_struct *tsk = current;
        unsigned long condition;
-       siginfo_t info;
+       int si_code;
 
        get_debugreg(condition, 6);
 
                                                SIGTRAP) == NOTIFY_STOP)
                return;
 
+       /* It's safe to allow irq's after DR6 has been saved */
        preempt_conditional_sti(regs);
 
        /* Mask out spurious debug traps due to lazy DR7 setting */
                        goto clear_dr7;
        }
 
+       /* Save debug status register where ptrace can see it */
        tsk->thread.debugreg6 = condition;
 
        /*
                        goto clear_TF_reenable;
        }
 
+       si_code = get_si_code(condition);
        /* Ok, finally something we can handle */
-       tsk->thread.trap_no = 1;
-       tsk->thread.error_code = error_code;
-       info.si_signo = SIGTRAP;
-       info.si_errno = 0;
-       info.si_code = get_si_code(condition);
-       info.si_addr = user_mode(regs) ? (void __user *)regs->ip : NULL;
-       force_sig_info(SIGTRAP, &info, tsk);
+       send_sigtrap(tsk, regs, error_code, si_code);
 
+       /*
+        * Disable additional traps. They'll be re-enabled when
+        * the signal is delivered.
+        */
 clear_dr7:
        set_debugreg(0, 7);
        preempt_conditional_cli(regs);
 
 
 extern unsigned long
 convert_ip_to_linear(struct task_struct *child, struct pt_regs *regs);
-
-#ifdef CONFIG_X86_32
 extern void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs,
                         int error_code, int si_code);
-#endif
-
 void signal_fault(struct pt_regs *regs, void __user *frame, char *where);
 
 extern long syscall_trace_enter(struct pt_regs *);