MIPS: mm: Add debug information for userland SIGSEGV signals.
authorMarkos Chandras <markos.chandras@imgtec.com>
Wed, 21 Jan 2015 10:54:46 +0000 (10:54 +0000)
committerRalf Baechle <ralf@linux-mips.org>
Mon, 16 Feb 2015 09:55:26 +0000 (10:55 +0100)
Commit 41c594ab65fc ("[MIPS] MT: Improved multithreading support.")
removed useful debug information for userland segmentation faults.
This patch bring this back along with the ability to determine the
name of the object file where the EPC and RA registers point at.
Furthermore, we select the SYSCTL_EXCEPTION_TRACE symbol for MIPS
which is the de facto solution to turn userland exception logging
on and off via the /proc/sys/debug/exception-trace file.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
Cc: James Hogan <james.hogan@imgtec.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/9089/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
arch/mips/Kconfig
arch/mips/mm/fault.c

index 3289969ee423a9edbe7fb12359f56cea2bd2be2a..b1b2de537860dc9215a302ebd5d64fd4d4fb78bb 100644 (file)
@@ -54,6 +54,7 @@ config MIPS
        select CPU_PM if CPU_IDLE
        select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
        select ARCH_BINFMT_ELF_STATE
+       select SYSCTL_EXCEPTION_TRACE
 
 menu "Machine selection"
 
index becc42bb18495adf98389bd039bc111c1893cedd..ef10886dda46d3147022043153228481d668b0f9 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/string.h>
 #include <linux/types.h>
 #include <linux/ptrace.h>
+#include <linux/ratelimit.h>
 #include <linux/mman.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
@@ -28,6 +29,8 @@
 #include <asm/highmem.h>               /* For VMALLOC_END */
 #include <linux/kdebug.h>
 
+int show_unhandled_signals = 1;
+
 /*
  * This routine handles page faults.  It determines the address,
  * and the problem, and then passes it off to one of the appropriate
@@ -44,6 +47,8 @@ static void __kprobes __do_page_fault(struct pt_regs *regs, unsigned long write,
        int fault;
        unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
 
+       static DEFINE_RATELIMIT_STATE(ratelimit_state, 5 * HZ, 10);
+
 #if 0
        printk("Cpu%d[%s:%d:%0*lx:%ld:%0*lx]\n", raw_smp_processor_id(),
               current->comm, current->pid, field, address, write,
@@ -201,15 +206,21 @@ bad_area_nosemaphore:
        if (user_mode(regs)) {
                tsk->thread.cp0_badvaddr = address;
                tsk->thread.error_code = write;
-#if 0
-               printk("do_page_fault() #2: sending SIGSEGV to %s for "
-                      "invalid %s\n%0*lx (epc == %0*lx, ra == %0*lx)\n",
-                      tsk->comm,
-                      write ? "write access to" : "read access from",
-                      field, address,
-                      field, (unsigned long) regs->cp0_epc,
-                      field, (unsigned long) regs->regs[31]);
-#endif
+               if (show_unhandled_signals &&
+                   unhandled_signal(tsk, SIGSEGV) &&
+                   __ratelimit(&ratelimit_state)) {
+                       pr_info("\ndo_page_fault(): sending SIGSEGV to %s for invalid %s %0*lx",
+                               tsk->comm,
+                               write ? "write access to" : "read access from",
+                               field, address);
+                       pr_info("epc = %0*lx in", field,
+                               (unsigned long) regs->cp0_epc);
+                       print_vma_addr(" ", regs->cp0_epc);
+                       pr_info("ra  = %0*lx in", field,
+                               (unsigned long) regs->regs[31]);
+                       print_vma_addr(" ", regs->regs[31]);
+                       pr_info("\n");
+               }
                info.si_signo = SIGSEGV;
                info.si_errno = 0;
                /* info.si_code has been set above */