10c57dfccSAnton Vorontsov /* 20c57dfccSAnton Vorontsov * KGDB NMI serial console 30c57dfccSAnton Vorontsov * 40c57dfccSAnton Vorontsov * Copyright 2010 Google, Inc. 50c57dfccSAnton Vorontsov * Arve Hjønnevåg <arve@android.com> 60c57dfccSAnton Vorontsov * Colin Cross <ccross@android.com> 70c57dfccSAnton Vorontsov * Copyright 2012 Linaro Ltd. 80c57dfccSAnton Vorontsov * Anton Vorontsov <anton.vorontsov@linaro.org> 90c57dfccSAnton Vorontsov * 100c57dfccSAnton Vorontsov * This program is free software; you can redistribute it and/or modify it 110c57dfccSAnton Vorontsov * under the terms of the GNU General Public License version 2 as published 120c57dfccSAnton Vorontsov * by the Free Software Foundation. 130c57dfccSAnton Vorontsov */ 140c57dfccSAnton Vorontsov 150c57dfccSAnton Vorontsov #include <linux/kernel.h> 160c57dfccSAnton Vorontsov #include <linux/module.h> 170c57dfccSAnton Vorontsov #include <linux/compiler.h> 180c57dfccSAnton Vorontsov #include <linux/init.h> 190c57dfccSAnton Vorontsov #include <linux/slab.h> 200c57dfccSAnton Vorontsov #include <linux/errno.h> 210c57dfccSAnton Vorontsov #include <linux/atomic.h> 220c57dfccSAnton Vorontsov #include <linux/console.h> 230c57dfccSAnton Vorontsov #include <linux/tty.h> 240c57dfccSAnton Vorontsov #include <linux/tty_driver.h> 250c57dfccSAnton Vorontsov #include <linux/tty_flip.h> 260c57dfccSAnton Vorontsov #include <linux/interrupt.h> 270c57dfccSAnton Vorontsov #include <linux/hrtimer.h> 280c57dfccSAnton Vorontsov #include <linux/tick.h> 290c57dfccSAnton Vorontsov #include <linux/kfifo.h> 300c57dfccSAnton Vorontsov #include <linux/kgdb.h> 310c57dfccSAnton Vorontsov #include <linux/kdb.h> 320c57dfccSAnton Vorontsov 330c57dfccSAnton Vorontsov static int kgdb_nmi_knock = 1; 340c57dfccSAnton Vorontsov module_param_named(knock, kgdb_nmi_knock, int, 0600); 350c57dfccSAnton Vorontsov MODULE_PARM_DESC(knock, "if set to 1 (default), the special '$3#33' command " \ 360c57dfccSAnton Vorontsov "must be used to enter the debugger; when set to 0, " \ 370c57dfccSAnton Vorontsov "hitting return key is enough to enter the debugger; " \ 380c57dfccSAnton Vorontsov "when set to -1, the debugger is entered immediately " \ 390c57dfccSAnton Vorontsov "upon NMI"); 400c57dfccSAnton Vorontsov 410c57dfccSAnton Vorontsov static char *kgdb_nmi_magic = "$3#33"; 420c57dfccSAnton Vorontsov module_param_named(magic, kgdb_nmi_magic, charp, 0600); 430c57dfccSAnton Vorontsov MODULE_PARM_DESC(magic, "magic sequence to enter NMI debugger (default $3#33)"); 440c57dfccSAnton Vorontsov 450c57dfccSAnton Vorontsov static bool kgdb_nmi_tty_enabled; 460c57dfccSAnton Vorontsov 470c57dfccSAnton Vorontsov static void kgdb_nmi_console_write(struct console *co, const char *s, uint c) 480c57dfccSAnton Vorontsov { 490c57dfccSAnton Vorontsov int i; 500c57dfccSAnton Vorontsov 510c57dfccSAnton Vorontsov if (!kgdb_nmi_tty_enabled || atomic_read(&kgdb_active) >= 0) 520c57dfccSAnton Vorontsov return; 530c57dfccSAnton Vorontsov 540c57dfccSAnton Vorontsov for (i = 0; i < c; i++) 550c57dfccSAnton Vorontsov dbg_io_ops->write_char(s[i]); 560c57dfccSAnton Vorontsov } 570c57dfccSAnton Vorontsov 580c57dfccSAnton Vorontsov static struct tty_driver *kgdb_nmi_tty_driver; 590c57dfccSAnton Vorontsov 600c57dfccSAnton Vorontsov static struct tty_driver *kgdb_nmi_console_device(struct console *co, int *idx) 610c57dfccSAnton Vorontsov { 620c57dfccSAnton Vorontsov *idx = co->index; 630c57dfccSAnton Vorontsov return kgdb_nmi_tty_driver; 640c57dfccSAnton Vorontsov } 650c57dfccSAnton Vorontsov 660c57dfccSAnton Vorontsov static struct console kgdb_nmi_console = { 670c57dfccSAnton Vorontsov .name = "ttyNMI", 680c57dfccSAnton Vorontsov .write = kgdb_nmi_console_write, 690c57dfccSAnton Vorontsov .device = kgdb_nmi_console_device, 700c57dfccSAnton Vorontsov .flags = CON_PRINTBUFFER | CON_ANYTIME | CON_ENABLED, 710c57dfccSAnton Vorontsov .index = -1, 720c57dfccSAnton Vorontsov }; 730c57dfccSAnton Vorontsov 740c57dfccSAnton Vorontsov /* 750c57dfccSAnton Vorontsov * This is usually the maximum rate on debug ports. We make fifo large enough 760c57dfccSAnton Vorontsov * to make copy-pasting to the terminal usable. 770c57dfccSAnton Vorontsov */ 780c57dfccSAnton Vorontsov #define KGDB_NMI_BAUD 115200 790c57dfccSAnton Vorontsov #define KGDB_NMI_FIFO_SIZE roundup_pow_of_two(KGDB_NMI_BAUD / 8 / HZ) 800c57dfccSAnton Vorontsov 810c57dfccSAnton Vorontsov struct kgdb_nmi_tty_priv { 820c57dfccSAnton Vorontsov struct tty_port port; 830c57dfccSAnton Vorontsov struct tasklet_struct tlet; 840c57dfccSAnton Vorontsov STRUCT_KFIFO(char, KGDB_NMI_FIFO_SIZE) fifo; 850c57dfccSAnton Vorontsov }; 860c57dfccSAnton Vorontsov 870c57dfccSAnton Vorontsov static struct kgdb_nmi_tty_priv *kgdb_nmi_port_to_priv(struct tty_port *port) 880c57dfccSAnton Vorontsov { 890c57dfccSAnton Vorontsov return container_of(port, struct kgdb_nmi_tty_priv, port); 900c57dfccSAnton Vorontsov } 910c57dfccSAnton Vorontsov 920c57dfccSAnton Vorontsov /* 930c57dfccSAnton Vorontsov * Our debugging console is polled in a tasklet, so we'll check for input 940c57dfccSAnton Vorontsov * every tick. In HZ-less mode, we should program the next tick. We have 950c57dfccSAnton Vorontsov * to use the lowlevel stuff as no locks should be grabbed. 960c57dfccSAnton Vorontsov */ 970c57dfccSAnton Vorontsov #ifdef CONFIG_HIGH_RES_TIMERS 980c57dfccSAnton Vorontsov static void kgdb_tty_poke(void) 990c57dfccSAnton Vorontsov { 1000c57dfccSAnton Vorontsov tick_program_event(ktime_get(), 0); 1010c57dfccSAnton Vorontsov } 1020c57dfccSAnton Vorontsov #else 1030c57dfccSAnton Vorontsov static inline void kgdb_tty_poke(void) {} 1040c57dfccSAnton Vorontsov #endif 1050c57dfccSAnton Vorontsov 1060c57dfccSAnton Vorontsov static struct tty_port *kgdb_nmi_port; 1070c57dfccSAnton Vorontsov 1080c57dfccSAnton Vorontsov static void kgdb_tty_recv(int ch) 1090c57dfccSAnton Vorontsov { 1100c57dfccSAnton Vorontsov struct kgdb_nmi_tty_priv *priv; 1110c57dfccSAnton Vorontsov char c = ch; 1120c57dfccSAnton Vorontsov 1130c57dfccSAnton Vorontsov if (!kgdb_nmi_port || ch < 0) 1140c57dfccSAnton Vorontsov return; 1150c57dfccSAnton Vorontsov /* 1160c57dfccSAnton Vorontsov * Can't use port->tty->driver_data as tty might be not there. Tasklet 1170c57dfccSAnton Vorontsov * will check for tty and will get the ref, but here we don't have to 1180c57dfccSAnton Vorontsov * do that, and actually, we can't: we're in NMI context, no locks are 1190c57dfccSAnton Vorontsov * possible. 1200c57dfccSAnton Vorontsov */ 1210c57dfccSAnton Vorontsov priv = kgdb_nmi_port_to_priv(kgdb_nmi_port); 1220c57dfccSAnton Vorontsov kfifo_in(&priv->fifo, &c, 1); 1230c57dfccSAnton Vorontsov kgdb_tty_poke(); 1240c57dfccSAnton Vorontsov } 1250c57dfccSAnton Vorontsov 1260c57dfccSAnton Vorontsov static int kgdb_nmi_poll_one_knock(void) 1270c57dfccSAnton Vorontsov { 1280c57dfccSAnton Vorontsov static int n; 1290c57dfccSAnton Vorontsov int c = -1; 1300c57dfccSAnton Vorontsov const char *magic = kgdb_nmi_magic; 1310c57dfccSAnton Vorontsov size_t m = strlen(magic); 1320c57dfccSAnton Vorontsov bool printch = 0; 1330c57dfccSAnton Vorontsov 1340c57dfccSAnton Vorontsov c = dbg_io_ops->read_char(); 1350c57dfccSAnton Vorontsov if (c == NO_POLL_CHAR) 1360c57dfccSAnton Vorontsov return c; 1370c57dfccSAnton Vorontsov 1380c57dfccSAnton Vorontsov if (!kgdb_nmi_knock && (c == '\r' || c == '\n')) { 1390c57dfccSAnton Vorontsov return 1; 1400c57dfccSAnton Vorontsov } else if (c == magic[n]) { 1410c57dfccSAnton Vorontsov n = (n + 1) % m; 1420c57dfccSAnton Vorontsov if (!n) 1430c57dfccSAnton Vorontsov return 1; 1440c57dfccSAnton Vorontsov printch = 1; 1450c57dfccSAnton Vorontsov } else { 1460c57dfccSAnton Vorontsov n = 0; 1470c57dfccSAnton Vorontsov } 1480c57dfccSAnton Vorontsov 1490c57dfccSAnton Vorontsov if (kgdb_nmi_tty_enabled) { 1500c57dfccSAnton Vorontsov kgdb_tty_recv(c); 1510c57dfccSAnton Vorontsov return 0; 1520c57dfccSAnton Vorontsov } 1530c57dfccSAnton Vorontsov 1540c57dfccSAnton Vorontsov if (printch) { 1550c57dfccSAnton Vorontsov kdb_printf("%c", c); 1560c57dfccSAnton Vorontsov return 0; 1570c57dfccSAnton Vorontsov } 1580c57dfccSAnton Vorontsov 1590c57dfccSAnton Vorontsov kdb_printf("\r%s %s to enter the debugger> %*s", 1600c57dfccSAnton Vorontsov kgdb_nmi_knock ? "Type" : "Hit", 1610c57dfccSAnton Vorontsov kgdb_nmi_knock ? magic : "<return>", (int)m, ""); 1620c57dfccSAnton Vorontsov while (m--) 1630c57dfccSAnton Vorontsov kdb_printf("\b"); 1640c57dfccSAnton Vorontsov return 0; 1650c57dfccSAnton Vorontsov } 1660c57dfccSAnton Vorontsov 1670c57dfccSAnton Vorontsov /** 1680c57dfccSAnton Vorontsov * kgdb_nmi_poll_knock - Check if it is time to enter the debugger 1690c57dfccSAnton Vorontsov * 1700c57dfccSAnton Vorontsov * "Serial ports are often noisy, especially when muxed over another port (we 1710c57dfccSAnton Vorontsov * often use serial over the headset connector). Noise on the async command 1720c57dfccSAnton Vorontsov * line just causes characters that are ignored, on a command line that blocked 1730c57dfccSAnton Vorontsov * execution noise would be catastrophic." -- Colin Cross 1740c57dfccSAnton Vorontsov * 1750c57dfccSAnton Vorontsov * So, this function implements KGDB/KDB knocking on the serial line: we won't 1760c57dfccSAnton Vorontsov * enter the debugger until we receive a known magic phrase (which is actually 1770c57dfccSAnton Vorontsov * "$3#33", known as "escape to KDB" command. There is also a relaxed variant 1780c57dfccSAnton Vorontsov * of knocking, i.e. just pressing the return key is enough to enter the 1790c57dfccSAnton Vorontsov * debugger. And if knocking is disabled, the function always returns 1. 1800c57dfccSAnton Vorontsov */ 1810c57dfccSAnton Vorontsov bool kgdb_nmi_poll_knock(void) 1820c57dfccSAnton Vorontsov { 1830c57dfccSAnton Vorontsov if (kgdb_nmi_knock < 0) 1840c57dfccSAnton Vorontsov return 1; 1850c57dfccSAnton Vorontsov 1860c57dfccSAnton Vorontsov while (1) { 1870c57dfccSAnton Vorontsov int ret; 1880c57dfccSAnton Vorontsov 1890c57dfccSAnton Vorontsov ret = kgdb_nmi_poll_one_knock(); 1900c57dfccSAnton Vorontsov if (ret == NO_POLL_CHAR) 1910c57dfccSAnton Vorontsov return 0; 1920c57dfccSAnton Vorontsov else if (ret == 1) 1930c57dfccSAnton Vorontsov break; 1940c57dfccSAnton Vorontsov } 1950c57dfccSAnton Vorontsov return 1; 1960c57dfccSAnton Vorontsov } 1970c57dfccSAnton Vorontsov 1980c57dfccSAnton Vorontsov /* 1990c57dfccSAnton Vorontsov * The tasklet is cheap, it does not cause wakeups when reschedules itself, 2000c57dfccSAnton Vorontsov * instead it waits for the next tick. 2010c57dfccSAnton Vorontsov */ 2020c57dfccSAnton Vorontsov static void kgdb_nmi_tty_receiver(unsigned long data) 2030c57dfccSAnton Vorontsov { 2040c57dfccSAnton Vorontsov struct kgdb_nmi_tty_priv *priv = (void *)data; 2050c57dfccSAnton Vorontsov char ch; 2060c57dfccSAnton Vorontsov 2070c57dfccSAnton Vorontsov tasklet_schedule(&priv->tlet); 2080c57dfccSAnton Vorontsov 2090c57dfccSAnton Vorontsov if (likely(!kgdb_nmi_tty_enabled || !kfifo_len(&priv->fifo))) 2100c57dfccSAnton Vorontsov return; 2110c57dfccSAnton Vorontsov 2120c57dfccSAnton Vorontsov while (kfifo_out(&priv->fifo, &ch, 1)) 21392a19f9cSJiri Slaby tty_insert_flip_char(&priv->port, ch, TTY_NORMAL); 2142e124b4aSJiri Slaby tty_flip_buffer_push(&priv->port); 2150c57dfccSAnton Vorontsov } 2160c57dfccSAnton Vorontsov 2170c57dfccSAnton Vorontsov static int kgdb_nmi_tty_activate(struct tty_port *port, struct tty_struct *tty) 2180c57dfccSAnton Vorontsov { 2190c57dfccSAnton Vorontsov struct kgdb_nmi_tty_priv *priv = tty->driver_data; 2200c57dfccSAnton Vorontsov 2210c57dfccSAnton Vorontsov kgdb_nmi_port = port; 2220c57dfccSAnton Vorontsov tasklet_schedule(&priv->tlet); 2230c57dfccSAnton Vorontsov return 0; 2240c57dfccSAnton Vorontsov } 2250c57dfccSAnton Vorontsov 2260c57dfccSAnton Vorontsov static void kgdb_nmi_tty_shutdown(struct tty_port *port) 2270c57dfccSAnton Vorontsov { 2280c57dfccSAnton Vorontsov struct kgdb_nmi_tty_priv *priv = port->tty->driver_data; 2290c57dfccSAnton Vorontsov 2300c57dfccSAnton Vorontsov tasklet_kill(&priv->tlet); 2310c57dfccSAnton Vorontsov kgdb_nmi_port = NULL; 2320c57dfccSAnton Vorontsov } 2330c57dfccSAnton Vorontsov 2340c57dfccSAnton Vorontsov static const struct tty_port_operations kgdb_nmi_tty_port_ops = { 2350c57dfccSAnton Vorontsov .activate = kgdb_nmi_tty_activate, 2360c57dfccSAnton Vorontsov .shutdown = kgdb_nmi_tty_shutdown, 2370c57dfccSAnton Vorontsov }; 2380c57dfccSAnton Vorontsov 2390c57dfccSAnton Vorontsov static int kgdb_nmi_tty_install(struct tty_driver *drv, struct tty_struct *tty) 2400c57dfccSAnton Vorontsov { 2410c57dfccSAnton Vorontsov struct kgdb_nmi_tty_priv *priv; 2420c57dfccSAnton Vorontsov int ret; 2430c57dfccSAnton Vorontsov 2440c57dfccSAnton Vorontsov priv = kzalloc(sizeof(*priv), GFP_KERNEL); 2450c57dfccSAnton Vorontsov if (!priv) 2460c57dfccSAnton Vorontsov return -ENOMEM; 2470c57dfccSAnton Vorontsov 2480c57dfccSAnton Vorontsov INIT_KFIFO(priv->fifo); 2490c57dfccSAnton Vorontsov tasklet_init(&priv->tlet, kgdb_nmi_tty_receiver, (unsigned long)priv); 2500c57dfccSAnton Vorontsov tty_port_init(&priv->port); 2510c57dfccSAnton Vorontsov priv->port.ops = &kgdb_nmi_tty_port_ops; 2520c57dfccSAnton Vorontsov tty->driver_data = priv; 2530c57dfccSAnton Vorontsov 2540c57dfccSAnton Vorontsov ret = tty_port_install(&priv->port, drv, tty); 2550c57dfccSAnton Vorontsov if (ret) { 2560c57dfccSAnton Vorontsov pr_err("%s: can't install tty port: %d\n", __func__, ret); 2570c57dfccSAnton Vorontsov goto err; 2580c57dfccSAnton Vorontsov } 2590c57dfccSAnton Vorontsov return 0; 2600c57dfccSAnton Vorontsov err: 261191c5f10SJiri Slaby tty_port_destroy(&priv->port); 2620c57dfccSAnton Vorontsov kfree(priv); 2630c57dfccSAnton Vorontsov return ret; 2640c57dfccSAnton Vorontsov } 2650c57dfccSAnton Vorontsov 2660c57dfccSAnton Vorontsov static void kgdb_nmi_tty_cleanup(struct tty_struct *tty) 2670c57dfccSAnton Vorontsov { 2680c57dfccSAnton Vorontsov struct kgdb_nmi_tty_priv *priv = tty->driver_data; 2690c57dfccSAnton Vorontsov 2700c57dfccSAnton Vorontsov tty->driver_data = NULL; 271191c5f10SJiri Slaby tty_port_destroy(&priv->port); 2720c57dfccSAnton Vorontsov kfree(priv); 2730c57dfccSAnton Vorontsov } 2740c57dfccSAnton Vorontsov 2750c57dfccSAnton Vorontsov static int kgdb_nmi_tty_open(struct tty_struct *tty, struct file *file) 2760c57dfccSAnton Vorontsov { 2770c57dfccSAnton Vorontsov struct kgdb_nmi_tty_priv *priv = tty->driver_data; 2780c57dfccSAnton Vorontsov 2790c57dfccSAnton Vorontsov return tty_port_open(&priv->port, tty, file); 2800c57dfccSAnton Vorontsov } 2810c57dfccSAnton Vorontsov 2820c57dfccSAnton Vorontsov static void kgdb_nmi_tty_close(struct tty_struct *tty, struct file *file) 2830c57dfccSAnton Vorontsov { 2840c57dfccSAnton Vorontsov struct kgdb_nmi_tty_priv *priv = tty->driver_data; 2850c57dfccSAnton Vorontsov 2860c57dfccSAnton Vorontsov tty_port_close(&priv->port, tty, file); 2870c57dfccSAnton Vorontsov } 2880c57dfccSAnton Vorontsov 2890c57dfccSAnton Vorontsov static void kgdb_nmi_tty_hangup(struct tty_struct *tty) 2900c57dfccSAnton Vorontsov { 2910c57dfccSAnton Vorontsov struct kgdb_nmi_tty_priv *priv = tty->driver_data; 2920c57dfccSAnton Vorontsov 2930c57dfccSAnton Vorontsov tty_port_hangup(&priv->port); 2940c57dfccSAnton Vorontsov } 2950c57dfccSAnton Vorontsov 2960c57dfccSAnton Vorontsov static int kgdb_nmi_tty_write_room(struct tty_struct *tty) 2970c57dfccSAnton Vorontsov { 2980c57dfccSAnton Vorontsov /* Actually, we can handle any amount as we use polled writes. */ 2990c57dfccSAnton Vorontsov return 2048; 3000c57dfccSAnton Vorontsov } 3010c57dfccSAnton Vorontsov 3020c57dfccSAnton Vorontsov static int kgdb_nmi_tty_write(struct tty_struct *tty, const unchar *buf, int c) 3030c57dfccSAnton Vorontsov { 3040c57dfccSAnton Vorontsov int i; 3050c57dfccSAnton Vorontsov 3060c57dfccSAnton Vorontsov for (i = 0; i < c; i++) 3070c57dfccSAnton Vorontsov dbg_io_ops->write_char(buf[i]); 3080c57dfccSAnton Vorontsov return c; 3090c57dfccSAnton Vorontsov } 3100c57dfccSAnton Vorontsov 3110c57dfccSAnton Vorontsov static const struct tty_operations kgdb_nmi_tty_ops = { 3120c57dfccSAnton Vorontsov .open = kgdb_nmi_tty_open, 3130c57dfccSAnton Vorontsov .close = kgdb_nmi_tty_close, 3140c57dfccSAnton Vorontsov .install = kgdb_nmi_tty_install, 3150c57dfccSAnton Vorontsov .cleanup = kgdb_nmi_tty_cleanup, 3160c57dfccSAnton Vorontsov .hangup = kgdb_nmi_tty_hangup, 3170c57dfccSAnton Vorontsov .write_room = kgdb_nmi_tty_write_room, 3180c57dfccSAnton Vorontsov .write = kgdb_nmi_tty_write, 3190c57dfccSAnton Vorontsov }; 3200c57dfccSAnton Vorontsov 3210c57dfccSAnton Vorontsov static int kgdb_nmi_enable_console(int argc, const char *argv[]) 3220c57dfccSAnton Vorontsov { 3230c57dfccSAnton Vorontsov kgdb_nmi_tty_enabled = !(argc == 1 && !strcmp(argv[1], "off")); 3240c57dfccSAnton Vorontsov return 0; 3250c57dfccSAnton Vorontsov } 3260c57dfccSAnton Vorontsov 3270c57dfccSAnton Vorontsov int kgdb_register_nmi_console(void) 3280c57dfccSAnton Vorontsov { 3290c57dfccSAnton Vorontsov int ret; 3300c57dfccSAnton Vorontsov 3310c57dfccSAnton Vorontsov if (!arch_kgdb_ops.enable_nmi) 3320c57dfccSAnton Vorontsov return 0; 3330c57dfccSAnton Vorontsov 3340c57dfccSAnton Vorontsov kgdb_nmi_tty_driver = alloc_tty_driver(1); 3350c57dfccSAnton Vorontsov if (!kgdb_nmi_tty_driver) { 3360c57dfccSAnton Vorontsov pr_err("%s: cannot allocate tty\n", __func__); 3370c57dfccSAnton Vorontsov return -ENOMEM; 3380c57dfccSAnton Vorontsov } 3390c57dfccSAnton Vorontsov kgdb_nmi_tty_driver->driver_name = "ttyNMI"; 3400c57dfccSAnton Vorontsov kgdb_nmi_tty_driver->name = "ttyNMI"; 3410c57dfccSAnton Vorontsov kgdb_nmi_tty_driver->num = 1; 3420c57dfccSAnton Vorontsov kgdb_nmi_tty_driver->type = TTY_DRIVER_TYPE_SERIAL; 3430c57dfccSAnton Vorontsov kgdb_nmi_tty_driver->subtype = SERIAL_TYPE_NORMAL; 3440c57dfccSAnton Vorontsov kgdb_nmi_tty_driver->flags = TTY_DRIVER_REAL_RAW; 3450c57dfccSAnton Vorontsov kgdb_nmi_tty_driver->init_termios = tty_std_termios; 3460c57dfccSAnton Vorontsov tty_termios_encode_baud_rate(&kgdb_nmi_tty_driver->init_termios, 3470c57dfccSAnton Vorontsov KGDB_NMI_BAUD, KGDB_NMI_BAUD); 3480c57dfccSAnton Vorontsov tty_set_operations(kgdb_nmi_tty_driver, &kgdb_nmi_tty_ops); 3490c57dfccSAnton Vorontsov 3500c57dfccSAnton Vorontsov ret = tty_register_driver(kgdb_nmi_tty_driver); 3510c57dfccSAnton Vorontsov if (ret) { 3520c57dfccSAnton Vorontsov pr_err("%s: can't register tty driver: %d\n", __func__, ret); 3530c57dfccSAnton Vorontsov goto err_drv_reg; 3540c57dfccSAnton Vorontsov } 3550c57dfccSAnton Vorontsov 3560c57dfccSAnton Vorontsov ret = kdb_register("nmi_console", kgdb_nmi_enable_console, "[off]", 3570c57dfccSAnton Vorontsov "switch to Linux NMI console", 0); 3580c57dfccSAnton Vorontsov if (ret) { 3590c57dfccSAnton Vorontsov pr_err("%s: can't register kdb command: %d\n", __func__, ret); 3600c57dfccSAnton Vorontsov goto err_kdb_reg; 3610c57dfccSAnton Vorontsov } 3620c57dfccSAnton Vorontsov 3630c57dfccSAnton Vorontsov register_console(&kgdb_nmi_console); 3640c57dfccSAnton Vorontsov arch_kgdb_ops.enable_nmi(1); 3650c57dfccSAnton Vorontsov 3660c57dfccSAnton Vorontsov return 0; 3670c57dfccSAnton Vorontsov err_kdb_reg: 3680c57dfccSAnton Vorontsov tty_unregister_driver(kgdb_nmi_tty_driver); 3690c57dfccSAnton Vorontsov err_drv_reg: 3700c57dfccSAnton Vorontsov put_tty_driver(kgdb_nmi_tty_driver); 3710c57dfccSAnton Vorontsov return ret; 3720c57dfccSAnton Vorontsov } 3730c57dfccSAnton Vorontsov EXPORT_SYMBOL_GPL(kgdb_register_nmi_console); 3740c57dfccSAnton Vorontsov 3750c57dfccSAnton Vorontsov int kgdb_unregister_nmi_console(void) 3760c57dfccSAnton Vorontsov { 3770c57dfccSAnton Vorontsov int ret; 3780c57dfccSAnton Vorontsov 3790c57dfccSAnton Vorontsov if (!arch_kgdb_ops.enable_nmi) 3800c57dfccSAnton Vorontsov return 0; 3810c57dfccSAnton Vorontsov arch_kgdb_ops.enable_nmi(0); 3820c57dfccSAnton Vorontsov 3830c57dfccSAnton Vorontsov kdb_unregister("nmi_console"); 3840c57dfccSAnton Vorontsov 3850c57dfccSAnton Vorontsov ret = unregister_console(&kgdb_nmi_console); 3860c57dfccSAnton Vorontsov if (ret) 3870c57dfccSAnton Vorontsov return ret; 3880c57dfccSAnton Vorontsov 3890c57dfccSAnton Vorontsov ret = tty_unregister_driver(kgdb_nmi_tty_driver); 3900c57dfccSAnton Vorontsov if (ret) 3910c57dfccSAnton Vorontsov return ret; 3920c57dfccSAnton Vorontsov put_tty_driver(kgdb_nmi_tty_driver); 3930c57dfccSAnton Vorontsov 3940c57dfccSAnton Vorontsov return 0; 3950c57dfccSAnton Vorontsov } 3960c57dfccSAnton Vorontsov EXPORT_SYMBOL_GPL(kgdb_unregister_nmi_console); 397