diff options
Diffstat (limited to 'arch/s390/kernel/traps.c')
-rw-r--r-- | arch/s390/kernel/traps.c | 38 |
1 files changed, 22 insertions, 16 deletions
diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c index a65d2e82f61..ffabcd9d336 100644 --- a/arch/s390/kernel/traps.c +++ b/arch/s390/kernel/traps.c | |||
@@ -18,7 +18,7 @@ | |||
18 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
19 | #include <linux/string.h> | 19 | #include <linux/string.h> |
20 | #include <linux/errno.h> | 20 | #include <linux/errno.h> |
21 | #include <linux/tracehook.h> | 21 | #include <linux/ptrace.h> |
22 | #include <linux/timer.h> | 22 | #include <linux/timer.h> |
23 | #include <linux/mm.h> | 23 | #include <linux/mm.h> |
24 | #include <linux/smp.h> | 24 | #include <linux/smp.h> |
@@ -36,21 +36,17 @@ | |||
36 | #include <asm/system.h> | 36 | #include <asm/system.h> |
37 | #include <asm/uaccess.h> | 37 | #include <asm/uaccess.h> |
38 | #include <asm/io.h> | 38 | #include <asm/io.h> |
39 | #include <asm/atomic.h> | 39 | #include <linux/atomic.h> |
40 | #include <asm/mathemu.h> | 40 | #include <asm/mathemu.h> |
41 | #include <asm/cpcmd.h> | 41 | #include <asm/cpcmd.h> |
42 | #include <asm/lowcore.h> | 42 | #include <asm/lowcore.h> |
43 | #include <asm/debug.h> | 43 | #include <asm/debug.h> |
44 | #include "entry.h" | 44 | #include "entry.h" |
45 | 45 | ||
46 | pgm_check_handler_t *pgm_check_table[128]; | 46 | void (*pgm_check_table[128])(struct pt_regs *, long, unsigned long); |
47 | 47 | ||
48 | int show_unhandled_signals; | 48 | int show_unhandled_signals; |
49 | 49 | ||
50 | extern pgm_check_handler_t do_protection_exception; | ||
51 | extern pgm_check_handler_t do_dat_exception; | ||
52 | extern pgm_check_handler_t do_asce_exception; | ||
53 | |||
54 | #define stack_pointer ({ void **sp; asm("la %0,0(15)" : "=&d" (sp)); sp; }) | 50 | #define stack_pointer ({ void **sp; asm("la %0,0(15)" : "=&d" (sp)); sp; }) |
55 | 51 | ||
56 | #ifndef CONFIG_64BIT | 52 | #ifndef CONFIG_64BIT |
@@ -329,10 +325,17 @@ static inline void __user *get_psw_address(struct pt_regs *regs, | |||
329 | 325 | ||
330 | void __kprobes do_per_trap(struct pt_regs *regs) | 326 | void __kprobes do_per_trap(struct pt_regs *regs) |
331 | { | 327 | { |
328 | siginfo_t info; | ||
329 | |||
332 | if (notify_die(DIE_SSTEP, "sstep", regs, 0, 0, SIGTRAP) == NOTIFY_STOP) | 330 | if (notify_die(DIE_SSTEP, "sstep", regs, 0, 0, SIGTRAP) == NOTIFY_STOP) |
333 | return; | 331 | return; |
334 | if (tracehook_consider_fatal_signal(current, SIGTRAP)) | 332 | if (!current->ptrace) |
335 | force_sig(SIGTRAP, current); | 333 | return; |
334 | info.si_signo = SIGTRAP; | ||
335 | info.si_errno = 0; | ||
336 | info.si_code = TRAP_HWBKPT; | ||
337 | info.si_addr = (void *) current->thread.per_event.address; | ||
338 | force_sig_info(SIGTRAP, &info, current); | ||
336 | } | 339 | } |
337 | 340 | ||
338 | static void default_trap_handler(struct pt_regs *regs, long pgm_int_code, | 341 | static void default_trap_handler(struct pt_regs *regs, long pgm_int_code, |
@@ -425,9 +428,13 @@ static void __kprobes illegal_op(struct pt_regs *regs, long pgm_int_code, | |||
425 | if (get_user(*((__u16 *) opcode), (__u16 __user *) location)) | 428 | if (get_user(*((__u16 *) opcode), (__u16 __user *) location)) |
426 | return; | 429 | return; |
427 | if (*((__u16 *) opcode) == S390_BREAKPOINT_U16) { | 430 | if (*((__u16 *) opcode) == S390_BREAKPOINT_U16) { |
428 | if (tracehook_consider_fatal_signal(current, SIGTRAP)) | 431 | if (current->ptrace) { |
429 | force_sig(SIGTRAP, current); | 432 | info.si_signo = SIGTRAP; |
430 | else | 433 | info.si_errno = 0; |
434 | info.si_code = TRAP_BRKPT; | ||
435 | info.si_addr = location; | ||
436 | force_sig_info(SIGTRAP, &info, current); | ||
437 | } else | ||
431 | signal = SIGILL; | 438 | signal = SIGILL; |
432 | #ifdef CONFIG_MATHEMU | 439 | #ifdef CONFIG_MATHEMU |
433 | } else if (opcode[0] == 0xb3) { | 440 | } else if (opcode[0] == 0xb3) { |
@@ -489,9 +496,8 @@ static void __kprobes illegal_op(struct pt_regs *regs, long pgm_int_code, | |||
489 | 496 | ||
490 | 497 | ||
491 | #ifdef CONFIG_MATHEMU | 498 | #ifdef CONFIG_MATHEMU |
492 | asmlinkage void specification_exception(struct pt_regs *regs, | 499 | void specification_exception(struct pt_regs *regs, long pgm_int_code, |
493 | long pgm_int_code, | 500 | unsigned long trans_exc_code) |
494 | unsigned long trans_exc_code) | ||
495 | { | 501 | { |
496 | __u8 opcode[6]; | 502 | __u8 opcode[6]; |
497 | __u16 __user *location = NULL; | 503 | __u16 __user *location = NULL; |
@@ -648,7 +654,7 @@ static void space_switch_exception(struct pt_regs *regs, long pgm_int_code, | |||
648 | do_trap(pgm_int_code, SIGILL, "space switch event", regs, &info); | 654 | do_trap(pgm_int_code, SIGILL, "space switch event", regs, &info); |
649 | } | 655 | } |
650 | 656 | ||
651 | asmlinkage void __kprobes kernel_stack_overflow(struct pt_regs * regs) | 657 | void __kprobes kernel_stack_overflow(struct pt_regs * regs) |
652 | { | 658 | { |
653 | bust_spinlocks(1); | 659 | bust_spinlocks(1); |
654 | printk("Kernel stack overflow.\n"); | 660 | printk("Kernel stack overflow.\n"); |