if (verify_area(VERIFY_READ, buf, sizeof(*buf)))
goto badframe;
err |= restore_i387(buf);
+ } else {
+ struct task_struct *me = current;
+ if (used_math()) {
+ clear_fpu(me);
+ clear_used_math();
+ }
}
}
struct pt_regs *regs, unsigned long mask)
{
int tmp, err = 0;
- unsigned long eflags;
tmp = 0;
__asm__("movl %%gs,%0" : "=r"(tmp): "0"(tmp));
err |= __put_user(current->thread.error_code, &sc->err);
err |= __put_user(regs->eip, &sc->eip);
err |= __put_user(regs->xcs, (unsigned int __user *)&sc->cs);
- eflags = regs->eflags;
- if (current->ptrace & PT_PTRACED) {
- eflags &= ~TF_MASK;
- }
- err |= __put_user(eflags, &sc->eflags);
+ err |= __put_user(regs->eflags, &sc->eflags);
err |= __put_user(regs->esp, &sc->esp_at_signal);
err |= __put_user(regs->xss, (unsigned int __user *)&sc->ss);
? current_thread_info()->exec_domain->signal_invmap[sig]
: sig;
- err |= __put_user(usig, &frame->sig);
+ err = __put_user(usig, &frame->sig);
if (err)
goto give_sigsegv;
- err |= setup_sigcontext(&frame->sc, &frame->fpstate, regs, set->sig[0]);
+ err = setup_sigcontext(&frame->sc, &frame->fpstate, regs, set->sig[0]);
if (err)
goto give_sigsegv;
if (_NSIG_WORDS > 1) {
- err |= __copy_to_user(&frame->extramask, &set->sig[1],
+ err = __copy_to_user(&frame->extramask, &set->sig[1],
sizeof(frame->extramask));
+ if (err)
+ goto give_sigsegv;
}
- if (err)
- goto give_sigsegv;
restorer = &__kernel_sigreturn;
if (ka->sa.sa_flags & SA_RESTORER)
regs->xes = __USER_DS;
regs->xss = __USER_DS;
regs->xcs = __USER_CS;
- if (regs->eflags & TF_MASK) {
- if (current->ptrace & PT_PTRACED) {
- ptrace_notify(SIGTRAP);
- } else {
- regs->eflags &= ~TF_MASK;
- }
- }
+
+ /*
+ * Clear TF when entering the signal handler, but
+ * notify any tracer that was single-stepping it.
+ * The tracer may want to single-step inside the
+ * handler too.
+ */
+ regs->eflags &= ~TF_MASK;
+ if (test_thread_flag(TIF_SINGLESTEP))
+ ptrace_notify(SIGTRAP);
#if DEBUG_SIG
printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",
regs->xes = __USER_DS;
regs->xss = __USER_DS;
regs->xcs = __USER_CS;
- if (regs->eflags & TF_MASK) {
- if (current->ptrace & PT_PTRACED) {
- ptrace_notify(SIGTRAP);
- } else {
- regs->eflags &= ~TF_MASK;
- }
- }
+
+ /*
+ * Clear TF when entering the signal handler, but
+ * notify any tracer that was single-stepping it.
+ * The tracer may want to single-step inside the
+ * handler too.
+ */
+ regs->eflags &= ~TF_MASK;
+ if (test_thread_flag(TIF_SINGLESTEP))
+ ptrace_notify(SIGTRAP);
#if DEBUG_SIG
printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",
* have been cleared if the watchpoint triggered
* inside the kernel.
*/
- __asm__("movl %0,%%db7" : : "r" (current->thread.debugreg[7]));
+ if (unlikely(current->thread.debugreg[7])) {
+ __asm__("movl %0,%%db7" : : "r" (current->thread.debugreg[7]));
+ }
/* Whee! Actually deliver the signal. */
handle_signal(signr, &info, &ka, oldset, regs);