diff options
author | Heiko Carstens <heiko.carstens@de.ibm.com> | 2010-05-17 04:00:21 -0400 |
---|---|---|
committer | Martin Schwidefsky <sky@mschwide.boeblingen.de.ibm.com> | 2010-05-17 04:00:17 -0400 |
commit | ab3c68ee5fd329ba48094d3417fd60e30ea14a87 (patch) | |
tree | e5c3daa56821c33ea80b6853b4f817193b22df99 /arch/s390/kernel | |
parent | 57b28f66316d287b9dbf7b28358ca90257230769 (diff) |
[S390] debug: enable exception-trace debug facility
The exception-trace facility on x86 and other architectures prints
traces to dmesg whenever a user space application crashes.
s390 has such a feature since ages however it is called
userprocess_debug and is enabled differently.
This patch makes sure that whenever one of the two procfs files
/proc/sys/kernel/userprocess_debug
/proc/sys/debug/exception-trace
is modified the contents of the second one changes as well.
That way we keep backwards compatibilty but also support the same
interface like other architectures do.
Besides that the output of the traces is improved since it will now
also contain the corresponding filename of the vma (when available)
where the process caused a fault or trap.
Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'arch/s390/kernel')
-rw-r--r-- | arch/s390/kernel/traps.c | 31 |
1 files changed, 13 insertions, 18 deletions
diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c index e605f070610c..5d8f0f3d0250 100644 --- a/arch/s390/kernel/traps.c +++ b/arch/s390/kernel/traps.c | |||
@@ -46,13 +46,7 @@ | |||
46 | 46 | ||
47 | pgm_check_handler_t *pgm_check_table[128]; | 47 | pgm_check_handler_t *pgm_check_table[128]; |
48 | 48 | ||
49 | #ifdef CONFIG_SYSCTL | 49 | int show_unhandled_signals; |
50 | #ifdef CONFIG_PROCESS_DEBUG | ||
51 | int sysctl_userprocess_debug = 1; | ||
52 | #else | ||
53 | int sysctl_userprocess_debug = 0; | ||
54 | #endif | ||
55 | #endif | ||
56 | 50 | ||
57 | extern pgm_check_handler_t do_protection_exception; | 51 | extern pgm_check_handler_t do_protection_exception; |
58 | extern pgm_check_handler_t do_dat_exception; | 52 | extern pgm_check_handler_t do_dat_exception; |
@@ -315,18 +309,19 @@ void die(const char * str, struct pt_regs * regs, long err) | |||
315 | do_exit(SIGSEGV); | 309 | do_exit(SIGSEGV); |
316 | } | 310 | } |
317 | 311 | ||
318 | static void inline | 312 | static void inline report_user_fault(struct pt_regs *regs, long int_code, |
319 | report_user_fault(long interruption_code, struct pt_regs *regs) | 313 | int signr) |
320 | { | 314 | { |
321 | #if defined(CONFIG_SYSCTL) | 315 | if ((task_pid_nr(current) > 1) && !show_unhandled_signals) |
322 | if (!sysctl_userprocess_debug) | ||
323 | return; | 316 | return; |
324 | #endif | 317 | if (!unhandled_signal(current, signr)) |
325 | #if defined(CONFIG_SYSCTL) || defined(CONFIG_PROCESS_DEBUG) | 318 | return; |
326 | printk("User process fault: interruption code 0x%lX\n", | 319 | if (!printk_ratelimit()) |
327 | interruption_code); | 320 | return; |
321 | printk("User process fault: interruption code 0x%lX ", int_code); | ||
322 | print_vma_addr("in ", regs->psw.addr & PSW_ADDR_INSN); | ||
323 | printk("\n"); | ||
328 | show_regs(regs); | 324 | show_regs(regs); |
329 | #endif | ||
330 | } | 325 | } |
331 | 326 | ||
332 | int is_valid_bugaddr(unsigned long addr) | 327 | int is_valid_bugaddr(unsigned long addr) |
@@ -354,7 +349,7 @@ static void __kprobes inline do_trap(long interruption_code, int signr, | |||
354 | 349 | ||
355 | tsk->thread.trap_no = interruption_code & 0xffff; | 350 | tsk->thread.trap_no = interruption_code & 0xffff; |
356 | force_sig_info(signr, info, tsk); | 351 | force_sig_info(signr, info, tsk); |
357 | report_user_fault(interruption_code, regs); | 352 | report_user_fault(regs, interruption_code, signr); |
358 | } else { | 353 | } else { |
359 | const struct exception_table_entry *fixup; | 354 | const struct exception_table_entry *fixup; |
360 | fixup = search_exception_tables(regs->psw.addr & PSW_ADDR_INSN); | 355 | fixup = search_exception_tables(regs->psw.addr & PSW_ADDR_INSN); |
@@ -390,7 +385,7 @@ static void default_trap_handler(struct pt_regs * regs, long interruption_code) | |||
390 | { | 385 | { |
391 | if (regs->psw.mask & PSW_MASK_PSTATE) { | 386 | if (regs->psw.mask & PSW_MASK_PSTATE) { |
392 | local_irq_enable(); | 387 | local_irq_enable(); |
393 | report_user_fault(interruption_code, regs); | 388 | report_user_fault(regs, interruption_code, SIGSEGV); |
394 | do_exit(SIGSEGV); | 389 | do_exit(SIGSEGV); |
395 | } else | 390 | } else |
396 | die("Unknown program exception", regs, interruption_code); | 391 | die("Unknown program exception", regs, interruption_code); |