aboutsummaryrefslogtreecommitdiffstats
path: root/arch/parisc/kernel/traps.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/parisc/kernel/traps.c')
-rw-r--r--arch/parisc/kernel/traps.c153
1 files changed, 75 insertions, 78 deletions
diff --git a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c
index 65cd6ca32fed..55bc1471967d 100644
--- a/arch/parisc/kernel/traps.c
+++ b/arch/parisc/kernel/traps.c
@@ -26,6 +26,7 @@
26#include <linux/interrupt.h> 26#include <linux/interrupt.h>
27#include <linux/console.h> 27#include <linux/console.h>
28#include <linux/kallsyms.h> 28#include <linux/kallsyms.h>
29#include <linux/bug.h>
29 30
30#include <asm/assembly.h> 31#include <asm/assembly.h>
31#include <asm/system.h> 32#include <asm/system.h>
@@ -39,6 +40,8 @@
39#include <asm/pdc.h> 40#include <asm/pdc.h>
40#include <asm/pdc_chassis.h> 41#include <asm/pdc_chassis.h>
41#include <asm/unwind.h> 42#include <asm/unwind.h>
43#include <asm/tlbflush.h>
44#include <asm/cacheflush.h>
42 45
43#include "../math-emu/math-emu.h" /* for handle_fpe() */ 46#include "../math-emu/math-emu.h" /* for handle_fpe() */
44 47
@@ -49,7 +52,7 @@
49DEFINE_SPINLOCK(pa_dbit_lock); 52DEFINE_SPINLOCK(pa_dbit_lock);
50#endif 53#endif
51 54
52int printbinary(char *buf, unsigned long x, int nbits) 55static int printbinary(char *buf, unsigned long x, int nbits)
53{ 56{
54 unsigned long mask = 1UL << (nbits - 1); 57 unsigned long mask = 1UL << (nbits - 1);
55 while (mask != 0) { 58 while (mask != 0) {
@@ -61,7 +64,7 @@ int printbinary(char *buf, unsigned long x, int nbits)
61 return nbits; 64 return nbits;
62} 65}
63 66
64#ifdef __LP64__ 67#ifdef CONFIG_64BIT
65#define RFMT "%016lx" 68#define RFMT "%016lx"
66#else 69#else
67#define RFMT "%08lx" 70#define RFMT "%08lx"
@@ -160,13 +163,13 @@ static void do_show_stack(struct unwind_frame_info *info)
160{ 163{
161 int i = 1; 164 int i = 1;
162 165
163 printk("Backtrace:\n"); 166 printk(KERN_CRIT "Backtrace:\n");
164 while (i <= 16) { 167 while (i <= 16) {
165 if (unwind_once(info) < 0 || info->ip == 0) 168 if (unwind_once(info) < 0 || info->ip == 0)
166 break; 169 break;
167 170
168 if (__kernel_text_address(info->ip)) { 171 if (__kernel_text_address(info->ip)) {
169 printk(" [<" RFMT ">] ", info->ip); 172 printk("%s [<" RFMT ">] ", (i&0x3)==1 ? KERN_CRIT : "", info->ip);
170#ifdef CONFIG_KALLSYMS 173#ifdef CONFIG_KALLSYMS
171 print_symbol("%s\n", info->ip); 174 print_symbol("%s\n", info->ip);
172#else 175#else
@@ -185,18 +188,19 @@ void show_stack(struct task_struct *task, unsigned long *s)
185 188
186 if (!task) { 189 if (!task) {
187 unsigned long sp; 190 unsigned long sp;
188 struct pt_regs *r;
189 191
190HERE: 192HERE:
191 asm volatile ("copy %%r30, %0" : "=r"(sp)); 193 asm volatile ("copy %%r30, %0" : "=r"(sp));
192 r = kzalloc(sizeof(struct pt_regs), GFP_KERNEL); 194 {
193 if (!r) 195 struct pt_regs r;
194 return; 196
195 r->iaoq[0] = (unsigned long)&&HERE; 197 memset(&r, 0, sizeof(struct pt_regs));
196 r->gr[2] = (unsigned long)__builtin_return_address(0); 198 r.iaoq[0] = (unsigned long)&&HERE;
197 r->gr[30] = sp; 199 r.gr[2] = (unsigned long)__builtin_return_address(0);
198 unwind_frame_init(&info, current, r); 200 r.gr[30] = sp;
199 kfree(r); 201
202 unwind_frame_init(&info, current, &r);
203 }
200 } else { 204 } else {
201 unwind_frame_init_from_blocked_task(&info, task); 205 unwind_frame_init_from_blocked_task(&info, task);
202 } 206 }
@@ -204,6 +208,11 @@ HERE:
204 do_show_stack(&info); 208 do_show_stack(&info);
205} 209}
206 210
211int is_valid_bugaddr(unsigned long iaoq)
212{
213 return 1;
214}
215
207void die_if_kernel(char *str, struct pt_regs *regs, long err) 216void die_if_kernel(char *str, struct pt_regs *regs, long err)
208{ 217{
209 if (user_mode(regs)) { 218 if (user_mode(regs)) {
@@ -222,15 +231,15 @@ void die_if_kernel(char *str, struct pt_regs *regs, long err)
222 oops_in_progress = 1; 231 oops_in_progress = 1;
223 232
224 /* Amuse the user in a SPARC fashion */ 233 /* Amuse the user in a SPARC fashion */
225 printk( 234 if (err) printk(
226" _______________________________ \n" 235KERN_CRIT " _______________________________ \n"
227" < Your System ate a SPARC! Gah! >\n" 236KERN_CRIT " < Your System ate a SPARC! Gah! >\n"
228" ------------------------------- \n" 237KERN_CRIT " ------------------------------- \n"
229" \\ ^__^\n" 238KERN_CRIT " \\ ^__^\n"
230" \\ (xx)\\_______\n" 239KERN_CRIT " \\ (xx)\\_______\n"
231" (__)\\ )\\/\\\n" 240KERN_CRIT " (__)\\ )\\/\\\n"
232" U ||----w |\n" 241KERN_CRIT " U ||----w |\n"
233" || ||\n"); 242KERN_CRIT " || ||\n");
234 243
235 /* unlock the pdc lock if necessary */ 244 /* unlock the pdc lock if necessary */
236 pdc_emergency_unlock(); 245 pdc_emergency_unlock();
@@ -242,9 +251,20 @@ void die_if_kernel(char *str, struct pt_regs *regs, long err)
242 if (!console_drivers) 251 if (!console_drivers)
243 pdc_console_restart(); 252 pdc_console_restart();
244 253
245 printk(KERN_CRIT "%s (pid %d): %s (code %ld)\n", 254 if (err)
246 current->comm, current->pid, str, err); 255 printk(KERN_CRIT "%s (pid %d): %s (code %ld)\n",
256 current->comm, current->pid, str, err);
257
258 /* Wot's wrong wif bein' racy? */
259 if (current->thread.flags & PARISC_KERNEL_DEATH) {
260 printk(KERN_CRIT "%s() recursion detected.\n", __FUNCTION__);
261 local_irq_enable();
262 while (1);
263 }
264 current->thread.flags |= PARISC_KERNEL_DEATH;
265
247 show_regs(regs); 266 show_regs(regs);
267 dump_stack();
248 268
249 if (in_interrupt()) 269 if (in_interrupt())
250 panic("Fatal exception in interrupt"); 270 panic("Fatal exception in interrupt");
@@ -255,14 +275,6 @@ void die_if_kernel(char *str, struct pt_regs *regs, long err)
255 panic("Fatal exception"); 275 panic("Fatal exception");
256 } 276 }
257 277
258 /* Wot's wrong wif bein' racy? */
259 if (current->thread.flags & PARISC_KERNEL_DEATH) {
260 printk(KERN_CRIT "%s() recursion detected.\n", __FUNCTION__);
261 local_irq_enable();
262 while (1);
263 }
264
265 current->thread.flags |= PARISC_KERNEL_DEATH;
266 do_exit(SIGSEGV); 278 do_exit(SIGSEGV);
267} 279}
268 280
@@ -273,61 +285,45 @@ int syscall_ipi(int (*syscall) (struct pt_regs *), struct pt_regs *regs)
273 285
274/* gdb uses break 4,8 */ 286/* gdb uses break 4,8 */
275#define GDB_BREAK_INSN 0x10004 287#define GDB_BREAK_INSN 0x10004
276void handle_gdb_break(struct pt_regs *regs, int wot) 288static void handle_gdb_break(struct pt_regs *regs, int wot)
277{ 289{
278 struct siginfo si; 290 struct siginfo si;
279 291
280 si.si_code = wot;
281 si.si_addr = (void __user *) (regs->iaoq[0] & ~3);
282 si.si_signo = SIGTRAP; 292 si.si_signo = SIGTRAP;
283 si.si_errno = 0; 293 si.si_errno = 0;
294 si.si_code = wot;
295 si.si_addr = (void __user *) (regs->iaoq[0] & ~3);
284 force_sig_info(SIGTRAP, &si, current); 296 force_sig_info(SIGTRAP, &si, current);
285} 297}
286 298
287void handle_break(unsigned iir, struct pt_regs *regs) 299static void handle_break(struct pt_regs *regs)
288{ 300{
289 struct siginfo si; 301 unsigned iir = regs->iir;
290 302
291 switch(iir) { 303 if (unlikely(iir == PARISC_BUG_BREAK_INSN && !user_mode(regs))) {
292 case 0x00: 304 /* check if a BUG() or WARN() trapped here. */
293#ifdef PRINT_USER_FAULTS 305 enum bug_trap_type tt;
294 printk(KERN_DEBUG "break 0,0: pid=%d command='%s'\n", 306 tt = report_bug(regs->iaoq[0] & ~3);
295 current->pid, current->comm); 307 if (tt == BUG_TRAP_TYPE_WARN) {
296#endif 308 regs->iaoq[0] += 4;
297 die_if_kernel("Breakpoint", regs, 0); 309 regs->iaoq[1] += 4;
298#ifdef PRINT_USER_FAULTS 310 return; /* return to next instruction when WARN_ON(). */
299 show_regs(regs); 311 }
300#endif 312 die_if_kernel("Unknown kernel breakpoint", regs,
301 si.si_code = TRAP_BRKPT; 313 (tt == BUG_TRAP_TYPE_NONE) ? 9 : 0);
302 si.si_addr = (void __user *) (regs->iaoq[0] & ~3); 314 }
303 si.si_signo = SIGTRAP;
304 force_sig_info(SIGTRAP, &si, current);
305 break;
306
307 case GDB_BREAK_INSN:
308 die_if_kernel("Breakpoint", regs, 0);
309 handle_gdb_break(regs, TRAP_BRKPT);
310 break;
311 315
312 default:
313#ifdef PRINT_USER_FAULTS 316#ifdef PRINT_USER_FAULTS
314 printk(KERN_DEBUG "break %#08x: pid=%d command='%s'\n", 317 if (unlikely(iir != GDB_BREAK_INSN)) {
315 iir, current->pid, current->comm); 318 printk(KERN_DEBUG "break %d,%d: pid=%d command='%s'\n",
319 iir & 31, (iir>>13) & ((1<<13)-1),
320 current->pid, current->comm);
316 show_regs(regs); 321 show_regs(regs);
317#endif
318 si.si_signo = SIGTRAP;
319 si.si_code = TRAP_BRKPT;
320 si.si_addr = (void __user *) (regs->iaoq[0] & ~3);
321 force_sig_info(SIGTRAP, &si, current);
322 return;
323 } 322 }
324} 323#endif
325
326 324
327int handle_toc(void) 325 /* send standard GDB signal */
328{ 326 handle_gdb_break(regs, TRAP_BRKPT);
329 printk(KERN_CRIT "TOC call.\n");
330 return 0;
331} 327}
332 328
333static void default_trap(int code, struct pt_regs *regs) 329static void default_trap(int code, struct pt_regs *regs)
@@ -336,7 +332,7 @@ static void default_trap(int code, struct pt_regs *regs)
336 show_regs(regs); 332 show_regs(regs);
337} 333}
338 334
339void (*cpu_lpmc) (int code, struct pt_regs *regs) = default_trap; 335void (*cpu_lpmc) (int code, struct pt_regs *regs) __read_mostly = default_trap;
340 336
341 337
342void transfer_pim_to_trap_frame(struct pt_regs *regs) 338void transfer_pim_to_trap_frame(struct pt_regs *regs)
@@ -554,7 +550,8 @@ void handle_interruption(int code, struct pt_regs *regs)
554 /* Low-priority machine check */ 550 /* Low-priority machine check */
555 pdc_chassis_send_status(PDC_CHASSIS_DIRECT_LPMC); 551 pdc_chassis_send_status(PDC_CHASSIS_DIRECT_LPMC);
556 552
557 flush_all_caches(); 553 flush_cache_all();
554 flush_tlb_all();
558 cpu_lpmc(5, regs); 555 cpu_lpmc(5, regs);
559 return; 556 return;
560 557
@@ -572,7 +569,7 @@ void handle_interruption(int code, struct pt_regs *regs)
572 569
573 case 9: 570 case 9:
574 /* Break instruction trap */ 571 /* Break instruction trap */
575 handle_break(regs->iir,regs); 572 handle_break(regs);
576 return; 573 return;
577 574
578 case 10: 575 case 10:
@@ -840,7 +837,7 @@ int __init check_ivt(void *iva)
840 return 0; 837 return 0;
841} 838}
842 839
843#ifndef __LP64__ 840#ifndef CONFIG_64BIT
844extern const void fault_vector_11; 841extern const void fault_vector_11;
845#endif 842#endif
846extern const void fault_vector_20; 843extern const void fault_vector_20;
@@ -852,7 +849,7 @@ void __init trap_init(void)
852 if (boot_cpu_data.cpu_type >= pcxu) 849 if (boot_cpu_data.cpu_type >= pcxu)
853 iva = (void *) &fault_vector_20; 850 iva = (void *) &fault_vector_20;
854 else 851 else
855#ifdef __LP64__ 852#ifdef CONFIG_64BIT
856 panic("Can't boot 64-bit OS on PA1.1 processor!"); 853 panic("Can't boot 64-bit OS on PA1.1 processor!");
857#else 854#else
858 iva = (void *) &fault_vector_11; 855 iva = (void *) &fault_vector_11;