summaryrefslogtreecommitdiff
path: root/arch/arm/common
diff options
context:
space:
mode:
authorDima Zavin <dima@android.com>2011-11-09 16:10:57 -0800
committerDan Willemsen <dwillemsen@nvidia.com>2011-11-30 21:39:18 -0800
commit4c38a69720f669d7d7ced5f4e86298caac885a22 (patch)
tree3637003d962e20ce7fbca4c220df1198fdf6a959 /arch/arm/common
parentc19301dfaffa6aed346a467006eae603f02c0e3b (diff)
ARM: common: fiq_debugger: add irq context debug functions
This code is moved here from the drivers/misc/kernel_debugger. Change-Id: Iccf21c4313a8516a917125ca93f64baa5f354228 Signed-off-by: Dima Zavin <dima@android.com>
Diffstat (limited to 'arch/arm/common')
-rw-r--r--arch/arm/common/Kconfig3
-rw-r--r--arch/arm/common/fiq_debugger.c80
2 files changed, 62 insertions, 21 deletions
diff --git a/arch/arm/common/Kconfig b/arch/arm/common/Kconfig
index cf82a884a5c5..638256600ffe 100644
--- a/arch/arm/common/Kconfig
+++ b/arch/arm/common/Kconfig
@@ -48,12 +48,11 @@ config FIQ_DEBUGGER
bool "FIQ Mode Serial Debugger"
select FIQ
select FIQ_GLUE
- select KERNEL_DEBUGGER_CORE
default n
help
The FIQ serial debugger can accept commands even when the
kernel is unresponsive due to being stuck with interrupts
- disabled. Depends on the kernel debugger core in drivers/misc.
+ disabled.
config FIQ_DEBUGGER_NO_SLEEP
diff --git a/arch/arm/common/fiq_debugger.c b/arch/arm/common/fiq_debugger.c
index b9b53c9994ab..68e7265cc68d 100644
--- a/arch/arm/common/fiq_debugger.c
+++ b/arch/arm/common/fiq_debugger.c
@@ -22,7 +22,6 @@
#include <linux/interrupt.h>
#include <linux/clk.h>
#include <linux/platform_device.h>
-#include <linux/kernel_debugger.h>
#include <linux/kernel_stat.h>
#include <linux/irq.h>
#include <linux/delay.h>
@@ -474,7 +473,59 @@ void dump_stacktrace(struct fiq_debugger_state *state,
tail = user_backtrace(state, tail);
}
-static bool debug_help(struct fiq_debugger_state *state)
+static void do_ps(struct fiq_debugger_state *state)
+{
+ struct task_struct *g;
+ struct task_struct *p;
+ unsigned task_state;
+ static const char stat_nam[] = "RSDTtZX";
+
+ debug_printf(state, "pid ppid prio task pc\n");
+ read_lock(&tasklist_lock);
+ do_each_thread(g, p) {
+ task_state = p->state ? __ffs(p->state) + 1 : 0;
+ debug_printf(state,
+ "%5d %5d %4d ", p->pid, p->parent->pid, p->prio);
+ debug_printf(state, "%-13.13s %c", p->comm,
+ task_state >= sizeof(stat_nam) ? '?' : stat_nam[task_state]);
+ if (task_state == TASK_RUNNING)
+ debug_printf(state, " running\n");
+ else
+ debug_printf(state, " %08lx\n", thread_saved_pc(p));
+ } while_each_thread(g, p);
+ read_unlock(&tasklist_lock);
+}
+
+extern int do_syslog(int type, char __user *bug, int count);
+static void do_sysrq(struct fiq_debugger_state *state, char rq)
+{
+ char buf[128];
+ int ret;
+ int idx = 0;
+ do_syslog(5 /* clear */, NULL, 0);
+ handle_sysrq(rq);
+ while (1) {
+ ret = log_buf_copy(buf, idx, sizeof(buf) - 1);
+ if (ret <= 0)
+ break;
+ buf[ret] = 0;
+ debug_printf(state, "%s", buf);
+ idx += ret;
+ }
+}
+
+/* This function CANNOT be called in FIQ context */
+static void debug_irq_exec(struct fiq_debugger_state *state, char *cmd)
+{
+ if (!strcmp(cmd, "ps"))
+ do_ps(state);
+ if (!strcmp(cmd, "sysrq"))
+ do_sysrq(state, 'h');
+ if (!strncmp(cmd, "sysrq ", 6))
+ do_sysrq(state, cmd[6]);
+}
+
+static void debug_help(struct fiq_debugger_state *state)
{
debug_printf(state, "FIQ Debugger commands:\n"
" pc PC status\n"
@@ -490,13 +541,9 @@ static bool debug_help(struct fiq_debugger_state *state)
" console Switch terminal to console\n"
" cpu Current CPU\n"
" cpu <number> Switch to CPU<number>\n");
- if (!state->debug_busy) {
- strcpy(state->debug_cmd, "help");
- state->debug_busy = 1;
- return true;
- }
-
- return false;
+ debug_printf(state, " ps Process list\n"
+ " sysrq sysrq options\n"
+ " sysrq <param> Execute sysrq with <param>\n");
}
static void take_affinity(void *info)
@@ -517,13 +564,13 @@ static void switch_cpu(struct fiq_debugger_state *state, int cpu)
state->current_cpu = cpu;
}
-static bool debug_exec(struct fiq_debugger_state *state,
+static bool debug_fiq_exec(struct fiq_debugger_state *state,
const char *cmd, unsigned *regs, void *svc_sp)
{
bool signal_helper = false;
if (!strcmp(cmd, "help") || !strcmp(cmd, "?")) {
- signal_helper |= debug_help(state);
+ debug_help(state);
} else if (!strcmp(cmd, "pc")) {
debug_printf(state, " pc %08x cpsr %08x mode %s\n",
regs[15], regs[16], mode_name(regs[16]));
@@ -650,13 +697,8 @@ static void debug_handle_irq_context(struct fiq_debugger_state *state)
}
#endif
if (state->debug_busy) {
- struct kdbg_ctxt ctxt;
-
- ctxt.printf = debug_printf_nfiq;
- ctxt.cookie = state;
- kernel_debugger(&ctxt, state->debug_cmd);
+ debug_irq_exec(state, state->debug_cmd);
debug_prompt(state);
-
state->debug_busy = 0;
}
}
@@ -732,8 +774,8 @@ static bool debug_handle_uart_interrupt(struct fiq_debugger_state *state,
state->debug_buf[state->debug_count] = 0;
state->debug_count = 0;
signal_helper |=
- debug_exec(state, state->debug_buf,
- regs, svc_sp);
+ debug_fiq_exec(state, state->debug_buf,
+ regs, svc_sp);
} else {
debug_prompt(state);
}