diff options
Diffstat (limited to 'arch/s390/kernel/traps.c')
-rw-r--r-- | arch/s390/kernel/traps.c | 31 |
1 files changed, 28 insertions, 3 deletions
diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c index bde1d1d59858..c4982c963424 100644 --- a/arch/s390/kernel/traps.c +++ b/arch/s390/kernel/traps.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/module.h> | 29 | #include <linux/module.h> |
30 | #include <linux/kallsyms.h> | 30 | #include <linux/kallsyms.h> |
31 | #include <linux/reboot.h> | 31 | #include <linux/reboot.h> |
32 | #include <linux/kprobes.h> | ||
32 | 33 | ||
33 | #include <asm/system.h> | 34 | #include <asm/system.h> |
34 | #include <asm/uaccess.h> | 35 | #include <asm/uaccess.h> |
@@ -39,6 +40,7 @@ | |||
39 | #include <asm/s390_ext.h> | 40 | #include <asm/s390_ext.h> |
40 | #include <asm/lowcore.h> | 41 | #include <asm/lowcore.h> |
41 | #include <asm/debug.h> | 42 | #include <asm/debug.h> |
43 | #include <asm/kdebug.h> | ||
42 | 44 | ||
43 | /* Called from entry.S only */ | 45 | /* Called from entry.S only */ |
44 | extern void handle_per_exception(struct pt_regs *regs); | 46 | extern void handle_per_exception(struct pt_regs *regs); |
@@ -74,6 +76,20 @@ static int kstack_depth_to_print = 12; | |||
74 | static int kstack_depth_to_print = 20; | 76 | static int kstack_depth_to_print = 20; |
75 | #endif /* CONFIG_64BIT */ | 77 | #endif /* CONFIG_64BIT */ |
76 | 78 | ||
79 | ATOMIC_NOTIFIER_HEAD(s390die_chain); | ||
80 | |||
81 | int register_die_notifier(struct notifier_block *nb) | ||
82 | { | ||
83 | return atomic_notifier_chain_register(&s390die_chain, nb); | ||
84 | } | ||
85 | EXPORT_SYMBOL(register_die_notifier); | ||
86 | |||
87 | int unregister_die_notifier(struct notifier_block *nb) | ||
88 | { | ||
89 | return atomic_notifier_chain_unregister(&s390die_chain, nb); | ||
90 | } | ||
91 | EXPORT_SYMBOL(unregister_die_notifier); | ||
92 | |||
77 | /* | 93 | /* |
78 | * For show_trace we have tree different stack to consider: | 94 | * For show_trace we have tree different stack to consider: |
79 | * - the panic stack which is used if the kernel stack has overflown | 95 | * - the panic stack which is used if the kernel stack has overflown |
@@ -305,8 +321,9 @@ report_user_fault(long interruption_code, struct pt_regs *regs) | |||
305 | #endif | 321 | #endif |
306 | } | 322 | } |
307 | 323 | ||
308 | static void inline do_trap(long interruption_code, int signr, char *str, | 324 | static void __kprobes inline do_trap(long interruption_code, int signr, |
309 | struct pt_regs *regs, siginfo_t *info) | 325 | char *str, struct pt_regs *regs, |
326 | siginfo_t *info) | ||
310 | { | 327 | { |
311 | /* | 328 | /* |
312 | * We got all needed information from the lowcore and can | 329 | * We got all needed information from the lowcore and can |
@@ -315,6 +332,10 @@ static void inline do_trap(long interruption_code, int signr, char *str, | |||
315 | if (regs->psw.mask & PSW_MASK_PSTATE) | 332 | if (regs->psw.mask & PSW_MASK_PSTATE) |
316 | local_irq_enable(); | 333 | local_irq_enable(); |
317 | 334 | ||
335 | if (notify_die(DIE_TRAP, str, regs, interruption_code, | ||
336 | interruption_code, signr) == NOTIFY_STOP) | ||
337 | return; | ||
338 | |||
318 | if (regs->psw.mask & PSW_MASK_PSTATE) { | 339 | if (regs->psw.mask & PSW_MASK_PSTATE) { |
319 | struct task_struct *tsk = current; | 340 | struct task_struct *tsk = current; |
320 | 341 | ||
@@ -336,8 +357,12 @@ static inline void __user *get_check_address(struct pt_regs *regs) | |||
336 | return (void __user *)((regs->psw.addr-S390_lowcore.pgm_ilc) & PSW_ADDR_INSN); | 357 | return (void __user *)((regs->psw.addr-S390_lowcore.pgm_ilc) & PSW_ADDR_INSN); |
337 | } | 358 | } |
338 | 359 | ||
339 | void do_single_step(struct pt_regs *regs) | 360 | void __kprobes do_single_step(struct pt_regs *regs) |
340 | { | 361 | { |
362 | if (notify_die(DIE_SSTEP, "sstep", regs, 0, 0, | ||
363 | SIGTRAP) == NOTIFY_STOP){ | ||
364 | return; | ||
365 | } | ||
341 | if ((current->ptrace & PT_PTRACED) != 0) | 366 | if ((current->ptrace & PT_PTRACED) != 0) |
342 | force_sig(SIGTRAP, current); | 367 | force_sig(SIGTRAP, current); |
343 | } | 368 | } |