diff options
Diffstat (limited to 'arch/sh/kernel/kgdb.c')
-rw-r--r-- | arch/sh/kernel/kgdb.c | 46 |
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 @@ | |||
1 | /* | 1 | /* |
2 | * SuperH KGDB support | 2 | * SuperH KGDB support |
3 | * | 3 | * |
4 | * Copyright (C) 2008 Paul Mundt | 4 | * Copyright (C) 2008 - 2009 Paul Mundt |
5 | * | 5 | * |
6 | * Single stepping taken from the old stub by Henry Bell and Jeremy Siegel. | 6 | * Single stepping taken from the old stub by Henry Bell and Jeremy Siegel. |
7 | * | 7 | * |
@@ -251,24 +251,60 @@ BUILD_TRAP_HANDLER(singlestep) | |||
251 | local_irq_restore(flags); | 251 | local_irq_restore(flags); |
252 | } | 252 | } |
253 | 253 | ||
254 | static int __kgdb_notify(struct die_args *args, unsigned long cmd) | ||
255 | { | ||
256 | int ret; | ||
257 | |||
258 | switch (cmd) { | ||
259 | case DIE_BREAKPOINT: | ||
260 | /* | ||
261 | * This means a user thread is single stepping | ||
262 | * a system call which should be ignored | ||
263 | */ | ||
264 | if (test_thread_flag(TIF_SINGLESTEP)) | ||
265 | return NOTIFY_DONE; | ||
266 | |||
267 | ret = kgdb_handle_exception(args->trapnr & 0xff, args->signr, | ||
268 | args->err, args->regs); | ||
269 | if (ret) | ||
270 | return NOTIFY_DONE; | ||
271 | |||
272 | break; | ||
273 | } | ||
254 | 274 | ||
255 | BUILD_TRAP_HANDLER(breakpoint) | 275 | return NOTIFY_STOP; |
276 | } | ||
277 | |||
278 | static int | ||
279 | kgdb_notify(struct notifier_block *self, unsigned long cmd, void *ptr) | ||
256 | { | 280 | { |
257 | unsigned long flags; | 281 | unsigned long flags; |
258 | TRAP_HANDLER_DECL; | 282 | int ret; |
259 | 283 | ||
260 | local_irq_save(flags); | 284 | local_irq_save(flags); |
261 | kgdb_handle_exception(vec >> 2, SIGTRAP, 0, regs); | 285 | ret = __kgdb_notify(ptr, cmd); |
262 | local_irq_restore(flags); | 286 | local_irq_restore(flags); |
287 | |||
288 | return ret; | ||
263 | } | 289 | } |
264 | 290 | ||
291 | static struct notifier_block kgdb_notifier = { | ||
292 | .notifier_call = kgdb_notify, | ||
293 | |||
294 | /* | ||
295 | * Lowest-prio notifier priority, we want to be notified last: | ||
296 | */ | ||
297 | .priority = -INT_MAX, | ||
298 | }; | ||
299 | |||
265 | int kgdb_arch_init(void) | 300 | int kgdb_arch_init(void) |
266 | { | 301 | { |
267 | return 0; | 302 | return register_die_notifier(&kgdb_notifier); |
268 | } | 303 | } |
269 | 304 | ||
270 | void kgdb_arch_exit(void) | 305 | void kgdb_arch_exit(void) |
271 | { | 306 | { |
307 | unregister_die_notifier(&kgdb_notifier); | ||
272 | } | 308 | } |
273 | 309 | ||
274 | struct kgdb_arch arch_kgdb_ops = { | 310 | struct kgdb_arch arch_kgdb_ops = { |