NOTIFY_STOP) {
                cond_local_irq_enable(regs);
                do_trap(trapnr, signr, str, regs, error_code, sicode, addr);
+               cond_local_irq_disable(regs);
        }
 }
 
                die("bounds", regs, error_code);
 
        do_trap(X86_TRAP_BR, SIGSEGV, "bounds", regs, error_code, 0, NULL);
+
+       cond_local_irq_disable(regs);
 }
 
 enum kernel_gp_hint {
 
        if (static_cpu_has(X86_FEATURE_UMIP)) {
                if (user_mode(regs) && fixup_umip_exception(regs))
-                       return;
+                       goto exit;
        }
 
        if (v8086_mode(regs)) {
                local_irq_enable();
                handle_vm86_fault((struct kernel_vm86_regs *) regs, error_code);
+               local_irq_disable();
                return;
        }
 
 
                show_signal(tsk, SIGSEGV, "", desc, regs, error_code);
                force_sig(SIGSEGV);
-
-               return;
+               goto exit;
        }
 
        if (fixup_exception(regs, X86_TRAP_GP, error_code, 0))
-               return;
+               goto exit;
 
        tsk->thread.error_code = error_code;
        tsk->thread.trap_nr = X86_TRAP_GP;
        if (!preemptible() &&
            kprobe_running() &&
            kprobe_fault_handler(regs, X86_TRAP_GP))
-               return;
+               goto exit;
 
        ret = notify_die(DIE_GPF, desc, regs, error_code, X86_TRAP_GP, SIGSEGV);
        if (ret == NOTIFY_STOP)
-               return;
+               goto exit;
 
        if (error_code)
                snprintf(desc, sizeof(desc), "segment-related " GPFSTR);
 
        die_addr(desc, regs, error_code, gp_addr);
 
+exit:
+       cond_local_irq_disable(regs);
 }
 NOKPROBE_SYMBOL(do_general_protection);
 
 
        if (!user_mode(regs)) {
                if (fixup_exception(regs, trapnr, error_code, 0))
-                       return;
+                       goto exit;
 
                task->thread.error_code = error_code;
                task->thread.trap_nr = trapnr;
                if (notify_die(DIE_TRAP, str, regs, error_code,
                                        trapnr, SIGFPE) != NOTIFY_STOP)
                        die(str, regs, error_code);
-               return;
+               goto exit;
        }
 
        /*
        si_code = fpu__exception_code(fpu, trapnr);
        /* Retry when we get spurious exceptions: */
        if (!si_code)
-               return;
+               goto exit;
 
        force_sig_fault(SIGFPE, si_code,
                        (void __user *)uprobe_get_trap_addr(regs));
+exit:
+       cond_local_irq_disable(regs);
 }
 
 dotraplinkage void do_coprocessor_error(struct pt_regs *regs, long error_code)
 
                info.regs = regs;
                math_emulate(&info);
+
+               cond_local_irq_disable(regs);
                return;
        }
 #endif
                do_trap(X86_TRAP_IRET, SIGILL, "iret exception", regs, error_code,
                        ILL_BADSTK, (void __user *)NULL);
        }
+       local_irq_disable();
 }
 #endif
 
 
 
                force_sig_fault(SIGSEGV, si_code, (void __user *)address);
 
+               local_irq_disable();
+
                return;
        }
 
                return;
 
        /* Was the fault on kernel-controlled part of the address space? */
-       if (unlikely(fault_in_kernel_space(address)))
+       if (unlikely(fault_in_kernel_space(address))) {
                do_kern_addr_fault(regs, hw_error_code, address);
-       else
+       } else {
                do_user_addr_fault(regs, hw_error_code, address);
+               /*
+                * User address page fault handling might have reenabled
+                * interrupts. Fixing up all potential exit points of
+                * do_user_addr_fault() and its leaf functions is just not
+                * doable w/o creating an unholy mess or turning the code
+                * upside down.
+                */
+               local_irq_disable();
+       }
 }
 NOKPROBE_SYMBOL(do_page_fault);