aboutsummaryrefslogtreecommitdiff
path: root/arch/sh/kernel/kgdb.c
diff options
context:
space:
mode:
authorPaul Mundt <lethal@linux-sh.org>2009-12-22 12:44:14 +0900
committerPaul Mundt <lethal@linux-sh.org>2009-12-22 12:44:14 +0900
commit22648735405f73299b717bb5933767e9a9c335ca (patch)
tree84965df944bb9bf22367b243c4c2d631a607d9df /arch/sh/kernel/kgdb.c
parentb74ab703b1326aafadb5604ff6200da62c61df49 (diff)
sh: kgdb: Rework breakpoint handling on top of notifier chain.
This kills off kgdb's breakpoint handler and ties in to the notifier chain instead. Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch/sh/kernel/kgdb.c')
-rw-r--r--arch/sh/kernel/kgdb.c46
1 files changed, 41 insertions, 5 deletions
diff --git a/arch/sh/kernel/kgdb.c b/arch/sh/kernel/kgdb.c
index 3e532d0d4a5c..70c69659b846 100644
--- a/arch/sh/kernel/kgdb.c
+++ b/arch/sh/kernel/kgdb.c
@@ -1,7 +1,7 @@
/*
* SuperH KGDB support
*
- * Copyright (C) 2008 Paul Mundt
+ * Copyright (C) 2008 - 2009 Paul Mundt
*
* Single stepping taken from the old stub by Henry Bell and Jeremy Siegel.
*
@@ -251,24 +251,60 @@ BUILD_TRAP_HANDLER(singlestep)
local_irq_restore(flags);
}
+static int __kgdb_notify(struct die_args *args, unsigned long cmd)
+{
+ int ret;
+
+ switch (cmd) {
+ case DIE_BREAKPOINT:
+ /*
+ * This means a user thread is single stepping
+ * a system call which should be ignored
+ */
+ if (test_thread_flag(TIF_SINGLESTEP))
+ return NOTIFY_DONE;
+
+ ret = kgdb_handle_exception(args->trapnr & 0xff, args->signr,
+ args->err, args->regs);
+ if (ret)
+ return NOTIFY_DONE;
+
+ break;
+ }
-BUILD_TRAP_HANDLER(breakpoint)
+ return NOTIFY_STOP;
+}
+
+static int
+kgdb_notify(struct notifier_block *self, unsigned long cmd, void *ptr)
{
unsigned long flags;
- TRAP_HANDLER_DECL;
+ int ret;
local_irq_save(flags);
- kgdb_handle_exception(vec >> 2, SIGTRAP, 0, regs);
+ ret = __kgdb_notify(ptr, cmd);
local_irq_restore(flags);
+
+ return ret;
}
+static struct notifier_block kgdb_notifier = {
+ .notifier_call = kgdb_notify,
+
+ /*
+ * Lowest-prio notifier priority, we want to be notified last:
+ */
+ .priority = -INT_MAX,
+};
+
int kgdb_arch_init(void)
{
- return 0;
+ return register_die_notifier(&kgdb_notifier);
}
void kgdb_arch_exit(void)
{
+ unregister_die_notifier(&kgdb_notifier);
}
struct kgdb_arch arch_kgdb_ops = {