aboutsummaryrefslogtreecommitdiffstats
path: root/arch/parisc
diff options
context:
space:
mode:
Diffstat (limited to 'arch/parisc')
-rw-r--r--arch/parisc/Kconfig1
-rw-r--r--arch/parisc/kernel/traps.c54
-rw-r--r--arch/parisc/mm/fault.c44
3 files changed, 56 insertions, 43 deletions
diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig
index bb2a8ec440e7..a8f4a70c0742 100644
--- a/arch/parisc/Kconfig
+++ b/arch/parisc/Kconfig
@@ -22,6 +22,7 @@ config PARISC
22 select GENERIC_SMP_IDLE_THREAD 22 select GENERIC_SMP_IDLE_THREAD
23 select GENERIC_STRNCPY_FROM_USER 23 select GENERIC_STRNCPY_FROM_USER
24 select SYSCTL_ARCH_UNALIGN_ALLOW 24 select SYSCTL_ARCH_UNALIGN_ALLOW
25 select SYSCTL_EXCEPTION_TRACE
25 select HAVE_MOD_ARCH_SPECIFIC 26 select HAVE_MOD_ARCH_SPECIFIC
26 select VIRT_TO_BUS 27 select VIRT_TO_BUS
27 select MODULES_USE_ELF_RELA 28 select MODULES_USE_ELF_RELA
diff --git a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c
index 1cd1d0c83b6d..47ee620d15d2 100644
--- a/arch/parisc/kernel/traps.c
+++ b/arch/parisc/kernel/traps.c
@@ -25,6 +25,7 @@
25#include <linux/interrupt.h> 25#include <linux/interrupt.h>
26#include <linux/console.h> 26#include <linux/console.h>
27#include <linux/bug.h> 27#include <linux/bug.h>
28#include <linux/ratelimit.h>
28 29
29#include <asm/assembly.h> 30#include <asm/assembly.h>
30#include <asm/uaccess.h> 31#include <asm/uaccess.h>
@@ -42,9 +43,6 @@
42 43
43#include "../math-emu/math-emu.h" /* for handle_fpe() */ 44#include "../math-emu/math-emu.h" /* for handle_fpe() */
44 45
45#define PRINT_USER_FAULTS /* (turn this on if you want user faults to be */
46 /* dumped to the console via printk) */
47
48#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK) 46#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
49DEFINE_SPINLOCK(pa_dbit_lock); 47DEFINE_SPINLOCK(pa_dbit_lock);
50#endif 48#endif
@@ -160,6 +158,17 @@ void show_regs(struct pt_regs *regs)
160 } 158 }
161} 159}
162 160
161static DEFINE_RATELIMIT_STATE(_hppa_rs,
162 DEFAULT_RATELIMIT_INTERVAL, DEFAULT_RATELIMIT_BURST);
163
164#define parisc_printk_ratelimited(critical, regs, fmt, ...) { \
165 if ((critical || show_unhandled_signals) && __ratelimit(&_hppa_rs)) { \
166 printk(fmt, ##__VA_ARGS__); \
167 show_regs(regs); \
168 } \
169}
170
171
163static void do_show_stack(struct unwind_frame_info *info) 172static void do_show_stack(struct unwind_frame_info *info)
164{ 173{
165 int i = 1; 174 int i = 1;
@@ -229,12 +238,10 @@ void die_if_kernel(char *str, struct pt_regs *regs, long err)
229 if (err == 0) 238 if (err == 0)
230 return; /* STFU */ 239 return; /* STFU */
231 240
232 printk(KERN_CRIT "%s (pid %d): %s (code %ld) at " RFMT "\n", 241 parisc_printk_ratelimited(1, regs,
242 KERN_CRIT "%s (pid %d): %s (code %ld) at " RFMT "\n",
233 current->comm, task_pid_nr(current), str, err, regs->iaoq[0]); 243 current->comm, task_pid_nr(current), str, err, regs->iaoq[0]);
234#ifdef PRINT_USER_FAULTS 244
235 /* XXX for debugging only */
236 show_regs(regs);
237#endif
238 return; 245 return;
239 } 246 }
240 247
@@ -321,14 +328,11 @@ static void handle_break(struct pt_regs *regs)
321 (tt == BUG_TRAP_TYPE_NONE) ? 9 : 0); 328 (tt == BUG_TRAP_TYPE_NONE) ? 9 : 0);
322 } 329 }
323 330
324#ifdef PRINT_USER_FAULTS 331 if (unlikely(iir != GDB_BREAK_INSN))
325 if (unlikely(iir != GDB_BREAK_INSN)) { 332 parisc_printk_ratelimited(0, regs,
326 printk(KERN_DEBUG "break %d,%d: pid=%d command='%s'\n", 333 KERN_DEBUG "break %d,%d: pid=%d command='%s'\n",
327 iir & 31, (iir>>13) & ((1<<13)-1), 334 iir & 31, (iir>>13) & ((1<<13)-1),
328 task_pid_nr(current), current->comm); 335 task_pid_nr(current), current->comm);
329 show_regs(regs);
330 }
331#endif
332 336
333 /* send standard GDB signal */ 337 /* send standard GDB signal */
334 handle_gdb_break(regs, TRAP_BRKPT); 338 handle_gdb_break(regs, TRAP_BRKPT);
@@ -758,11 +762,9 @@ void notrace handle_interruption(int code, struct pt_regs *regs)
758 762
759 default: 763 default:
760 if (user_mode(regs)) { 764 if (user_mode(regs)) {
761#ifdef PRINT_USER_FAULTS 765 parisc_printk_ratelimited(0, regs, KERN_DEBUG
762 printk(KERN_DEBUG "\nhandle_interruption() pid=%d command='%s'\n", 766 "handle_interruption() pid=%d command='%s'\n",
763 task_pid_nr(current), current->comm); 767 task_pid_nr(current), current->comm);
764 show_regs(regs);
765#endif
766 /* SIGBUS, for lack of a better one. */ 768 /* SIGBUS, for lack of a better one. */
767 si.si_signo = SIGBUS; 769 si.si_signo = SIGBUS;
768 si.si_code = BUS_OBJERR; 770 si.si_code = BUS_OBJERR;
@@ -779,16 +781,10 @@ void notrace handle_interruption(int code, struct pt_regs *regs)
779 781
780 if (user_mode(regs)) { 782 if (user_mode(regs)) {
781 if ((fault_space >> SPACEID_SHIFT) != (regs->sr[7] >> SPACEID_SHIFT)) { 783 if ((fault_space >> SPACEID_SHIFT) != (regs->sr[7] >> SPACEID_SHIFT)) {
782#ifdef PRINT_USER_FAULTS 784 parisc_printk_ratelimited(0, regs, KERN_DEBUG
783 if (fault_space == 0) 785 "User fault %d on space 0x%08lx, pid=%d command='%s'\n",
784 printk(KERN_DEBUG "User Fault on Kernel Space "); 786 code, fault_space,
785 else 787 task_pid_nr(current), current->comm);
786 printk(KERN_DEBUG "User Fault (long pointer) (fault %d) ",
787 code);
788 printk(KERN_CONT "pid=%d command='%s'\n",
789 task_pid_nr(current), current->comm);
790 show_regs(regs);
791#endif
792 si.si_signo = SIGSEGV; 788 si.si_signo = SIGSEGV;
793 si.si_errno = 0; 789 si.si_errno = 0;
794 si.si_code = SEGV_MAPERR; 790 si.si_code = SEGV_MAPERR;
diff --git a/arch/parisc/mm/fault.c b/arch/parisc/mm/fault.c
index 9d08c71a967e..d72197f0ddb8 100644
--- a/arch/parisc/mm/fault.c
+++ b/arch/parisc/mm/fault.c
@@ -19,10 +19,6 @@
19#include <asm/uaccess.h> 19#include <asm/uaccess.h>
20#include <asm/traps.h> 20#include <asm/traps.h>
21 21
22#define PRINT_USER_FAULTS /* (turn this on if you want user faults to be */
23 /* dumped to the console via printk) */
24
25
26/* Various important other fields */ 22/* Various important other fields */
27#define bit22set(x) (x & 0x00000200) 23#define bit22set(x) (x & 0x00000200)
28#define bits23_25set(x) (x & 0x000001c0) 24#define bits23_25set(x) (x & 0x000001c0)
@@ -34,6 +30,8 @@
34 30
35DEFINE_PER_CPU(struct exception_data, exception_data); 31DEFINE_PER_CPU(struct exception_data, exception_data);
36 32
33int show_unhandled_signals = 1;
34
37/* 35/*
38 * parisc_acctyp(unsigned int inst) -- 36 * parisc_acctyp(unsigned int inst) --
39 * Given a PA-RISC memory access instruction, determine if the 37 * Given a PA-RISC memory access instruction, determine if the
@@ -173,6 +171,32 @@ int fixup_exception(struct pt_regs *regs)
173 return 0; 171 return 0;
174} 172}
175 173
174/*
175 * Print out info about fatal segfaults, if the show_unhandled_signals
176 * sysctl is set:
177 */
178static inline void
179show_signal_msg(struct pt_regs *regs, unsigned long code,
180 unsigned long address, struct task_struct *tsk,
181 struct vm_area_struct *vma)
182{
183 if (!unhandled_signal(tsk, SIGSEGV))
184 return;
185
186 if (!printk_ratelimit())
187 return;
188
189 pr_warn("\n");
190 pr_warn("do_page_fault() command='%s' type=%lu address=0x%08lx",
191 tsk->comm, code, address);
192 print_vma_addr(KERN_CONT " in ", regs->iaoq[0]);
193 if (vma)
194 pr_warn(" vm_start = 0x%08lx, vm_end = 0x%08lx\n",
195 vma->vm_start, vma->vm_end);
196
197 show_regs(regs);
198}
199
176void do_page_fault(struct pt_regs *regs, unsigned long code, 200void do_page_fault(struct pt_regs *regs, unsigned long code,
177 unsigned long address) 201 unsigned long address)
178{ 202{
@@ -270,16 +294,8 @@ bad_area:
270 if (user_mode(regs)) { 294 if (user_mode(regs)) {
271 struct siginfo si; 295 struct siginfo si;
272 296
273#ifdef PRINT_USER_FAULTS 297 show_signal_msg(regs, code, address, tsk, vma);
274 printk(KERN_DEBUG "\n"); 298
275 printk(KERN_DEBUG "do_page_fault() pid=%d command='%s' type=%lu address=0x%08lx\n",
276 task_pid_nr(tsk), tsk->comm, code, address);
277 if (vma) {
278 printk(KERN_DEBUG "vm_start = 0x%08lx, vm_end = 0x%08lx\n",
279 vma->vm_start, vma->vm_end);
280 }
281 show_regs(regs);
282#endif
283 switch (code) { 299 switch (code) {
284 case 15: /* Data TLB miss fault/Data page fault */ 300 case 15: /* Data TLB miss fault/Data page fault */
285 /* send SIGSEGV when outside of vma */ 301 /* send SIGSEGV when outside of vma */