From: Colin Cross Date: Thu, 15 Mar 2012 02:23:29 +0000 (-0700) Subject: ARM: fiq_debugger: add support for kgdb X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=35d99e56465d412e1bf707c31363650506bd15fa;p=GitHub%2Fexynos8895%2Fandroid_kernel_samsung_universal8895.git ARM: fiq_debugger: add support for kgdb Adds polling tty ops to the fiq debugger console tty, which allows kgdb to run against an fiq debugger console. Add a check in do_sysrq to prevent enabling kgdb from the fiq debugger unless a flag (writable only by root) has been set. This should make it safe to enable KGDB on a production device. Also add a shortcut to enable the console and kgdb together, to allow kgdb to be enabled when the shell on the console is not responding. Change-Id: Ifc65239ca96c9887431a6a36b9b44a539002f544 Signed-off-by: Colin Cross --- diff --git a/arch/arm/common/fiq_debugger.c b/arch/arm/common/fiq_debugger.c index 909ef56596e8..1f64d7dc83b4 100644 --- a/arch/arm/common/fiq_debugger.c +++ b/arch/arm/common/fiq_debugger.c @@ -106,9 +106,12 @@ static bool initial_debug_enable; static bool initial_console_enable; #endif +static bool fiq_kgdb_enable; + module_param_named(no_sleep, initial_no_sleep, bool, 0644); module_param_named(debug_enable, initial_debug_enable, bool, 0644); module_param_named(console_enable, initial_console_enable, bool, 0644); +module_param_named(kgdb_enable, fiq_kgdb_enable, bool, 0644); #ifdef CONFIG_FIQ_DEBUGGER_WAKEUP_IRQ_ALWAYS_ON static inline void enable_wakeup_irq(struct fiq_debugger_state *state) {} @@ -526,11 +529,29 @@ static void end_syslog_dump(struct fiq_debugger_state *state) static void do_sysrq(struct fiq_debugger_state *state, char rq) { + if ((rq == 'g' || rq == 'G') && !fiq_kgdb_enable) { + debug_printf(state, "sysrq-g blocked\n"); + return; + } begin_syslog_dump(state); handle_sysrq(rq); end_syslog_dump(state); } +#ifdef CONFIG_KGDB +static void do_kgdb(struct fiq_debugger_state *state) +{ + if (!fiq_kgdb_enable) { + debug_printf(state, "kgdb through fiq debugger not enabled\n"); + return; + } + + debug_printf(state, "enabling console and triggering kgdb\n"); + state->console_enable = true; + handle_sysrq('g'); +} +#endif + /* This function CANNOT be called in FIQ context */ static void debug_irq_exec(struct fiq_debugger_state *state, char *cmd) { @@ -540,6 +561,10 @@ static void debug_irq_exec(struct fiq_debugger_state *state, char *cmd) do_sysrq(state, 'h'); if (!strncmp(cmd, "sysrq ", 6)) do_sysrq(state, cmd[6]); +#ifdef CONFIG_KGDB + if (!strcmp(cmd, "kgdb")) + do_kgdb(state); +#endif } static void debug_help(struct fiq_debugger_state *state) @@ -561,6 +586,9 @@ static void debug_help(struct fiq_debugger_state *state) debug_printf(state, " ps Process list\n" " sysrq sysrq options\n" " sysrq Execute sysrq with \n"); +#ifdef CONFIG_KGDB + debug_printf(state, " kgdb Enter kernel debugger\n"); +#endif } static void take_affinity(void *info) @@ -724,7 +752,8 @@ static void debug_handle_irq_context(struct fiq_debugger_state *state) #endif if (state->debug_busy) { debug_irq_exec(state, state->debug_cmd); - debug_prompt(state); + if (!state->console_enable) + debug_prompt(state); state->debug_busy = 0; } } @@ -957,11 +986,53 @@ int fiq_tty_write_room(struct tty_struct *tty) return 1024; } +#ifdef CONFIG_CONSOLE_POLL +static int fiq_tty_poll_init(struct tty_driver *driver, int line, char *options) +{ + return 0; +} + +static int fiq_tty_poll_get_char(struct tty_driver *driver, int line) +{ + struct fiq_debugger_state *state = driver->ttys[line]->driver_data; + int c = NO_POLL_CHAR; + + debug_uart_enable(state); + if (debug_have_fiq(state)) { + int count = fiq_debugger_ringbuf_level(state->tty_rbuf); + if (count > 0) { + c = fiq_debugger_ringbuf_peek(state->tty_rbuf, 0); + fiq_debugger_ringbuf_consume(state->tty_rbuf, 1); + } + } else { + c = debug_getc(state); + if (c == FIQ_DEBUGGER_NO_CHAR) + c = NO_POLL_CHAR; + } + debug_uart_disable(state); + + return c; +} + +static void fiq_tty_poll_put_char(struct tty_driver *driver, int line, char ch) +{ + struct fiq_debugger_state *state = driver->ttys[line]->driver_data; + debug_uart_enable(state); + debug_putc(state, ch); + debug_uart_disable(state); +} +#endif + static const struct tty_operations fiq_tty_driver_ops = { .write = fiq_tty_write, .write_room = fiq_tty_write_room, .open = fiq_tty_open, .close = fiq_tty_close, +#ifdef CONFIG_CONSOLE_POLL + .poll_init = fiq_tty_poll_init, + .poll_get_char = fiq_tty_poll_get_char, + .poll_put_char = fiq_tty_poll_put_char, +#endif }; static int fiq_debugger_tty_init(struct fiq_debugger_state *state)