x86/traps: Split int3 handler up
authorPeter Zijlstra <peterz@infradead.org>
Thu, 5 Mar 2020 15:09:52 +0000 (16:09 +0100)
committerThomas Gleixner <tglx@linutronix.de>
Thu, 11 Jun 2020 13:14:55 +0000 (15:14 +0200)
For code simplicity split up the int3 handler into a kernel and user part
which makes the code flow simpler to understand.

Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Alexandre Chartre <alexandre.chartre@oracle.com>
Link: https://lkml.kernel.org/r/20200505135314.045220765@linutronix.de
arch/x86/kernel/traps.c

index 0ad12df..21c8cfc 100644 (file)
@@ -568,6 +568,35 @@ exit:
        cond_local_irq_disable(regs);
 }
 
+static bool do_int3(struct pt_regs *regs)
+{
+       int res;
+
+#ifdef CONFIG_KGDB_LOW_LEVEL_TRAP
+       if (kgdb_ll_trap(DIE_INT3, "int3", regs, 0, X86_TRAP_BP,
+                        SIGTRAP) == NOTIFY_STOP)
+               return true;
+#endif /* CONFIG_KGDB_LOW_LEVEL_TRAP */
+
+#ifdef CONFIG_KPROBES
+       if (kprobe_int3_handler(regs))
+               return true;
+#endif
+       res = notify_die(DIE_INT3, "int3", regs, 0, X86_TRAP_BP, SIGTRAP);
+
+       return res == NOTIFY_STOP;
+}
+
+static void do_int3_user(struct pt_regs *regs)
+{
+       if (do_int3(regs))
+               return;
+
+       cond_local_irq_enable(regs);
+       do_trap(X86_TRAP_BP, SIGTRAP, "int3", regs, 0, 0, NULL);
+       cond_local_irq_disable(regs);
+}
+
 DEFINE_IDTENTRY_RAW(exc_int3)
 {
        /*
@@ -585,37 +614,20 @@ DEFINE_IDTENTRY_RAW(exc_int3)
         * because the INT3 could have been hit in any context including
         * NMI.
         */
-       if (user_mode(regs))
+       if (user_mode(regs)) {
                idtentry_enter(regs);
-       else
-               nmi_enter();
-
-       instrumentation_begin();
-#ifdef CONFIG_KGDB_LOW_LEVEL_TRAP
-       if (kgdb_ll_trap(DIE_INT3, "int3", regs, 0, X86_TRAP_BP,
-                               SIGTRAP) == NOTIFY_STOP)
-               goto exit;
-#endif /* CONFIG_KGDB_LOW_LEVEL_TRAP */
-
-#ifdef CONFIG_KPROBES
-       if (kprobe_int3_handler(regs))
-               goto exit;
-#endif
-
-       if (notify_die(DIE_INT3, "int3", regs, 0, X86_TRAP_BP,
-                       SIGTRAP) == NOTIFY_STOP)
-               goto exit;
-
-       cond_local_irq_enable(regs);
-       do_trap(X86_TRAP_BP, SIGTRAP, "int3", regs, 0, 0, NULL);
-       cond_local_irq_disable(regs);
-
-exit:
-       instrumentation_end();
-       if (user_mode(regs))
+               instrumentation_begin();
+               do_int3_user(regs);
+               instrumentation_end();
                idtentry_exit(regs);
-       else
+       } else {
+               nmi_enter();
+               instrumentation_begin();
+               if (!do_int3(regs))
+                       die("int3", regs, 0);
+               instrumentation_end();
                nmi_exit();
+       }
 }
 
 #ifdef CONFIG_X86_64