Merge branch 'siginfo-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ebieder...
[linux-2.6-microblaze.git] / arch / x86 / kernel / traps.c
index 34a327f..8f6dcd8 100644 (file)
@@ -203,7 +203,7 @@ do_trap_no_signal(struct task_struct *tsk, int trapnr, const char *str,
                                return 0;
                }
        } else if (!user_mode(regs)) {
-               if (fixup_exception(regs, trapnr))
+               if (fixup_exception(regs, trapnr, error_code, 0))
                        return 0;
 
                tsk->thread.error_code = error_code;
@@ -358,6 +358,10 @@ dotraplinkage void do_double_fault(struct pt_regs *regs, long error_code)
                 * we won't enable interupts or schedule before we invoke
                 * general_protection, so nothing will clobber the stack
                 * frame we just set up.
+                *
+                * We will enter general_protection with kernel GSBASE,
+                * which is what the stub expects, given that the faulting
+                * RIP will be the IRET instruction.
                 */
                regs->ip = (unsigned long)general_protection;
                regs->sp = (unsigned long)&gpregs->orig_ax;
@@ -535,11 +539,21 @@ do_general_protection(struct pt_regs *regs, long error_code)
 
        tsk = current;
        if (!user_mode(regs)) {
-               if (fixup_exception(regs, X86_TRAP_GP))
+               if (fixup_exception(regs, X86_TRAP_GP, error_code, 0))
                        return;
 
                tsk->thread.error_code = error_code;
                tsk->thread.trap_nr = X86_TRAP_GP;
+
+               /*
+                * To be potentially processing a kprobe fault and to
+                * trust the result from kprobe_running(), we have to
+                * be non-preemptible.
+                */
+               if (!preemptible() && kprobe_running() &&
+                   kprobe_fault_handler(regs, X86_TRAP_GP))
+                       return;
+
                if (notify_die(DIE_GPF, desc, regs, error_code,
                               X86_TRAP_GP, SIGSEGV) != NOTIFY_STOP)
                        die(desc, regs, error_code);
@@ -815,7 +829,7 @@ static void math_error(struct pt_regs *regs, int error_code, int trapnr)
        cond_local_irq_enable(regs);
 
        if (!user_mode(regs)) {
-               if (fixup_exception(regs, trapnr))
+               if (fixup_exception(regs, trapnr, error_code, 0))
                        return;
 
                task->thread.error_code = error_code;