1616#include <linux/console.h>
1717#include <linux/vt_kern.h>
1818#include <linux/input.h>
19+ #include <linux/irq_work.h>
1920#include <linux/module.h>
2021
2122#define MAX_CONFIG_LEN 40
@@ -35,6 +36,25 @@ static int kgdboc_use_kms; /* 1 if we use kernel mode switching */
3536static struct tty_driver * kgdb_tty_driver ;
3637static int kgdb_tty_line ;
3738
39+ /*
40+ * When we leave the debug trap handler we need to reset the keyboard status
41+ * (since the original keyboard state gets partially clobbered by kdb use of
42+ * the keyboard).
43+ *
44+ * The path to deliver the reset is somewhat circuitous.
45+ *
46+ * To deliver the reset we register an input handler, reset the keyboard and
47+ * then deregister the input handler. However, to get this done right, we do
48+ * have to carefully manage the calling context because we can only register
49+ * input handlers from task context.
50+ *
51+ * In particular we need to trigger the action from the debug trap handler with
52+ * all its NMI and/or NMI-like oddities. To solve this the kgdboc trap exit code
53+ * (the "post_exception" callback) uses irq_work_queue(), which is NMI-safe, to
54+ * schedule a callback from a hardirq context. From there we have to defer the
55+ * work again, this time using schedule_work(), to get a callback using the
56+ * system workqueue, which runs in task context.
57+ */
3858#ifdef CONFIG_KDB_KEYBOARD
3959static int kgdboc_reset_connect (struct input_handler * handler ,
4060 struct input_dev * dev ,
@@ -86,10 +106,17 @@ static void kgdboc_restore_input_helper(struct work_struct *dummy)
86106
87107static DECLARE_WORK (kgdboc_restore_input_work , kgdboc_restore_input_helper ) ;
88108
109+ static void kgdboc_queue_restore_input_helper (struct irq_work * unused )
110+ {
111+ schedule_work (& kgdboc_restore_input_work );
112+ }
113+
114+ static DEFINE_IRQ_WORK (kgdboc_restore_input_irq_work , kgdboc_queue_restore_input_helper ) ;
115+
89116static void kgdboc_restore_input (void )
90117{
91118 if (likely (system_state == SYSTEM_RUNNING ))
92- schedule_work ( & kgdboc_restore_input_work );
119+ irq_work_queue ( & kgdboc_restore_input_irq_work );
93120}
94121
95122static int kgdboc_register_kbd (char * * cptr )
@@ -120,6 +147,7 @@ static void kgdboc_unregister_kbd(void)
120147 i -- ;
121148 }
122149 }
150+ irq_work_sync (& kgdboc_restore_input_irq_work );
123151 flush_work (& kgdboc_restore_input_work );
124152}
125153#else /* ! CONFIG_KDB_KEYBOARD */
0 commit comments