[S390] debug: enable exception-trace debug facility
authorHeiko Carstens <heiko.carstens@de.ibm.com>
Mon, 17 May 2010 08:00:21 +0000 (10:00 +0200)
committerMartin Schwidefsky <sky@mschwide.boeblingen.de.ibm.com>
Mon, 17 May 2010 08:00:17 +0000 (10:00 +0200)
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>
arch/s390/Kconfig
arch/s390/kernel/traps.c
arch/s390/mm/fault.c
kernel/sysctl.c

index 0d8cd9bbe101a07c9e39aa3a1759ba85a76381e6..79d0ca0868200462357e04ece79837647441cae3 100644 (file)
@@ -444,13 +444,6 @@ config FORCE_MAX_ZONEORDER
        int
        default "9"
 
-config PROCESS_DEBUG
-       bool "Show crashed user process info"
-       help
-         Say Y to print all process fault locations to the console.  This is
-         a debugging option; you probably do not want to set it unless you
-         are an S390 port maintainer.
-
 config PFAULT
        bool "Pseudo page fault support"
        help
index e605f070610c21f451e1fe3aa4e55be41dfb6758..5d8f0f3d025008a11614500fc1908e8cf7de1658 100644 (file)
 
 pgm_check_handler_t *pgm_check_table[128];
 
-#ifdef CONFIG_SYSCTL
-#ifdef CONFIG_PROCESS_DEBUG
-int sysctl_userprocess_debug = 1;
-#else
-int sysctl_userprocess_debug = 0;
-#endif
-#endif
+int show_unhandled_signals;
 
 extern pgm_check_handler_t do_protection_exception;
 extern pgm_check_handler_t do_dat_exception;
@@ -315,18 +309,19 @@ void die(const char * str, struct pt_regs * regs, long err)
        do_exit(SIGSEGV);
 }
 
-static void inline
-report_user_fault(long interruption_code, struct pt_regs *regs)
+static void inline report_user_fault(struct pt_regs *regs, long int_code,
+                                    int signr)
 {
-#if defined(CONFIG_SYSCTL)
-       if (!sysctl_userprocess_debug)
+       if ((task_pid_nr(current) > 1) && !show_unhandled_signals)
                return;
-#endif
-#if defined(CONFIG_SYSCTL) || defined(CONFIG_PROCESS_DEBUG)
-       printk("User process fault: interruption code 0x%lX\n",
-              interruption_code);
+       if (!unhandled_signal(current, signr))
+               return;
+       if (!printk_ratelimit())
+               return;
+       printk("User process fault: interruption code 0x%lX ", int_code);
+       print_vma_addr("in ", regs->psw.addr & PSW_ADDR_INSN);
+       printk("\n");
        show_regs(regs);
-#endif
 }
 
 int is_valid_bugaddr(unsigned long addr)
@@ -354,7 +349,7 @@ static void __kprobes inline do_trap(long interruption_code, int signr,
 
                 tsk->thread.trap_no = interruption_code & 0xffff;
                force_sig_info(signr, info, tsk);
-               report_user_fault(interruption_code, regs);
+               report_user_fault(regs, interruption_code, signr);
         } else {
                 const struct exception_table_entry *fixup;
                 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)
 {
         if (regs->psw.mask & PSW_MASK_PSTATE) {
                local_irq_enable();
-               report_user_fault(interruption_code, regs);
+               report_user_fault(regs, interruption_code, SIGSEGV);
                do_exit(SIGSEGV);
        } else
                die("Unknown program exception", regs, interruption_code);
index 3040d7c78fe083768451e7ca4da99483cba59ce3..2505b2ea0ef187803033c096bab3cff8eac45f02 100644 (file)
 #define __PF_RES_FIELD 0x8000000000000000ULL
 #endif /* CONFIG_64BIT */
 
-#ifdef CONFIG_SYSCTL
-extern int sysctl_userprocess_debug;
-#endif
-
 #define VM_FAULT_BADCONTEXT    0x010000
 #define VM_FAULT_BADMAP                0x020000
 #define VM_FAULT_BADACCESS     0x040000
@@ -120,6 +116,22 @@ static inline int user_space_fault(unsigned long trans_exc_code)
        return trans_exc_code != 3;
 }
 
+static inline void report_user_fault(struct pt_regs *regs, long int_code,
+                                    int signr, unsigned long address)
+{
+       if ((task_pid_nr(current) > 1) && !show_unhandled_signals)
+               return;
+       if (!unhandled_signal(current, signr))
+               return;
+       if (!printk_ratelimit())
+               return;
+       printk("User process fault: interruption code 0x%lX ", int_code);
+       print_vma_addr(KERN_CONT "in ", regs->psw.addr & PSW_ADDR_INSN);
+       printk("\n");
+       printk("failing address: %lX\n", address);
+       show_regs(regs);
+}
+
 /*
  * Send SIGSEGV to task.  This is an external routine
  * to keep the stack usage of do_page_fault small.
@@ -133,17 +145,7 @@ static noinline void do_sigsegv(struct pt_regs *regs, long int_code,
        address = trans_exc_code & __FAIL_ADDR_MASK;
        current->thread.prot_addr = address;
        current->thread.trap_no = int_code;
-#if defined(CONFIG_SYSCTL) || defined(CONFIG_PROCESS_DEBUG)
-#if defined(CONFIG_SYSCTL)
-       if (sysctl_userprocess_debug)
-#endif
-       {
-               printk("User process fault: interruption code 0x%lX\n",
-                      int_code);
-               printk("failing address: %lX\n", address);
-               show_regs(regs);
-       }
-#endif
+       report_user_fault(regs, int_code, SIGSEGV, address);
        si.si_signo = SIGSEGV;
        si.si_code = si_code;
        si.si_addr = (void __user *) address;
index 8686b0f5fc12fc85d19c31d934bbe34bd55d5af2..90f536d846439439593af5f85c92bace046c611e 100644 (file)
@@ -621,7 +621,7 @@ static struct ctl_table kern_table[] = {
 #endif
        {
                .procname       = "userprocess_debug",
-               .data           = &sysctl_userprocess_debug,
+               .data           = &show_unhandled_signals,
                .maxlen         = sizeof(int),
                .mode           = 0644,
                .proc_handler   = proc_dointvec,
@@ -1431,7 +1431,8 @@ static struct ctl_table fs_table[] = {
 };
 
 static struct ctl_table debug_table[] = {
-#if defined(CONFIG_X86) || defined(CONFIG_PPC) || defined(CONFIG_SPARC)
+#if defined(CONFIG_X86) || defined(CONFIG_PPC) || defined(CONFIG_SPARC) || \
+    defined(CONFIG_S390)
        {
                .procname       = "exception-trace",
                .data           = &show_unhandled_signals,