unsigned vector = ~regs->orig_ax;
        unsigned irq;
  
+       /*
+        * NB: Unlike exception entries, IRQ entries do not reliably
+        * handle context tracking in the low-level entry code.  This is
+        * because syscall entries execute briefly with IRQs on before
+        * updating context tracking state, so we can take an IRQ from
+        * kernel mode with CONTEXT_USER.  The low-level entry code only
+        * updates the context if we came from user mode, so we won't
+        * switch to CONTEXT_KERNEL.  We'll fix that once the syscall
+        * code is cleaned up enough that we can cleanly defer enabling
+        * IRQs.
+        */
+ 
        entering_irq();
  
 -      rcu_lockdep_assert(rcu_is_watching(), "IRQ failed to wake up RCU");
+       /* entering_irq() tells RCU that we're not quiescent.  Check it. */
++      RCU_LOCKDEP_WARN(!rcu_is_watching(), "IRQ failed to wake up RCU");
+ 
        irq = __this_cpu_read(vector_irq[vector]);
  
        if (!handle_irq(irq, regs)) {
 
        preempt_count_dec();
  }
  
- enum ctx_state ist_enter(struct pt_regs *regs)
+ void ist_enter(struct pt_regs *regs)
  {
-       enum ctx_state prev_state;
- 
        if (user_mode(regs)) {
-               /* Other than that, we're just an exception. */
-               prev_state = exception_enter();
 -              rcu_lockdep_assert(rcu_is_watching(), "entry code didn't wake RCU");
++              RCU_LOCKDEP_WARN(!rcu_is_watching(), "entry code didn't wake RCU");
        } else {
                /*
                 * We might have interrupted pretty much anything.  In
        preempt_count_add(HARDIRQ_OFFSET);
  
        /* This code is a bit fragile.  Test it. */
 -      rcu_lockdep_assert(rcu_is_watching(), "ist_enter didn't work");
 +      RCU_LOCKDEP_WARN(!rcu_is_watching(), "ist_enter didn't work");
- 
-       return prev_state;
  }
  
- void ist_exit(struct pt_regs *regs, enum ctx_state prev_state)
+ void ist_exit(struct pt_regs *regs)
  {
-       /* Must be before exception_exit. */
        preempt_count_sub(HARDIRQ_OFFSET);
  
-       if (user_mode(regs))
-               return exception_exit(prev_state);
-       else
+       if (!user_mode(regs))
                rcu_nmi_exit();
  }
  
  static void do_error_trap(struct pt_regs *regs, long error_code, char *str,
                          unsigned long trapnr, int signr)
  {
-       enum ctx_state prev_state = exception_enter();
        siginfo_t info;
  
 -      rcu_lockdep_assert(rcu_is_watching(), "entry code didn't wake RCU");
++      RCU_LOCKDEP_WARN(!rcu_is_watching(), "entry code didn't wake RCU");
+ 
        if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) !=
                        NOTIFY_STOP) {
                conditional_sti(regs);
        const struct bndcsr *bndcsr;
        siginfo_t *info;
  
-       prev_state = exception_enter();
 -      rcu_lockdep_assert(rcu_is_watching(), "entry code didn't wake RCU");
++      RCU_LOCKDEP_WARN(!rcu_is_watching(), "entry code didn't wake RCU");
        if (notify_die(DIE_TRAP, "bounds", regs, error_code,
                        X86_TRAP_BR, SIGSEGV) == NOTIFY_STOP)
-               goto exit;
+               return;
        conditional_sti(regs);
  
        if (!user_mode(regs))
  do_general_protection(struct pt_regs *regs, long error_code)
  {
        struct task_struct *tsk;
-       enum ctx_state prev_state;
  
-       prev_state = exception_enter();
 -      rcu_lockdep_assert(rcu_is_watching(), "entry code didn't wake RCU");
++      RCU_LOCKDEP_WARN(!rcu_is_watching(), "entry code didn't wake RCU");
        conditional_sti(regs);
  
        if (v8086_mode(regs)) {
        if (poke_int3_handler(regs))
                return;
  
-       prev_state = ist_enter(regs);
+       ist_enter(regs);
 -      rcu_lockdep_assert(rcu_is_watching(), "entry code didn't wake RCU");
++      RCU_LOCKDEP_WARN(!rcu_is_watching(), "entry code didn't wake RCU");
  #ifdef CONFIG_KGDB_LOW_LEVEL_TRAP
        if (kgdb_ll_trap(DIE_INT3, "int3", regs, error_code, X86_TRAP_BP,
                                SIGTRAP) == NOTIFY_STOP)
  
  dotraplinkage void do_coprocessor_error(struct pt_regs *regs, long error_code)
  {
-       enum ctx_state prev_state;
- 
-       prev_state = exception_enter();
 -      rcu_lockdep_assert(rcu_is_watching(), "entry code didn't wake RCU");
++      RCU_LOCKDEP_WARN(!rcu_is_watching(), "entry code didn't wake RCU");
        math_error(regs, error_code, X86_TRAP_MF);
-       exception_exit(prev_state);
  }
  
  dotraplinkage void
  do_simd_coprocessor_error(struct pt_regs *regs, long error_code)
  {
-       enum ctx_state prev_state;
- 
-       prev_state = exception_enter();
 -      rcu_lockdep_assert(rcu_is_watching(), "entry code didn't wake RCU");
++      RCU_LOCKDEP_WARN(!rcu_is_watching(), "entry code didn't wake RCU");
        math_error(regs, error_code, X86_TRAP_XF);
-       exception_exit(prev_state);
  }
  
  dotraplinkage void
  dotraplinkage void
  do_device_not_available(struct pt_regs *regs, long error_code)
  {
-       enum ctx_state prev_state;
- 
-       prev_state = exception_enter();
 -      rcu_lockdep_assert(rcu_is_watching(), "entry code didn't wake RCU");
++      RCU_LOCKDEP_WARN(!rcu_is_watching(), "entry code didn't wake RCU");
        BUG_ON(use_eager_fpu());
  
  #ifdef CONFIG_MATH_EMULATION
  dotraplinkage void do_iret_error(struct pt_regs *regs, long error_code)
  {
        siginfo_t info;
-       enum ctx_state prev_state;
  
-       prev_state = exception_enter();
 -      rcu_lockdep_assert(rcu_is_watching(), "entry code didn't wake RCU");
++      RCU_LOCKDEP_WARN(!rcu_is_watching(), "entry code didn't wake RCU");
        local_irq_enable();
  
        info.si_signo = SIGILL;