From 22648735405f73299b717bb5933767e9a9c335ca Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Tue, 22 Dec 2009 12:44:14 +0900 Subject: [PATCH] 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 --- arch/sh/kernel/debugtraps.S | 1 - arch/sh/kernel/kgdb.c | 46 +++++++++++++++++++++++++++++++++---- 2 files changed, 41 insertions(+), 6 deletions(-) diff --git a/arch/sh/kernel/debugtraps.S b/arch/sh/kernel/debugtraps.S index 591741383ee..7a1b46fec0f 100644 --- a/arch/sh/kernel/debugtraps.S +++ b/arch/sh/kernel/debugtraps.S @@ -13,7 +13,6 @@ #include #if !defined(CONFIG_KGDB) -#define breakpoint_trap_handler debug_trap_handler #define singlestep_trap_handler debug_trap_handler #endif diff --git a/arch/sh/kernel/kgdb.c b/arch/sh/kernel/kgdb.c index 3e532d0d4a5..70c69659b84 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 = { -- 2.46.0