Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 992dbb2a authored by Colin Cross's avatar Colin Cross Committed by Amit Pundir
Browse files

ANDROID: 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: default avatarColin Cross <ccross@android.com>
parent 5d12c56f
Loading
Loading
Loading
Loading
+72 −1
Original line number Original line Diff line number Diff line
@@ -107,9 +107,12 @@ static bool initial_debug_enable;
static bool initial_console_enable;
static bool initial_console_enable;
#endif
#endif


static bool fiq_kgdb_enable;

module_param_named(no_sleep, initial_no_sleep, bool, 0644);
module_param_named(no_sleep, initial_no_sleep, bool, 0644);
module_param_named(debug_enable, initial_debug_enable, 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(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
#ifdef CONFIG_FIQ_DEBUGGER_WAKEUP_IRQ_ALWAYS_ON
static inline void enable_wakeup_irq(struct fiq_debugger_state *state) {}
static inline void enable_wakeup_irq(struct fiq_debugger_state *state) {}
@@ -507,11 +510,29 @@ static void end_syslog_dump(struct fiq_debugger_state *state)


static void do_sysrq(struct fiq_debugger_state *state, char rq)
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);
	begin_syslog_dump(state);
	handle_sysrq(rq);
	handle_sysrq(rq);
	end_syslog_dump(state);
	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 */
/* This function CANNOT be called in FIQ context */
static void debug_irq_exec(struct fiq_debugger_state *state, char *cmd)
static void debug_irq_exec(struct fiq_debugger_state *state, char *cmd)
{
{
@@ -521,6 +542,10 @@ static void debug_irq_exec(struct fiq_debugger_state *state, char *cmd)
		do_sysrq(state, 'h');
		do_sysrq(state, 'h');
	if (!strncmp(cmd, "sysrq ", 6))
	if (!strncmp(cmd, "sysrq ", 6))
		do_sysrq(state, cmd[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)
static void debug_help(struct fiq_debugger_state *state)
@@ -542,6 +567,9 @@ static void debug_help(struct fiq_debugger_state *state)
	debug_printf(state,	" ps            Process list\n"
	debug_printf(state,	" ps            Process list\n"
				" sysrq         sysrq options\n"
				" sysrq         sysrq options\n"
				" sysrq <param> Execute sysrq with <param>\n");
				" sysrq <param> Execute sysrq with <param>\n");
#ifdef CONFIG_KGDB
	debug_printf(state,	" kgdb          Enter kernel debugger\n");
#endif
}
}


static void take_affinity(void *info)
static void take_affinity(void *info)
@@ -705,6 +733,7 @@ static void debug_handle_irq_context(struct fiq_debugger_state *state)
#endif
#endif
	if (state->debug_busy) {
	if (state->debug_busy) {
		debug_irq_exec(state, state->debug_cmd);
		debug_irq_exec(state, state->debug_cmd);
		if (!state->console_enable)
			debug_prompt(state);
			debug_prompt(state);
		state->debug_busy = 0;
		state->debug_busy = 0;
	}
	}
@@ -938,11 +967,53 @@ int fiq_tty_write_room(struct tty_struct *tty)
	return 1024;
	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 = {
static const struct tty_operations fiq_tty_driver_ops = {
	.write = fiq_tty_write,
	.write = fiq_tty_write,
	.write_room = fiq_tty_write_room,
	.write_room = fiq_tty_write_room,
	.open = fiq_tty_open,
	.open = fiq_tty_open,
	.close = fiq_tty_close,
	.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)
static int fiq_debugger_tty_init(struct fiq_debugger_state *state)