aboutsummaryrefslogtreecommitdiff
path: root/arch/s390/kernel/traps.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390/kernel/traps.c')
-rw-r--r--arch/s390/kernel/traps.c39
1 files changed, 32 insertions, 7 deletions
diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c
index b5a4a739b477..ff0dc02adc38 100644
--- a/arch/s390/kernel/traps.c
+++ b/arch/s390/kernel/traps.c
@@ -5,6 +5,7 @@
* Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
* Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
* Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com),
+ * Portions added by T. Halloran: (C) Copyright 2002 IBM Poughkeepsie, IBM Corporation
*
* Derived from "arch/i386/kernel/traps.c"
* Copyright (C) 1991, 1992 Linus Torvalds
@@ -33,6 +34,7 @@
#include <linux/kprobes.h>
#include <linux/bug.h>
#include <linux/utsname.h>
+#include <trace/trap.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/io.h>
@@ -65,6 +67,12 @@ static int kstack_depth_to_print = 20;
#endif /* CONFIG_64BIT */
/*
+ * Also used in fault.c.
+ */
+DEFINE_TRACE(trap_entry);
+DEFINE_TRACE(trap_exit);
+
+/*
* For show_trace we have tree different stack to consider:
* - the panic stack which is used if the kernel stack has overflown
* - the asynchronous interrupt stack (cpu related)
@@ -299,6 +307,8 @@ static inline void __kprobes do_trap(long pgm_int_code, int signr, char *str,
pgm_int_code, signr) == NOTIFY_STOP)
return;
+ trace_trap_entry(regs, pgm_int_code & 0xffff);
+
if (regs->psw.mask & PSW_MASK_PSTATE) {
struct task_struct *tsk = current;
@@ -314,11 +324,14 @@ static inline void __kprobes do_trap(long pgm_int_code, int signr, char *str,
enum bug_trap_type btt;
btt = report_bug(regs->psw.addr & PSW_ADDR_INSN, regs);
- if (btt == BUG_TRAP_TYPE_WARN)
+ if (btt == BUG_TRAP_TYPE_WARN) {
+ trace_trap_exit();
return;
+ }
die(str, regs, pgm_int_code);
}
}
+ trace_trap_exit();
}
static inline void __user *get_psw_address(struct pt_regs *regs,
@@ -422,9 +435,11 @@ static void __kprobes illegal_op(struct pt_regs *regs, long pgm_int_code,
location = get_psw_address(regs, pgm_int_code);
+ trace_trap_entry(regs, pgm_int_code & 0xffff);
+
if (regs->psw.mask & PSW_MASK_PSTATE) {
if (get_user(*((__u16 *) opcode), (__u16 __user *) location))
- return;
+ goto end;
if (*((__u16 *) opcode) == S390_BREAKPOINT_U16) {
if (tracehook_consider_fatal_signal(current, SIGTRAP))
force_sig(SIGTRAP, current);
@@ -433,24 +448,24 @@ static void __kprobes illegal_op(struct pt_regs *regs, long pgm_int_code,
#ifdef CONFIG_MATHEMU
} else if (opcode[0] == 0xb3) {
if (get_user(*((__u16 *) (opcode+2)), location+1))
- return;
+ goto end;
signal = math_emu_b3(opcode, regs);
} else if (opcode[0] == 0xed) {
if (get_user(*((__u32 *) (opcode+2)),
(__u32 __user *)(location+1)))
- return;
+ goto end;
signal = math_emu_ed(opcode, regs);
} else if (*((__u16 *) opcode) == 0xb299) {
if (get_user(*((__u16 *) (opcode+2)), location+1))
- return;
+ goto end;
signal = math_emu_srnm(opcode, regs);
} else if (*((__u16 *) opcode) == 0xb29c) {
if (get_user(*((__u16 *) (opcode+2)), location+1))
- return;
+ goto end;
signal = math_emu_stfpc(opcode, regs);
} else if (*((__u16 *) opcode) == 0xb29d) {
if (get_user(*((__u16 *) (opcode+2)), location+1))
- return;
+ goto end;
signal = math_emu_lfpc(opcode, regs);
#endif
} else
@@ -486,6 +501,8 @@ static void __kprobes illegal_op(struct pt_regs *regs, long pgm_int_code,
do_trap(pgm_int_code, signal,
"illegal operation", regs, &info);
}
+end:
+ trace_trap_exit();
}
@@ -500,6 +517,8 @@ asmlinkage void specification_exception(struct pt_regs *regs,
location = (__u16 __user *) get_psw_address(regs, pgm_int_code);
+ trace_trap_entry(regs, pgm_int_code & 0xffff);
+
if (regs->psw.mask & PSW_MASK_PSTATE) {
get_user(*((__u16 *) opcode), location);
switch (opcode[0]) {
@@ -544,6 +563,7 @@ asmlinkage void specification_exception(struct pt_regs *regs,
do_trap(pgm_int_code, signal,
"specification exception", regs, &info);
}
+ trace_trap_exit();
}
#else
DO_ERROR_INFO(specification_exception, SIGILL, ILL_ILLOPN,
@@ -558,6 +578,8 @@ static void data_exception(struct pt_regs *regs, long pgm_int_code,
location = get_psw_address(regs, pgm_int_code);
+ trace_trap_entry(regs, pgm_int_code & 0xffff);
+
if (MACHINE_HAS_IEEE)
asm volatile("stfpc %0" : "=m" (current->thread.fp_regs.fpc));
@@ -631,6 +653,7 @@ static void data_exception(struct pt_regs *regs, long pgm_int_code,
info.si_addr = location;
do_trap(pgm_int_code, signal, "data exception", regs, &info);
}
+ trace_trap_exit();
}
static void space_switch_exception(struct pt_regs *regs, long pgm_int_code,
@@ -638,6 +661,7 @@ static void space_switch_exception(struct pt_regs *regs, long pgm_int_code,
{
siginfo_t info;
+ trace_trap_entry(regs, pgm_int_code & 0xffff);
/* Set user psw back to home space mode. */
if (regs->psw.mask & PSW_MASK_PSTATE)
regs->psw.mask |= PSW_ASC_HOME;
@@ -647,6 +671,7 @@ static void space_switch_exception(struct pt_regs *regs, long pgm_int_code,
info.si_code = ILL_PRVOPC;
info.si_addr = get_psw_address(regs, pgm_int_code);
do_trap(pgm_int_code, SIGILL, "space switch event", regs, &info);
+ trace_trap_exit();
}
asmlinkage void __kprobes kernel_stack_overflow(struct pt_regs * regs)