patch-2.1.113 linux/arch/i386/kernel/traps.c
Next file: linux/arch/i386/mm/fault.c
Previous file: linux/arch/i386/kernel/ptrace.c
Back to the patch index
Back to the overall index
- Lines: 108
- Date:
Fri Jul 31 23:21:00 1998
- Orig file:
v2.1.112/linux/arch/i386/kernel/traps.c
- Orig date:
Thu Jul 16 18:09:23 1998
diff -u --recursive --new-file v2.1.112/linux/arch/i386/kernel/traps.c linux/arch/i386/kernel/traps.c
@@ -27,6 +27,7 @@
#include <asm/io.h>
#include <asm/spinlock.h>
#include <asm/atomic.h>
+#include <asm/debugreg.h>
asmlinkage int system_call(void);
asmlinkage void lcall7(void);
@@ -294,24 +295,66 @@
unknown_nmi_error(reason, regs);
}
+/*
+ * Careful - we must not do a lock-kernel until we have checked that the
+ * debug fault happened in user mode. Getting debug exceptions while
+ * in the kernel has to be handled without locking, to avoid deadlocks..
+ *
+ * Being careful here means that we don't have to be as careful in a
+ * lot of more complicated places (task switching can be a bit lazy
+ * about restoring all the debug state, and ptrace doesn't have to
+ * find every occurrence of the TF bit that could be saved away even
+ * by user code - and we don't have to be careful about what values
+ * can be written to the debug registers because there are no really
+ * bad cases).
+ */
asmlinkage void do_debug(struct pt_regs * regs, long error_code)
{
- lock_kernel();
- if (regs->eflags & VM_MASK) {
- handle_vm86_trap((struct kernel_vm86_regs *) regs, error_code, 1);
- goto out;
+ unsigned int condition;
+ struct task_struct *tsk = current;
+
+ if (regs->eflags & VM_MASK)
+ goto debug_vm86;
+
+ __asm__ __volatile__("movl %%db6,%0" : "=r" (condition));
+
+ /* Mask out spurious TF errors due to lazy TF clearing */
+ if (condition & DR_STEP) {
+ if ((tsk->flags & PF_PTRACED) == 0)
+ goto clear_TF;
}
- force_sig(SIGTRAP, current);
- current->tss.trap_no = 1;
- current->tss.error_code = error_code;
- if ((regs->xcs & 3) == 0) {
- /* If this is a kernel mode trap, then reset db7 and allow us to continue */
- __asm__("movl %0,%%db7"
- : /* no output */
- : "r" (0));
+
+ /* Mast out spurious debug traps due to lazy DR7 setting */
+ if (condition & (DR_TRAP0|DR_TRAP1|DR_TRAP2|DR_TRAP3)) {
+ if (!tsk->tss.debugreg[7])
+ goto clear_dr7;
}
-out:
+
+ /* If this is a kernel mode trap, we need to reset db7 to allow us to continue sanely */
+ if ((regs->xcs & 3) == 0)
+ goto clear_dr7;
+
+ /* Ok, finally something we can handle */
+ tsk->tss.trap_no = 1;
+ tsk->tss.error_code = error_code;
+ force_sig(SIGTRAP, tsk);
+ return;
+
+debug_vm86:
+ lock_kernel();
+ handle_vm86_trap((struct kernel_vm86_regs *) regs, error_code, 1);
unlock_kernel();
+ return;
+
+clear_dr7:
+ __asm__("movl %0,%%db7"
+ : /* no output */
+ : "r" (0));
+ return;
+
+clear_TF:
+ regs->eflags &= ~TF_MASK;
+ return;
}
/*
@@ -333,9 +376,9 @@
task->flags&=~PF_USEDFPU;
stts();
- force_sig(SIGFPE, task);
task->tss.trap_no = 16;
task->tss.error_code = 0;
+ force_sig(SIGFPE, task);
unlock_kernel();
}
@@ -434,7 +477,7 @@
-__initfunc(void trap_init(void))
+void __init trap_init(void)
{
int i;
struct desc_struct * p;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov