aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnton Vorontsov <anton.vorontsov@linaro.org>2012-09-24 17:27:56 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-09-26 16:52:36 -0400
commit0c57dfcc6c1d037243c2f8fbf62eab3633326ec0 (patch)
tree0cbdffff6807949c49b49190188d295d489b0c66
parent5c8124a0f8f50c5671b028b7a030d893a3a1a539 (diff)
tty/serial: Add kgdb_nmi driver
This special driver makes it possible to temporary use NMI debugger port as a normal console by issuing 'nmi_console' command (assuming that the port is attached to KGDB). Unlike KDB's disable_nmi command, with this driver you are always able to go back to the debugger using KGDB escape sequence ($3#33). This is because this console driver processes the input in NMI context, and thus is able to intercept the magic sequence. Note that since the console interprets input and uses polling communication methods, for things like PPP it is still better to fully detach debugger port from the KGDB NMI (i.e. disable_nmi), and use raw console. Usually, to enter the debugger one have to type the magic sequence, so initially the kernel will print the following prompt on the NMI debugger console: Type $3#33 to enter the debugger> For convenience, there is a kgdb_fiq.knock kernel command line option, when set to 0, this turns the special command to just a return key press, so the kernel will be printing this: Hit <return> to enter the debugger> This is more convenient for long debugging sessions, although it makes nmi_console feature somewhat useless. And for the cases when NMI connected to a dedicated button, the knocking can be disabled altogether by setting kgdb_fiq.knock to -1. Suggested-by: Colin Cross <ccross@android.com> Signed-off-by: Anton Vorontsov <anton.vorontsov@linaro.org> Acked-by: Alan Cox <alan@linux.intel.com> Acked-by: Jason Wessel <jason.wessel@windriver.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/tty/serial/Kconfig19
-rw-r--r--drivers/tty/serial/Makefile1
-rw-r--r--drivers/tty/serial/kgdb_nmi.c402
-rw-r--r--drivers/tty/serial/kgdboc.c9
-rw-r--r--include/linux/kgdb.h10
5 files changed, 441 insertions, 0 deletions
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index 2a9659dfb74c..233fbaaf2559 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -141,6 +141,25 @@ config SERIAL_ATMEL_TTYAT
141 141
142 Say Y if you have an external 8250/16C550 UART. If unsure, say N. 142 Say Y if you have an external 8250/16C550 UART. If unsure, say N.
143 143
144config SERIAL_KGDB_NMI
145 bool "Serial console over KGDB NMI debugger port"
146 depends on KGDB_SERIAL_CONSOLE
147 help
148 This special driver allows you to temporary use NMI debugger port
149 as a normal console (assuming that the port is attached to KGDB).
150
151 Unlike KDB's disable_nmi command, with this driver you are always
152 able to go back to the debugger using KGDB escape sequence ($3#33).
153 This is because this console driver processes the input in NMI
154 context, and thus is able to intercept the magic sequence.
155
156 Note that since the console interprets input and uses polling
157 communication methods, for things like PPP you still must fully
158 detach debugger port from the KGDB NMI (i.e. disable_nmi), and
159 use raw console.
160
161 If unsure, say N.
162
144config SERIAL_KS8695 163config SERIAL_KS8695
145 bool "Micrel KS8695 (Centaur) serial port support" 164 bool "Micrel KS8695 (Centaur) serial port support"
146 depends on ARCH_KS8695 165 depends on ARCH_KS8695
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
index ce88667cfd17..4f694dafa719 100644
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -61,6 +61,7 @@ obj-$(CONFIG_SERIAL_MSM_HS) += msm_serial_hs.o
61obj-$(CONFIG_SERIAL_NETX) += netx-serial.o 61obj-$(CONFIG_SERIAL_NETX) += netx-serial.o
62obj-$(CONFIG_SERIAL_OF_PLATFORM) += of_serial.o 62obj-$(CONFIG_SERIAL_OF_PLATFORM) += of_serial.o
63obj-$(CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL) += nwpserial.o 63obj-$(CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL) += nwpserial.o
64obj-$(CONFIG_SERIAL_KGDB_NMI) += kgdb_nmi.o
64obj-$(CONFIG_SERIAL_KS8695) += serial_ks8695.o 65obj-$(CONFIG_SERIAL_KS8695) += serial_ks8695.o
65obj-$(CONFIG_SERIAL_OMAP) += omap-serial.o 66obj-$(CONFIG_SERIAL_OMAP) += omap-serial.o
66obj-$(CONFIG_SERIAL_ALTERA_UART) += altera_uart.o 67obj-$(CONFIG_SERIAL_ALTERA_UART) += altera_uart.o
diff --git a/drivers/tty/serial/kgdb_nmi.c b/drivers/tty/serial/kgdb_nmi.c
new file mode 100644
index 000000000000..d185247ba1aa
--- /dev/null
+++ b/drivers/tty/serial/kgdb_nmi.c
@@ -0,0 +1,402 @@
1/*
2 * KGDB NMI serial console
3 *
4 * Copyright 2010 Google, Inc.
5 * Arve Hjønnevåg <arve@android.com>
6 * Colin Cross <ccross@android.com>
7 * Copyright 2012 Linaro Ltd.
8 * Anton Vorontsov <anton.vorontsov@linaro.org>
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License version 2 as published
12 * by the Free Software Foundation.
13 */
14
15#include <linux/kernel.h>
16#include <linux/module.h>
17#include <linux/compiler.h>
18#include <linux/init.h>
19#include <linux/slab.h>
20#include <linux/errno.h>
21#include <linux/atomic.h>
22#include <linux/console.h>
23#include <linux/tty.h>
24#include <linux/tty_driver.h>
25#include <linux/tty_flip.h>
26#include <linux/interrupt.h>
27#include <linux/hrtimer.h>
28#include <linux/tick.h>
29#include <linux/kfifo.h>
30#include <linux/kgdb.h>
31#include <linux/kdb.h>
32
33static int kgdb_nmi_knock = 1;
34module_param_named(knock, kgdb_nmi_knock, int, 0600);
35MODULE_PARM_DESC(knock, "if set to 1 (default), the special '$3#33' command " \
36 "must be used to enter the debugger; when set to 0, " \
37 "hitting return key is enough to enter the debugger; " \
38 "when set to -1, the debugger is entered immediately " \
39 "upon NMI");
40
41static char *kgdb_nmi_magic = "$3#33";
42module_param_named(magic, kgdb_nmi_magic, charp, 0600);
43MODULE_PARM_DESC(magic, "magic sequence to enter NMI debugger (default $3#33)");
44
45static bool kgdb_nmi_tty_enabled;
46
47static void kgdb_nmi_console_write(struct console *co, const char *s, uint c)
48{
49 int i;
50
51 if (!kgdb_nmi_tty_enabled || atomic_read(&kgdb_active) >= 0)
52 return;
53
54 for (i = 0; i < c; i++)
55 dbg_io_ops->write_char(s[i]);
56}
57
58static struct tty_driver *kgdb_nmi_tty_driver;
59
60static struct tty_driver *kgdb_nmi_console_device(struct console *co, int *idx)
61{
62 *idx = co->index;
63 return kgdb_nmi_tty_driver;
64}
65
66static struct console kgdb_nmi_console = {
67 .name = "ttyNMI",
68 .write = kgdb_nmi_console_write,
69 .device = kgdb_nmi_console_device,
70 .flags = CON_PRINTBUFFER | CON_ANYTIME | CON_ENABLED,
71 .index = -1,
72};
73
74/*
75 * This is usually the maximum rate on debug ports. We make fifo large enough
76 * to make copy-pasting to the terminal usable.
77 */
78#define KGDB_NMI_BAUD 115200
79#define KGDB_NMI_FIFO_SIZE roundup_pow_of_two(KGDB_NMI_BAUD / 8 / HZ)
80
81struct kgdb_nmi_tty_priv {
82 struct tty_port port;
83 struct tasklet_struct tlet;
84 STRUCT_KFIFO(char, KGDB_NMI_FIFO_SIZE) fifo;
85};
86
87static struct kgdb_nmi_tty_priv *kgdb_nmi_port_to_priv(struct tty_port *port)
88{
89 return container_of(port, struct kgdb_nmi_tty_priv, port);
90}
91
92/*
93 * Our debugging console is polled in a tasklet, so we'll check for input
94 * every tick. In HZ-less mode, we should program the next tick. We have
95 * to use the lowlevel stuff as no locks should be grabbed.
96 */
97#ifdef CONFIG_HIGH_RES_TIMERS
98static void kgdb_tty_poke(void)
99{
100 tick_program_event(ktime_get(), 0);
101}
102#else
103static inline void kgdb_tty_poke(void) {}
104#endif
105
106static struct tty_port *kgdb_nmi_port;
107
108static void kgdb_tty_recv(int ch)
109{
110 struct kgdb_nmi_tty_priv *priv;
111 char c = ch;
112
113 if (!kgdb_nmi_port || ch < 0)
114 return;
115 /*
116 * Can't use port->tty->driver_data as tty might be not there. Tasklet
117 * will check for tty and will get the ref, but here we don't have to
118 * do that, and actually, we can't: we're in NMI context, no locks are
119 * possible.
120 */
121 priv = kgdb_nmi_port_to_priv(kgdb_nmi_port);
122 kfifo_in(&priv->fifo, &c, 1);
123 kgdb_tty_poke();
124}
125
126static int kgdb_nmi_poll_one_knock(void)
127{
128 static int n;
129 int c = -1;
130 const char *magic = kgdb_nmi_magic;
131 size_t m = strlen(magic);
132 bool printch = 0;
133
134 c = dbg_io_ops->read_char();
135 if (c == NO_POLL_CHAR)
136 return c;
137
138 if (!kgdb_nmi_knock && (c == '\r' || c == '\n')) {
139 return 1;
140 } else if (c == magic[n]) {
141 n = (n + 1) % m;
142 if (!n)
143 return 1;
144 printch = 1;
145 } else {
146 n = 0;
147 }
148
149 if (kgdb_nmi_tty_enabled) {
150 kgdb_tty_recv(c);
151 return 0;
152 }
153
154 if (printch) {
155 kdb_printf("%c", c);
156 return 0;
157 }
158
159 kdb_printf("\r%s %s to enter the debugger> %*s",
160 kgdb_nmi_knock ? "Type" : "Hit",
161 kgdb_nmi_knock ? magic : "<return>", (int)m, "");
162 while (m--)
163 kdb_printf("\b");
164 return 0;
165}
166
167/**
168 * kgdb_nmi_poll_knock - Check if it is time to enter the debugger
169 *
170 * "Serial ports are often noisy, especially when muxed over another port (we
171 * often use serial over the headset connector). Noise on the async command
172 * line just causes characters that are ignored, on a command line that blocked
173 * execution noise would be catastrophic." -- Colin Cross
174 *
175 * So, this function implements KGDB/KDB knocking on the serial line: we won't
176 * enter the debugger until we receive a known magic phrase (which is actually
177 * "$3#33", known as "escape to KDB" command. There is also a relaxed variant
178 * of knocking, i.e. just pressing the return key is enough to enter the
179 * debugger. And if knocking is disabled, the function always returns 1.
180 */
181bool kgdb_nmi_poll_knock(void)
182{
183 if (kgdb_nmi_knock < 0)
184 return 1;
185
186 while (1) {
187 int ret;
188
189 ret = kgdb_nmi_poll_one_knock();
190 if (ret == NO_POLL_CHAR)
191 return 0;
192 else if (ret == 1)
193 break;
194 }
195 return 1;
196}
197
198/*
199 * The tasklet is cheap, it does not cause wakeups when reschedules itself,
200 * instead it waits for the next tick.
201 */
202static void kgdb_nmi_tty_receiver(unsigned long data)
203{
204 struct kgdb_nmi_tty_priv *priv = (void *)data;
205 struct tty_struct *tty;
206 char ch;
207
208 tasklet_schedule(&priv->tlet);
209
210 if (likely(!kgdb_nmi_tty_enabled || !kfifo_len(&priv->fifo)))
211 return;
212
213 /* Port is there, but tty might be hung up, check. */
214 tty = tty_port_tty_get(kgdb_nmi_port);
215 if (!tty)
216 return;
217
218 while (kfifo_out(&priv->fifo, &ch, 1))
219 tty_insert_flip_char(priv->port.tty, ch, TTY_NORMAL);
220 tty_flip_buffer_push(priv->port.tty);
221
222 tty_kref_put(tty);
223}
224
225static int kgdb_nmi_tty_activate(struct tty_port *port, struct tty_struct *tty)
226{
227 struct kgdb_nmi_tty_priv *priv = tty->driver_data;
228
229 kgdb_nmi_port = port;
230 tasklet_schedule(&priv->tlet);
231 return 0;
232}
233
234static void kgdb_nmi_tty_shutdown(struct tty_port *port)
235{
236 struct kgdb_nmi_tty_priv *priv = port->tty->driver_data;
237
238 tasklet_kill(&priv->tlet);
239 kgdb_nmi_port = NULL;
240}
241
242static const struct tty_port_operations kgdb_nmi_tty_port_ops = {
243 .activate = kgdb_nmi_tty_activate,
244 .shutdown = kgdb_nmi_tty_shutdown,
245};
246
247static int kgdb_nmi_tty_install(struct tty_driver *drv, struct tty_struct *tty)
248{
249 struct kgdb_nmi_tty_priv *priv;
250 int ret;
251
252 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
253 if (!priv)
254 return -ENOMEM;
255
256 INIT_KFIFO(priv->fifo);
257 tasklet_init(&priv->tlet, kgdb_nmi_tty_receiver, (unsigned long)priv);
258 tty_port_init(&priv->port);
259 priv->port.ops = &kgdb_nmi_tty_port_ops;
260 tty->driver_data = priv;
261
262 ret = tty_port_install(&priv->port, drv, tty);
263 if (ret) {
264 pr_err("%s: can't install tty port: %d\n", __func__, ret);
265 goto err;
266 }
267 return 0;
268err:
269 kfree(priv);
270 return ret;
271}
272
273static void kgdb_nmi_tty_cleanup(struct tty_struct *tty)
274{
275 struct kgdb_nmi_tty_priv *priv = tty->driver_data;
276
277 tty->driver_data = NULL;
278 kfree(priv);
279}
280
281static int kgdb_nmi_tty_open(struct tty_struct *tty, struct file *file)
282{
283 struct kgdb_nmi_tty_priv *priv = tty->driver_data;
284
285 return tty_port_open(&priv->port, tty, file);
286}
287
288static void kgdb_nmi_tty_close(struct tty_struct *tty, struct file *file)
289{
290 struct kgdb_nmi_tty_priv *priv = tty->driver_data;
291
292 tty_port_close(&priv->port, tty, file);
293}
294
295static void kgdb_nmi_tty_hangup(struct tty_struct *tty)
296{
297 struct kgdb_nmi_tty_priv *priv = tty->driver_data;
298
299 tty_port_hangup(&priv->port);
300}
301
302static int kgdb_nmi_tty_write_room(struct tty_struct *tty)
303{
304 /* Actually, we can handle any amount as we use polled writes. */
305 return 2048;
306}
307
308static int kgdb_nmi_tty_write(struct tty_struct *tty, const unchar *buf, int c)
309{
310 int i;
311
312 for (i = 0; i < c; i++)
313 dbg_io_ops->write_char(buf[i]);
314 return c;
315}
316
317static const struct tty_operations kgdb_nmi_tty_ops = {
318 .open = kgdb_nmi_tty_open,
319 .close = kgdb_nmi_tty_close,
320 .install = kgdb_nmi_tty_install,
321 .cleanup = kgdb_nmi_tty_cleanup,
322 .hangup = kgdb_nmi_tty_hangup,
323 .write_room = kgdb_nmi_tty_write_room,
324 .write = kgdb_nmi_tty_write,
325};
326
327static int kgdb_nmi_enable_console(int argc, const char *argv[])
328{
329 kgdb_nmi_tty_enabled = !(argc == 1 && !strcmp(argv[1], "off"));
330 return 0;
331}
332
333int kgdb_register_nmi_console(void)
334{
335 int ret;
336
337 if (!arch_kgdb_ops.enable_nmi)
338 return 0;
339
340 kgdb_nmi_tty_driver = alloc_tty_driver(1);
341 if (!kgdb_nmi_tty_driver) {
342 pr_err("%s: cannot allocate tty\n", __func__);
343 return -ENOMEM;
344 }
345 kgdb_nmi_tty_driver->driver_name = "ttyNMI";
346 kgdb_nmi_tty_driver->name = "ttyNMI";
347 kgdb_nmi_tty_driver->num = 1;
348 kgdb_nmi_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
349 kgdb_nmi_tty_driver->subtype = SERIAL_TYPE_NORMAL;
350 kgdb_nmi_tty_driver->flags = TTY_DRIVER_REAL_RAW;
351 kgdb_nmi_tty_driver->init_termios = tty_std_termios;
352 tty_termios_encode_baud_rate(&kgdb_nmi_tty_driver->init_termios,
353 KGDB_NMI_BAUD, KGDB_NMI_BAUD);
354 tty_set_operations(kgdb_nmi_tty_driver, &kgdb_nmi_tty_ops);
355
356 ret = tty_register_driver(kgdb_nmi_tty_driver);
357 if (ret) {
358 pr_err("%s: can't register tty driver: %d\n", __func__, ret);
359 goto err_drv_reg;
360 }
361
362 ret = kdb_register("nmi_console", kgdb_nmi_enable_console, "[off]",
363 "switch to Linux NMI console", 0);
364 if (ret) {
365 pr_err("%s: can't register kdb command: %d\n", __func__, ret);
366 goto err_kdb_reg;
367 }
368
369 register_console(&kgdb_nmi_console);
370 arch_kgdb_ops.enable_nmi(1);
371
372 return 0;
373err_kdb_reg:
374 tty_unregister_driver(kgdb_nmi_tty_driver);
375err_drv_reg:
376 put_tty_driver(kgdb_nmi_tty_driver);
377 return ret;
378}
379EXPORT_SYMBOL_GPL(kgdb_register_nmi_console);
380
381int kgdb_unregister_nmi_console(void)
382{
383 int ret;
384
385 if (!arch_kgdb_ops.enable_nmi)
386 return 0;
387 arch_kgdb_ops.enable_nmi(0);
388
389 kdb_unregister("nmi_console");
390
391 ret = unregister_console(&kgdb_nmi_console);
392 if (ret)
393 return ret;
394
395 ret = tty_unregister_driver(kgdb_nmi_tty_driver);
396 if (ret)
397 return ret;
398 put_tty_driver(kgdb_nmi_tty_driver);
399
400 return 0;
401}
402EXPORT_SYMBOL_GPL(kgdb_unregister_nmi_console);
diff --git a/drivers/tty/serial/kgdboc.c b/drivers/tty/serial/kgdboc.c
index 2b42a01a81c6..3f63d834cbc9 100644
--- a/drivers/tty/serial/kgdboc.c
+++ b/drivers/tty/serial/kgdboc.c
@@ -145,6 +145,8 @@ __setup("kgdboc=", kgdboc_option_setup);
145 145
146static void cleanup_kgdboc(void) 146static void cleanup_kgdboc(void)
147{ 147{
148 if (kgdb_unregister_nmi_console())
149 return;
148 kgdboc_unregister_kbd(); 150 kgdboc_unregister_kbd();
149 if (configured == 1) 151 if (configured == 1)
150 kgdb_unregister_io_module(&kgdboc_io_ops); 152 kgdb_unregister_io_module(&kgdboc_io_ops);
@@ -198,11 +200,18 @@ do_register:
198 if (err) 200 if (err)
199 goto noconfig; 201 goto noconfig;
200 202
203 err = kgdb_register_nmi_console();
204 if (err)
205 goto nmi_con_failed;
206
201 configured = 1; 207 configured = 1;
202 208
203 return 0; 209 return 0;
204 210
211nmi_con_failed:
212 kgdb_unregister_io_module(&kgdboc_io_ops);
205noconfig: 213noconfig:
214 kgdboc_unregister_kbd();
206 config[0] = 0; 215 config[0] = 0;
207 configured = 0; 216 configured = 0;
208 cleanup_kgdboc(); 217 cleanup_kgdboc();
diff --git a/include/linux/kgdb.h b/include/linux/kgdb.h
index 7800cce284db..4dff0c6ed58f 100644
--- a/include/linux/kgdb.h
+++ b/include/linux/kgdb.h
@@ -286,6 +286,16 @@ extern struct kgdb_arch arch_kgdb_ops;
286 286
287extern unsigned long __weak kgdb_arch_pc(int exception, struct pt_regs *regs); 287extern unsigned long __weak kgdb_arch_pc(int exception, struct pt_regs *regs);
288 288
289#ifdef CONFIG_SERIAL_KGDB_NMI
290extern int kgdb_register_nmi_console(void);
291extern int kgdb_unregister_nmi_console(void);
292extern bool kgdb_nmi_poll_knock(void);
293#else
294static inline int kgdb_register_nmi_console(void) { return 0; }
295static inline int kgdb_unregister_nmi_console(void) { return 0; }
296static inline bool kgdb_nmi_poll_knock(void) { return 1; }
297#endif
298
289extern int kgdb_register_io_module(struct kgdb_io *local_kgdb_io_ops); 299extern int kgdb_register_io_module(struct kgdb_io *local_kgdb_io_ops);
290extern void kgdb_unregister_io_module(struct kgdb_io *local_kgdb_io_ops); 300extern void kgdb_unregister_io_module(struct kgdb_io *local_kgdb_io_ops);
291extern struct kgdb_io *dbg_io_ops; 301extern struct kgdb_io *dbg_io_ops;