diff options
author | Stephen Rothwell <sfr@canb.auug.org.au> | 2005-10-01 04:43:42 -0400 |
---|---|---|
committer | Stephen Rothwell <sfr@canb.auug.org.au> | 2005-10-01 04:43:42 -0400 |
commit | dc1c1ca3dcd94c545c5e01d7c06b46824d43f4d0 (patch) | |
tree | fa088ac3eae8709dd379deda6f31d5b29197d4c9 /arch/powerpc/kernel/traps.c | |
parent | d96024c688b59d4d1e60dbb0e226964eb758aa01 (diff) |
powerpc: merge idle_power4.S and trapc.s
Use idle_power4.S from ppc64 as we are not going to support
32 bit power4 in the merged tree.
Merge ppc64 traps.c into powerpc traps.c:
use ppc64 versions of exception routine names
(as they don't have StudlyCaps)
make all the versions if die() have the same
prototype
Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
Diffstat (limited to 'arch/powerpc/kernel/traps.c')
-rw-r--r-- | arch/powerpc/kernel/traps.c | 407 |
1 files changed, 305 insertions, 102 deletions
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index c7afbbba0f36..37b961f1e279 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * arch/powerpc/kernel/traps.c | ||
3 | * | ||
4 | * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) | 2 | * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) |
5 | * | 3 | * |
6 | * This program is free software; you can redistribute it and/or | 4 | * This program is free software; you can redistribute it and/or |
@@ -23,29 +21,46 @@ | |||
23 | #include <linux/mm.h> | 21 | #include <linux/mm.h> |
24 | #include <linux/stddef.h> | 22 | #include <linux/stddef.h> |
25 | #include <linux/unistd.h> | 23 | #include <linux/unistd.h> |
26 | #include <linux/ptrace.h> | ||
27 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
28 | #include <linux/user.h> | 25 | #include <linux/user.h> |
29 | #include <linux/a.out.h> | 26 | #include <linux/a.out.h> |
30 | #include <linux/interrupt.h> | 27 | #include <linux/interrupt.h> |
31 | #include <linux/config.h> | ||
32 | #include <linux/init.h> | 28 | #include <linux/init.h> |
33 | #include <linux/module.h> | 29 | #include <linux/module.h> |
34 | #include <linux/prctl.h> | ||
35 | #include <linux/delay.h> | 30 | #include <linux/delay.h> |
36 | #include <linux/kprobes.h> | 31 | #include <linux/kprobes.h> |
37 | #include <asm/kdebug.h> | 32 | #include <asm/kdebug.h> |
33 | #ifdef CONFIG_PPC32 | ||
34 | #include <linux/ptrace.h> | ||
35 | #include <linux/prctl.h> | ||
36 | #endif | ||
38 | 37 | ||
39 | #include <asm/pgtable.h> | 38 | #include <asm/pgtable.h> |
40 | #include <asm/uaccess.h> | 39 | #include <asm/uaccess.h> |
41 | #include <asm/system.h> | 40 | #include <asm/system.h> |
42 | #include <asm/io.h> | 41 | #include <asm/io.h> |
42 | #ifdef CONFIG_PPC32 | ||
43 | #include <asm/reg.h> | 43 | #include <asm/reg.h> |
44 | #include <asm/xmon.h> | 44 | #include <asm/xmon.h> |
45 | #ifdef CONFIG_PMAC_BACKLIGHT | 45 | #ifdef CONFIG_PMAC_BACKLIGHT |
46 | #include <asm/backlight.h> | 46 | #include <asm/backlight.h> |
47 | #endif | 47 | #endif |
48 | #include <asm/perfmon.h> | 48 | #include <asm/perfmon.h> |
49 | #endif | ||
50 | #ifdef CONFIG_PPC64 | ||
51 | #include <asm/processor.h> | ||
52 | #include <asm/ppcdebug.h> | ||
53 | #include <asm/rtas.h> | ||
54 | #include <asm/systemcfg.h> | ||
55 | #include <asm/machdep.h> | ||
56 | #include <asm/pmc.h> | ||
57 | #endif | ||
58 | |||
59 | #ifdef CONFIG_PPC64 | ||
60 | #define __KPROBES __kprobes | ||
61 | #else | ||
62 | #define __KPROBES | ||
63 | #endif | ||
49 | 64 | ||
50 | #ifdef CONFIG_DEBUGGER | 65 | #ifdef CONFIG_DEBUGGER |
51 | int (*__debugger)(struct pt_regs *regs); | 66 | int (*__debugger)(struct pt_regs *regs); |
@@ -96,7 +111,7 @@ int die(const char *str, struct pt_regs *regs, long err) | |||
96 | console_verbose(); | 111 | console_verbose(); |
97 | spin_lock_irq(&die_lock); | 112 | spin_lock_irq(&die_lock); |
98 | bust_spinlocks(1); | 113 | bust_spinlocks(1); |
99 | #ifdef CONFIG_PMAC_BACKLIGHT | 114 | #if defined(CONFIG_PPC32) && defined(CONFIG_PMAC_BACKLIGHT) |
100 | if (_machine == _MACH_Pmac) { | 115 | if (_machine == _MACH_Pmac) { |
101 | set_backlight_enable(1); | 116 | set_backlight_enable(1); |
102 | set_backlight_level(BACKLIGHT_MAX); | 117 | set_backlight_level(BACKLIGHT_MAX); |
@@ -154,9 +169,17 @@ int die(const char *str, struct pt_regs *regs, long err) | |||
154 | panic("Fatal exception in interrupt"); | 169 | panic("Fatal exception in interrupt"); |
155 | 170 | ||
156 | if (panic_on_oops) { | 171 | if (panic_on_oops) { |
172 | #ifdef CONFIG_PPC64 | ||
173 | printk(KERN_EMERG "Fatal exception: panic in 5 seconds\n"); | ||
174 | ssleep(5); | ||
175 | #endif | ||
157 | panic("Fatal exception"); | 176 | panic("Fatal exception"); |
158 | } | 177 | } |
178 | #ifdef CONFIG_PPC32 | ||
159 | do_exit(err); | 179 | do_exit(err); |
180 | #else | ||
181 | do_exit(SIGSEGV); | ||
182 | #endif | ||
160 | 183 | ||
161 | return 0; | 184 | return 0; |
162 | } | 185 | } |
@@ -176,6 +199,7 @@ void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr) | |||
176 | info.si_addr = (void __user *) addr; | 199 | info.si_addr = (void __user *) addr; |
177 | force_sig_info(signr, &info, current); | 200 | force_sig_info(signr, &info, current); |
178 | 201 | ||
202 | #ifdef CONFIG_PPC32 | ||
179 | /* | 203 | /* |
180 | * Init gets no signals that it doesn't have a handler for. | 204 | * Init gets no signals that it doesn't have a handler for. |
181 | * That's all very well, but if it has caused a synchronous | 205 | * That's all very well, but if it has caused a synchronous |
@@ -197,6 +221,7 @@ void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr) | |||
197 | do_exit(signr); | 221 | do_exit(signr); |
198 | } | 222 | } |
199 | } | 223 | } |
224 | #endif | ||
200 | } | 225 | } |
201 | 226 | ||
202 | #ifdef CONFIG_PPC64 | 227 | #ifdef CONFIG_PPC64 |
@@ -206,7 +231,7 @@ void system_reset_exception(struct pt_regs *regs) | |||
206 | if (ppc_md.system_reset_exception) | 231 | if (ppc_md.system_reset_exception) |
207 | ppc_md.system_reset_exception(regs); | 232 | ppc_md.system_reset_exception(regs); |
208 | 233 | ||
209 | die("System Reset", regs, SIGABRT); | 234 | die("System Reset", regs, 0); |
210 | 235 | ||
211 | /* Must die if the interrupt is not recoverable */ | 236 | /* Must die if the interrupt is not recoverable */ |
212 | if (!(regs->msr & MSR_RI)) | 237 | if (!(regs->msr & MSR_RI)) |
@@ -216,6 +241,7 @@ void system_reset_exception(struct pt_regs *regs) | |||
216 | } | 241 | } |
217 | #endif | 242 | #endif |
218 | 243 | ||
244 | #ifdef CONFIG_PPC32 | ||
219 | /* | 245 | /* |
220 | * I/O accesses can cause machine checks on powermacs. | 246 | * I/O accesses can cause machine checks on powermacs. |
221 | * Check if the NIP corresponds to the address of a sync | 247 | * Check if the NIP corresponds to the address of a sync |
@@ -264,8 +290,10 @@ static inline int check_io_access(struct pt_regs *regs) | |||
264 | #endif /* CONFIG_PPC_PMAC */ | 290 | #endif /* CONFIG_PPC_PMAC */ |
265 | return 0; | 291 | return 0; |
266 | } | 292 | } |
293 | #endif /* CONFIG_PPC32 */ | ||
267 | 294 | ||
268 | #if defined(CONFIG_4xx) || defined(CONFIG_BOOKE) | 295 | #if defined(CONFIG_4xx) || defined(CONFIG_BOOKE) |
296 | |||
269 | /* On 4xx, the reason for the machine check or program exception | 297 | /* On 4xx, the reason for the machine check or program exception |
270 | is in the ESR. */ | 298 | is in the ESR. */ |
271 | #define get_reason(regs) ((regs)->dsisr) | 299 | #define get_reason(regs) ((regs)->dsisr) |
@@ -284,6 +312,7 @@ static inline int check_io_access(struct pt_regs *regs) | |||
284 | #define clear_single_step(regs) (current->thread.dbcr0 &= ~DBCR0_IC) | 312 | #define clear_single_step(regs) (current->thread.dbcr0 &= ~DBCR0_IC) |
285 | 313 | ||
286 | #else | 314 | #else |
315 | |||
287 | /* On non-4xx, the reason for the machine check or program | 316 | /* On non-4xx, the reason for the machine check or program |
288 | exception is in the MSR. */ | 317 | exception is in the MSR. */ |
289 | #define get_reason(regs) ((regs)->msr) | 318 | #define get_reason(regs) ((regs)->msr) |
@@ -297,6 +326,7 @@ static inline int check_io_access(struct pt_regs *regs) | |||
297 | #define clear_single_step(regs) ((regs)->msr &= ~MSR_SE) | 326 | #define clear_single_step(regs) ((regs)->msr &= ~MSR_SE) |
298 | #endif | 327 | #endif |
299 | 328 | ||
329 | #ifdef CONFIG_PPC32 | ||
300 | /* | 330 | /* |
301 | * This is "fall-back" implementation for configurations | 331 | * This is "fall-back" implementation for configurations |
302 | * which don't provide platform-specific machine check info | 332 | * which don't provide platform-specific machine check info |
@@ -305,8 +335,9 @@ void __attribute__ ((weak)) | |||
305 | platform_machine_check(struct pt_regs *regs) | 335 | platform_machine_check(struct pt_regs *regs) |
306 | { | 336 | { |
307 | } | 337 | } |
338 | #endif | ||
308 | 339 | ||
309 | void MachineCheckException(struct pt_regs *regs) | 340 | void machine_check_exception(struct pt_regs *regs) |
310 | { | 341 | { |
311 | #ifdef CONFIG_PPC64 | 342 | #ifdef CONFIG_PPC64 |
312 | int recover = 0; | 343 | int recover = 0; |
@@ -462,23 +493,31 @@ void MachineCheckException(struct pt_regs *regs) | |||
462 | * additional info, e.g. bus error registers. | 493 | * additional info, e.g. bus error registers. |
463 | */ | 494 | */ |
464 | platform_machine_check(regs); | 495 | platform_machine_check(regs); |
465 | #endif /* CONFIG_PPC64 */ | 496 | #endif /* CONFIG_PPC32 */ |
466 | 497 | ||
467 | if (debugger_fault_handler(regs)) | 498 | if (debugger_fault_handler(regs)) |
468 | return; | 499 | return; |
469 | die("Machine check", regs, SIGBUS); | 500 | die("Machine check", regs, |
501 | #ifdef CONFIG_PPC32 | ||
502 | SIGBUS | ||
503 | #else | ||
504 | 0 | ||
505 | #endif | ||
506 | ); | ||
470 | 507 | ||
471 | /* Must die if the interrupt is not recoverable */ | 508 | /* Must die if the interrupt is not recoverable */ |
472 | if (!(regs->msr & MSR_RI)) | 509 | if (!(regs->msr & MSR_RI)) |
473 | panic("Unrecoverable Machine check"); | 510 | panic("Unrecoverable Machine check"); |
474 | } | 511 | } |
475 | 512 | ||
513 | #ifdef CONFIG_PPC32 | ||
476 | void SMIException(struct pt_regs *regs) | 514 | void SMIException(struct pt_regs *regs) |
477 | { | 515 | { |
478 | die("System Management Interrupt", regs, SIGABRT); | 516 | die("System Management Interrupt", regs, SIGABRT); |
479 | } | 517 | } |
518 | #endif | ||
480 | 519 | ||
481 | void UnknownException(struct pt_regs *regs) | 520 | void unknown_exception(struct pt_regs *regs) |
482 | { | 521 | { |
483 | printk("Bad trap at PC: %lx, SR: %lx, vector=%lx\n", | 522 | printk("Bad trap at PC: %lx, SR: %lx, vector=%lx\n", |
484 | regs->nip, regs->msr, regs->trap); | 523 | regs->nip, regs->msr, regs->trap); |
@@ -486,7 +525,7 @@ void UnknownException(struct pt_regs *regs) | |||
486 | _exception(SIGTRAP, regs, 0, 0); | 525 | _exception(SIGTRAP, regs, 0, 0); |
487 | } | 526 | } |
488 | 527 | ||
489 | void InstructionBreakpoint(struct pt_regs *regs) | 528 | void instruction_breakpoint_exception(struct pt_regs *regs) |
490 | { | 529 | { |
491 | if (notify_die(DIE_IABR_MATCH, "iabr_match", regs, 5, | 530 | if (notify_die(DIE_IABR_MATCH, "iabr_match", regs, 5, |
492 | 5, SIGTRAP) == NOTIFY_STOP) | 531 | 5, SIGTRAP) == NOTIFY_STOP) |
@@ -496,14 +535,20 @@ void InstructionBreakpoint(struct pt_regs *regs) | |||
496 | _exception(SIGTRAP, regs, TRAP_BRKPT, regs->nip); | 535 | _exception(SIGTRAP, regs, TRAP_BRKPT, regs->nip); |
497 | } | 536 | } |
498 | 537 | ||
538 | #ifdef CONFIG_PPC32 | ||
499 | void RunModeException(struct pt_regs *regs) | 539 | void RunModeException(struct pt_regs *regs) |
500 | { | 540 | { |
501 | _exception(SIGTRAP, regs, 0, 0); | 541 | _exception(SIGTRAP, regs, 0, 0); |
502 | } | 542 | } |
543 | #endif | ||
503 | 544 | ||
504 | void SingleStepException(struct pt_regs *regs) | 545 | void __KPROBES single_step_exception(struct pt_regs *regs) |
505 | { | 546 | { |
547 | #ifdef CONFIG_PPC32 | ||
506 | regs->msr &= ~(MSR_SE | MSR_BE); /* Turn off 'trace' bits */ | 548 | regs->msr &= ~(MSR_SE | MSR_BE); /* Turn off 'trace' bits */ |
549 | #else | ||
550 | regs->msr &= ~MSR_SE; /* Turn off 'trace' bit */ | ||
551 | #endif | ||
507 | 552 | ||
508 | if (notify_die(DIE_SSTEP, "single_step", regs, 5, | 553 | if (notify_die(DIE_SSTEP, "single_step", regs, 5, |
509 | 5, SIGTRAP) == NOTIFY_STOP) | 554 | 5, SIGTRAP) == NOTIFY_STOP) |
@@ -520,15 +565,62 @@ void SingleStepException(struct pt_regs *regs) | |||
520 | * pretend we got a single-step exception. This was pointed out | 565 | * pretend we got a single-step exception. This was pointed out |
521 | * by Kumar Gala. -- paulus | 566 | * by Kumar Gala. -- paulus |
522 | */ | 567 | */ |
523 | static void emulate_single_step(struct pt_regs *regs) | 568 | static inline void emulate_single_step(struct pt_regs *regs) |
524 | { | 569 | { |
525 | if (single_stepping(regs)) { | 570 | if (single_stepping(regs)) { |
571 | #ifdef CONFIG_PPC32 | ||
526 | clear_single_step(regs); | 572 | clear_single_step(regs); |
527 | _exception(SIGTRAP, regs, TRAP_TRACE, 0); | 573 | _exception(SIGTRAP, regs, TRAP_TRACE, 0); |
574 | #else | ||
575 | single_step_exception(regs); | ||
576 | #endif | ||
528 | } | 577 | } |
529 | } | 578 | } |
530 | 579 | ||
531 | /* Illegal instruction emulation support. Originally written to | 580 | static void parse_fpe(struct pt_regs *regs) |
581 | { | ||
582 | int code = 0; | ||
583 | unsigned long fpscr; | ||
584 | |||
585 | #ifdef CONFIG_PPC32 | ||
586 | /* We must make sure the FP state is consistent with | ||
587 | * our MSR_FP in regs | ||
588 | */ | ||
589 | preempt_disable(); | ||
590 | if (regs->msr & MSR_FP) | ||
591 | giveup_fpu(current); | ||
592 | preempt_enable(); | ||
593 | #else | ||
594 | flush_fp_to_thread(current); | ||
595 | #endif | ||
596 | |||
597 | fpscr = current->thread.fpscr; | ||
598 | |||
599 | /* Invalid operation */ | ||
600 | if ((fpscr & FPSCR_VE) && (fpscr & FPSCR_VX)) | ||
601 | code = FPE_FLTINV; | ||
602 | |||
603 | /* Overflow */ | ||
604 | else if ((fpscr & FPSCR_OE) && (fpscr & FPSCR_OX)) | ||
605 | code = FPE_FLTOVF; | ||
606 | |||
607 | /* Underflow */ | ||
608 | else if ((fpscr & FPSCR_UE) && (fpscr & FPSCR_UX)) | ||
609 | code = FPE_FLTUND; | ||
610 | |||
611 | /* Divide by zero */ | ||
612 | else if ((fpscr & FPSCR_ZE) && (fpscr & FPSCR_ZX)) | ||
613 | code = FPE_FLTDIV; | ||
614 | |||
615 | /* Inexact result */ | ||
616 | else if ((fpscr & FPSCR_XE) && (fpscr & FPSCR_XX)) | ||
617 | code = FPE_FLTRES; | ||
618 | |||
619 | _exception(SIGFPE, regs, code, regs->nip); | ||
620 | } | ||
621 | |||
622 | /* | ||
623 | * Illegal instruction emulation support. Originally written to | ||
532 | * provide the PVR to user applications using the mfspr rd, PVR. | 624 | * provide the PVR to user applications using the mfspr rd, PVR. |
533 | * Return non-zero if we can't emulate, or -EFAULT if the associated | 625 | * Return non-zero if we can't emulate, or -EFAULT if the associated |
534 | * memory access caused an access fault. Return zero on success. | 626 | * memory access caused an access fault. Return zero on success. |
@@ -536,7 +628,6 @@ static void emulate_single_step(struct pt_regs *regs) | |||
536 | * There are a couple of ways to do this, either "decode" the instruction | 628 | * There are a couple of ways to do this, either "decode" the instruction |
537 | * or directly match lots of bits. In this case, matching lots of | 629 | * or directly match lots of bits. In this case, matching lots of |
538 | * bits is faster and easier. | 630 | * bits is faster and easier. |
539 | * | ||
540 | */ | 631 | */ |
541 | #define INST_MFSPR_PVR 0x7c1f42a6 | 632 | #define INST_MFSPR_PVR 0x7c1f42a6 |
542 | #define INST_MFSPR_PVR_MASK 0xfc1fffff | 633 | #define INST_MFSPR_PVR_MASK 0xfc1fffff |
@@ -547,6 +638,8 @@ static void emulate_single_step(struct pt_regs *regs) | |||
547 | #define INST_MCRXR 0x7c000400 | 638 | #define INST_MCRXR 0x7c000400 |
548 | #define INST_MCRXR_MASK 0x7c0007fe | 639 | #define INST_MCRXR_MASK 0x7c0007fe |
549 | 640 | ||
641 | #ifdef CONFIG_PPC32 | ||
642 | |||
550 | #define INST_STRING 0x7c00042a | 643 | #define INST_STRING 0x7c00042a |
551 | #define INST_STRING_MASK 0x7c0007fe | 644 | #define INST_STRING_MASK 0x7c0007fe |
552 | #define INST_STRING_GEN_MASK 0x7c00067e | 645 | #define INST_STRING_GEN_MASK 0x7c00067e |
@@ -622,6 +715,7 @@ static int emulate_string_inst(struct pt_regs *regs, u32 instword) | |||
622 | 715 | ||
623 | return 0; | 716 | return 0; |
624 | } | 717 | } |
718 | #endif /* CONFIG_PPC32 */ | ||
625 | 719 | ||
626 | static int emulate_instruction(struct pt_regs *regs) | 720 | static int emulate_instruction(struct pt_regs *regs) |
627 | { | 721 | { |
@@ -643,22 +737,44 @@ static int emulate_instruction(struct pt_regs *regs) | |||
643 | } | 737 | } |
644 | 738 | ||
645 | /* Emulating the dcba insn is just a no-op. */ | 739 | /* Emulating the dcba insn is just a no-op. */ |
646 | if ((instword & INST_DCBA_MASK) == INST_DCBA) | 740 | if ((instword & INST_DCBA_MASK) == INST_DCBA) { |
741 | #ifdef CONFIG_PPC64 | ||
742 | static int warned; | ||
743 | |||
744 | if (!warned) { | ||
745 | printk(KERN_WARNING | ||
746 | "process %d (%s) uses obsolete 'dcba' insn\n", | ||
747 | current->pid, current->comm); | ||
748 | warned = 1; | ||
749 | } | ||
750 | #endif /* CONFIG_PPC64 */ | ||
647 | return 0; | 751 | return 0; |
752 | } | ||
648 | 753 | ||
649 | /* Emulate the mcrxr insn. */ | 754 | /* Emulate the mcrxr insn. */ |
650 | if ((instword & INST_MCRXR_MASK) == INST_MCRXR) { | 755 | if ((instword & INST_MCRXR_MASK) == INST_MCRXR) { |
651 | int shift = (instword >> 21) & 0x1c; | 756 | unsigned int shift = (instword >> 21) & 0x1c; |
652 | unsigned long msk = 0xf0000000UL >> shift; | 757 | unsigned long msk = 0xf0000000UL >> shift; |
758 | #ifdef CONFIG_PPC64 | ||
759 | static int warned; | ||
653 | 760 | ||
761 | if (!warned) { | ||
762 | printk(KERN_WARNING | ||
763 | "process %d (%s) uses obsolete 'mcrxr' insn\n", | ||
764 | current->pid, current->comm); | ||
765 | warned = 1; | ||
766 | } | ||
767 | #endif | ||
654 | regs->ccr = (regs->ccr & ~msk) | ((regs->xer >> shift) & msk); | 768 | regs->ccr = (regs->ccr & ~msk) | ((regs->xer >> shift) & msk); |
655 | regs->xer &= ~0xf0000000UL; | 769 | regs->xer &= ~0xf0000000UL; |
656 | return 0; | 770 | return 0; |
657 | } | 771 | } |
658 | 772 | ||
773 | #ifdef CONFIG_PPC32 | ||
659 | /* Emulate load/store string insn. */ | 774 | /* Emulate load/store string insn. */ |
660 | if ((instword & INST_STRING_GEN_MASK) == INST_STRING) | 775 | if ((instword & INST_STRING_GEN_MASK) == INST_STRING) |
661 | return emulate_string_inst(regs, instword); | 776 | return emulate_string_inst(regs, instword); |
777 | #endif | ||
662 | 778 | ||
663 | return -EINVAL; | 779 | return -EINVAL; |
664 | } | 780 | } |
@@ -686,7 +802,7 @@ struct bug_entry *find_bug(unsigned long bugaddr) | |||
686 | return module_find_bug(bugaddr); | 802 | return module_find_bug(bugaddr); |
687 | } | 803 | } |
688 | 804 | ||
689 | int check_bug_trap(struct pt_regs *regs) | 805 | static int check_bug_trap(struct pt_regs *regs) |
690 | { | 806 | { |
691 | struct bug_entry *bug; | 807 | struct bug_entry *bug; |
692 | unsigned long addr; | 808 | unsigned long addr; |
@@ -701,34 +817,38 @@ int check_bug_trap(struct pt_regs *regs) | |||
701 | return 0; | 817 | return 0; |
702 | if (bug->line & BUG_WARNING_TRAP) { | 818 | if (bug->line & BUG_WARNING_TRAP) { |
703 | /* this is a WARN_ON rather than BUG/BUG_ON */ | 819 | /* this is a WARN_ON rather than BUG/BUG_ON */ |
704 | #ifdef CONFIG_XMON | 820 | #if defined(CONFIG_PPC32) && defined(CONFIG_XMON) |
705 | xmon_printf(KERN_ERR "Badness in %s at %s:%d\n", | 821 | xmon_printf(KERN_ERR "Badness in %s at %s:%d\n", |
706 | bug->function, bug->file, | 822 | bug->function, bug->file, |
707 | bug->line & ~BUG_WARNING_TRAP); | 823 | bug->line & ~BUG_WARNING_TRAP); |
708 | #endif /* CONFIG_XMON */ | 824 | #endif |
709 | printk(KERN_ERR "Badness in %s at %s:%d\n", | 825 | printk(KERN_ERR "Badness in %s at %s:%d\n", |
710 | bug->function, bug->file, | 826 | bug->function, bug->file, |
711 | bug->line & ~BUG_WARNING_TRAP); | 827 | bug->line & ~BUG_WARNING_TRAP); |
828 | #ifdef CONFIG_PPC32 | ||
712 | dump_stack(); | 829 | dump_stack(); |
830 | #else | ||
831 | show_stack(current, (void *)regs->gpr[1]); | ||
832 | #endif | ||
713 | return 1; | 833 | return 1; |
714 | } | 834 | } |
715 | #ifdef CONFIG_XMON | 835 | #if defined(CONFIG_PPC32) && defined(CONFIG_XMON) |
716 | xmon_printf(KERN_CRIT "kernel BUG in %s at %s:%d!\n", | 836 | xmon_printf(KERN_CRIT "kernel BUG in %s at %s:%d!\n", |
717 | bug->function, bug->file, bug->line); | 837 | bug->function, bug->file, bug->line); |
718 | xmon(regs); | 838 | xmon(regs); |
719 | #endif /* CONFIG_XMON */ | 839 | #endif |
720 | printk(KERN_CRIT "kernel BUG in %s at %s:%d!\n", | 840 | printk(KERN_CRIT "kernel BUG in %s at %s:%d!\n", |
721 | bug->function, bug->file, bug->line); | 841 | bug->function, bug->file, bug->line); |
722 | 842 | ||
723 | return 0; | 843 | return 0; |
724 | } | 844 | } |
725 | 845 | ||
726 | void ProgramCheckException(struct pt_regs *regs) | 846 | void __KPROBES program_check_exception(struct pt_regs *regs) |
727 | { | 847 | { |
728 | unsigned int reason = get_reason(regs); | 848 | unsigned int reason = get_reason(regs); |
849 | #if defined(CONFIG_PPC32) && defined(CONFIG_MATH_EMULATION) | ||
729 | extern int do_mathemu(struct pt_regs *regs); | 850 | extern int do_mathemu(struct pt_regs *regs); |
730 | 851 | ||
731 | #ifdef CONFIG_MATH_EMULATION | ||
732 | /* (reason & REASON_ILLEGAL) would be the obvious thing here, | 852 | /* (reason & REASON_ILLEGAL) would be the obvious thing here, |
733 | * but there seems to be a hardware bug on the 405GP (RevD) | 853 | * but there seems to be a hardware bug on the 405GP (RevD) |
734 | * that means ESR is sometimes set incorrectly - either to | 854 | * that means ESR is sometimes set incorrectly - either to |
@@ -740,69 +860,61 @@ void ProgramCheckException(struct pt_regs *regs) | |||
740 | emulate_single_step(regs); | 860 | emulate_single_step(regs); |
741 | return; | 861 | return; |
742 | } | 862 | } |
743 | #endif /* CONFIG_MATH_EMULATION */ | 863 | #endif |
744 | |||
745 | if (reason & REASON_FP) { | ||
746 | /* IEEE FP exception */ | ||
747 | int code = 0; | ||
748 | u32 fpscr; | ||
749 | 864 | ||
750 | /* We must make sure the FP state is consistent with | 865 | #ifdef CONFIG_PPC64 |
751 | * our MSR_FP in regs | 866 | if (debugger_fault_handler(regs)) |
752 | */ | ||
753 | preempt_disable(); | ||
754 | if (regs->msr & MSR_FP) | ||
755 | giveup_fpu(current); | ||
756 | preempt_enable(); | ||
757 | |||
758 | fpscr = current->thread.fpscr; | ||
759 | fpscr &= fpscr << 22; /* mask summary bits with enables */ | ||
760 | if (fpscr & FPSCR_VX) | ||
761 | code = FPE_FLTINV; | ||
762 | else if (fpscr & FPSCR_OX) | ||
763 | code = FPE_FLTOVF; | ||
764 | else if (fpscr & FPSCR_UX) | ||
765 | code = FPE_FLTUND; | ||
766 | else if (fpscr & FPSCR_ZX) | ||
767 | code = FPE_FLTDIV; | ||
768 | else if (fpscr & FPSCR_XX) | ||
769 | code = FPE_FLTRES; | ||
770 | _exception(SIGFPE, regs, code, regs->nip); | ||
771 | return; | 867 | return; |
772 | } | 868 | #endif |
773 | 869 | ||
774 | if (reason & REASON_TRAP) { | 870 | if (reason & REASON_FP) { |
871 | /* IEEE FP exception */ | ||
872 | parse_fpe(regs); | ||
873 | } else if (reason & REASON_TRAP) { | ||
775 | /* trap exception */ | 874 | /* trap exception */ |
875 | #ifdef CONFIG_PPC64 | ||
876 | if (notify_die(DIE_BPT, "breakpoint", regs, 5, 5, SIGTRAP) | ||
877 | == NOTIFY_STOP) | ||
878 | return; | ||
879 | #endif | ||
776 | if (debugger_bpt(regs)) | 880 | if (debugger_bpt(regs)) |
777 | return; | 881 | return; |
778 | if (check_bug_trap(regs)) { | 882 | if (check_bug_trap(regs)) { |
779 | regs->nip += 4; | 883 | regs->nip += 4; |
780 | return; | 884 | return; |
781 | } | 885 | } |
782 | _exception(SIGTRAP, regs, TRAP_BRKPT, 0); | 886 | _exception(SIGTRAP, regs, TRAP_BRKPT, |
783 | return; | 887 | #ifdef CONFIG_PPC32 |
784 | } | 888 | 0 |
785 | 889 | #else | |
786 | /* Try to emulate it if we should. */ | 890 | regs->nip |
787 | if (reason & (REASON_ILLEGAL | REASON_PRIVILEGED)) { | 891 | #endif |
892 | ); | ||
893 | } else | ||
894 | #ifdef CONFIG_PPC32 | ||
895 | if (reason & (REASON_ILLEGAL | REASON_PRIVILEGED)) | ||
896 | #endif | ||
897 | { | ||
898 | /* Privileged or illegal instruction; try to emulate it. */ | ||
788 | switch (emulate_instruction(regs)) { | 899 | switch (emulate_instruction(regs)) { |
789 | case 0: | 900 | case 0: |
790 | regs->nip += 4; | 901 | regs->nip += 4; |
791 | emulate_single_step(regs); | 902 | emulate_single_step(regs); |
792 | return; | 903 | break; |
793 | case -EFAULT: | 904 | case -EFAULT: |
794 | _exception(SIGSEGV, regs, SEGV_MAPERR, regs->nip); | 905 | _exception(SIGSEGV, regs, SEGV_MAPERR, regs->nip); |
795 | return; | 906 | break; |
907 | default: | ||
908 | if (reason & REASON_PRIVILEGED) | ||
909 | _exception(SIGILL, regs, ILL_PRVOPC, regs->nip); | ||
910 | else | ||
911 | _exception(SIGILL, regs, ILL_ILLOPC, regs->nip); | ||
912 | break; | ||
796 | } | 913 | } |
797 | } | 914 | } |
798 | |||
799 | if (reason & REASON_PRIVILEGED) | ||
800 | _exception(SIGILL, regs, ILL_PRVOPC, regs->nip); | ||
801 | else | ||
802 | _exception(SIGILL, regs, ILL_ILLOPC, regs->nip); | ||
803 | } | 915 | } |
804 | 916 | ||
805 | void AlignmentException(struct pt_regs *regs) | 917 | void alignment_exception(struct pt_regs *regs) |
806 | { | 918 | { |
807 | int fixed; | 919 | int fixed; |
808 | 920 | ||
@@ -814,18 +926,31 @@ void AlignmentException(struct pt_regs *regs) | |||
814 | return; | 926 | return; |
815 | } | 927 | } |
816 | 928 | ||
817 | /* Operand address was bad */ | 929 | /* Operand address was bad */ |
818 | if (fixed == -EFAULT) { | 930 | if (fixed == -EFAULT) { |
819 | if (user_mode(regs)) | 931 | if (user_mode(regs)) |
820 | _exception(SIGSEGV, regs, SEGV_ACCERR, regs->dar); | 932 | _exception(SIGSEGV, regs, |
933 | #ifdef CONFIG_PPC32 | ||
934 | SEGV_ACCERR, | ||
935 | #else | ||
936 | SEGV_MAPERR, | ||
937 | #endif | ||
938 | regs->dar); | ||
821 | else | 939 | else |
822 | /* Search exception table */ | 940 | /* Search exception table */ |
823 | bad_page_fault(regs, regs->dar, SIGSEGV); | 941 | bad_page_fault(regs, regs->dar, SIGSEGV); |
824 | return; | 942 | return; |
825 | } | 943 | } |
826 | _exception(SIGBUS, regs, BUS_ADRALN, regs->dar); | 944 | _exception(SIGBUS, regs, BUS_ADRALN, |
945 | #ifdef CONFIG_PPC32 | ||
946 | regs->dar | ||
947 | #else | ||
948 | regs->nip | ||
949 | #endif | ||
950 | ); | ||
827 | } | 951 | } |
828 | 952 | ||
953 | #ifdef CONFIG_PPC32 | ||
829 | void StackOverflow(struct pt_regs *regs) | 954 | void StackOverflow(struct pt_regs *regs) |
830 | { | 955 | { |
831 | printk(KERN_CRIT "Kernel stack overflow in process %p, r1=%lx\n", | 956 | printk(KERN_CRIT "Kernel stack overflow in process %p, r1=%lx\n", |
@@ -849,8 +974,58 @@ void trace_syscall(struct pt_regs *regs) | |||
849 | current, current->pid, regs->nip, regs->link, regs->gpr[0], | 974 | current, current->pid, regs->nip, regs->link, regs->gpr[0], |
850 | regs->ccr&0x10000000?"Error=":"", regs->gpr[3], print_tainted()); | 975 | regs->ccr&0x10000000?"Error=":"", regs->gpr[3], print_tainted()); |
851 | } | 976 | } |
977 | #endif /* CONFIG_PPC32 */ | ||
978 | |||
979 | #ifdef CONFIG_PPC64 | ||
980 | void kernel_fp_unavailable_exception(struct pt_regs *regs) | ||
981 | { | ||
982 | printk(KERN_EMERG "Unrecoverable FP Unavailable Exception " | ||
983 | "%lx at %lx\n", regs->trap, regs->nip); | ||
984 | die("Unrecoverable FP Unavailable Exception", regs, SIGABRT); | ||
985 | } | ||
986 | #endif | ||
987 | |||
988 | void altivec_unavailable_exception(struct pt_regs *regs) | ||
989 | { | ||
990 | #if !defined(CONFIG_ALTIVEC) || defined(CONFIG_PPC64) | ||
991 | if (user_mode(regs)) { | ||
992 | /* A user program has executed an altivec instruction, | ||
993 | but this kernel doesn't support altivec. */ | ||
994 | _exception(SIGILL, regs, ILL_ILLOPC, regs->nip); | ||
995 | return; | ||
996 | } | ||
997 | #endif | ||
998 | #ifdef CONFIG_PPC32 | ||
999 | { | ||
1000 | static int kernel_altivec_count; | ||
1001 | |||
1002 | /* The kernel has executed an altivec instruction without | ||
1003 | first enabling altivec. Whinge but let it do it. */ | ||
1004 | if (++kernel_altivec_count < 10) | ||
1005 | printk(KERN_ERR "AltiVec used in kernel (task=%p, pc=%lx)\n", | ||
1006 | current, regs->nip); | ||
1007 | regs->msr |= MSR_VEC; | ||
1008 | } | ||
1009 | #else | ||
1010 | printk(KERN_EMERG "Unrecoverable VMX/Altivec Unavailable Exception " | ||
1011 | "%lx at %lx\n", regs->trap, regs->nip); | ||
1012 | die("Unrecoverable VMX/Altivec Unavailable Exception", regs, SIGABRT); | ||
1013 | #endif | ||
1014 | } | ||
1015 | |||
1016 | #ifdef CONFIG_PPC64 | ||
1017 | extern perf_irq_t perf_irq; | ||
1018 | #endif | ||
1019 | |||
1020 | #if defined(CONFIG_PPC64) || defined(CONFIG_E500) | ||
1021 | void performance_monitor_exception(struct pt_regs *regs) | ||
1022 | { | ||
1023 | perf_irq(regs); | ||
1024 | } | ||
1025 | #endif | ||
1026 | |||
852 | 1027 | ||
853 | #ifdef CONFIG_8xx | 1028 | #if defined(CONFIG_PPC32) && defined(CONFIG_8xx) |
854 | void SoftwareEmulation(struct pt_regs *regs) | 1029 | void SoftwareEmulation(struct pt_regs *regs) |
855 | { | 1030 | { |
856 | extern int do_mathemu(struct pt_regs *); | 1031 | extern int do_mathemu(struct pt_regs *); |
@@ -879,8 +1054,9 @@ void SoftwareEmulation(struct pt_regs *regs) | |||
879 | } else | 1054 | } else |
880 | emulate_single_step(regs); | 1055 | emulate_single_step(regs); |
881 | } | 1056 | } |
882 | #endif /* CONFIG_8xx */ | 1057 | #endif /* defined(CONFIG_PPC32) && defined(CONFIG_8xx) */ |
883 | 1058 | ||
1059 | #ifdef CONFIG_PPC32 | ||
884 | #if defined(CONFIG_40x) || defined(CONFIG_BOOKE) | 1060 | #if defined(CONFIG_40x) || defined(CONFIG_BOOKE) |
885 | 1061 | ||
886 | void DebugException(struct pt_regs *regs, unsigned long debug_status) | 1062 | void DebugException(struct pt_regs *regs, unsigned long debug_status) |
@@ -909,42 +1085,36 @@ void TAUException(struct pt_regs *regs) | |||
909 | regs->nip, regs->msr, regs->trap, print_tainted()); | 1085 | regs->nip, regs->msr, regs->trap, print_tainted()); |
910 | } | 1086 | } |
911 | #endif /* CONFIG_INT_TAU */ | 1087 | #endif /* CONFIG_INT_TAU */ |
912 | 1088 | #endif /* CONFIG_PPC32*/ | |
913 | void AltivecUnavailException(struct pt_regs *regs) | ||
914 | { | ||
915 | static int kernel_altivec_count; | ||
916 | |||
917 | #ifndef CONFIG_ALTIVEC | ||
918 | if (user_mode(regs)) { | ||
919 | /* A user program has executed an altivec instruction, | ||
920 | but this kernel doesn't support altivec. */ | ||
921 | _exception(SIGILL, regs, ILL_ILLOPC, regs->nip); | ||
922 | return; | ||
923 | } | ||
924 | #endif | ||
925 | /* The kernel has executed an altivec instruction without | ||
926 | first enabling altivec. Whinge but let it do it. */ | ||
927 | if (++kernel_altivec_count < 10) | ||
928 | printk(KERN_ERR "AltiVec used in kernel (task=%p, pc=%lx)\n", | ||
929 | current, regs->nip); | ||
930 | regs->msr |= MSR_VEC; | ||
931 | } | ||
932 | 1089 | ||
933 | #ifdef CONFIG_ALTIVEC | 1090 | #ifdef CONFIG_ALTIVEC |
934 | void AltivecAssistException(struct pt_regs *regs) | 1091 | void altivec_assist_exception(struct pt_regs *regs) |
935 | { | 1092 | { |
936 | int err; | 1093 | int err; |
1094 | #ifdef CONFIG_PPC64 | ||
1095 | siginfo_t info; | ||
1096 | #endif | ||
937 | 1097 | ||
1098 | #ifdef CONFIG_PPC32 | ||
938 | preempt_disable(); | 1099 | preempt_disable(); |
939 | if (regs->msr & MSR_VEC) | 1100 | if (regs->msr & MSR_VEC) |
940 | giveup_altivec(current); | 1101 | giveup_altivec(current); |
941 | preempt_enable(); | 1102 | preempt_enable(); |
1103 | #endif | ||
942 | if (!user_mode(regs)) { | 1104 | if (!user_mode(regs)) { |
943 | printk(KERN_EMERG "VMX/Altivec assist exception in kernel mode" | 1105 | printk(KERN_EMERG "VMX/Altivec assist exception in kernel mode" |
944 | " at %lx\n", regs->nip); | 1106 | " at %lx\n", regs->nip); |
945 | die("Kernel Altivec assist exception", regs, SIGILL); | 1107 | die("Kernel " |
1108 | #ifdef CONFIG_PPC64 | ||
1109 | "VMX/" | ||
1110 | #endif | ||
1111 | "Altivec assist exception", regs, SIGILL); | ||
946 | } | 1112 | } |
947 | 1113 | ||
1114 | #ifdef CONFIG_PPC64 | ||
1115 | flush_altivec_to_thread(current); | ||
1116 | #endif /* CONFIG_PPC64 */ | ||
1117 | |||
948 | err = emulate_altivec(regs); | 1118 | err = emulate_altivec(regs); |
949 | if (err == 0) { | 1119 | if (err == 0) { |
950 | regs->nip += 4; /* skip emulated instruction */ | 1120 | regs->nip += 4; /* skip emulated instruction */ |
@@ -954,7 +1124,15 @@ void AltivecAssistException(struct pt_regs *regs) | |||
954 | 1124 | ||
955 | if (err == -EFAULT) { | 1125 | if (err == -EFAULT) { |
956 | /* got an error reading the instruction */ | 1126 | /* got an error reading the instruction */ |
1127 | #ifdef CONFIG_PPC32 | ||
957 | _exception(SIGSEGV, regs, SEGV_ACCERR, regs->nip); | 1128 | _exception(SIGSEGV, regs, SEGV_ACCERR, regs->nip); |
1129 | #else | ||
1130 | info.si_signo = SIGSEGV; | ||
1131 | info.si_errno = 0; | ||
1132 | info.si_code = SEGV_MAPERR; | ||
1133 | info.si_addr = (void __user *) regs->nip; | ||
1134 | force_sig_info(SIGSEGV, &info, current); | ||
1135 | #endif | ||
958 | } else { | 1136 | } else { |
959 | /* didn't recognize the instruction */ | 1137 | /* didn't recognize the instruction */ |
960 | /* XXX quick hack for now: set the non-Java bit in the VSCR */ | 1138 | /* XXX quick hack for now: set the non-Java bit in the VSCR */ |
@@ -966,13 +1144,7 @@ void AltivecAssistException(struct pt_regs *regs) | |||
966 | } | 1144 | } |
967 | #endif /* CONFIG_ALTIVEC */ | 1145 | #endif /* CONFIG_ALTIVEC */ |
968 | 1146 | ||
969 | #ifdef CONFIG_E500 | 1147 | #ifdef CONFIG_PPC32 |
970 | void PerformanceMonitorException(struct pt_regs *regs) | ||
971 | { | ||
972 | perf_irq(regs); | ||
973 | } | ||
974 | #endif | ||
975 | |||
976 | #ifdef CONFIG_FSL_BOOKE | 1148 | #ifdef CONFIG_FSL_BOOKE |
977 | void CacheLockingException(struct pt_regs *regs, unsigned long address, | 1149 | void CacheLockingException(struct pt_regs *regs, unsigned long address, |
978 | unsigned long error_code) | 1150 | unsigned long error_code) |
@@ -1022,7 +1194,24 @@ void SPEFloatingPointException(struct pt_regs *regs) | |||
1022 | return; | 1194 | return; |
1023 | } | 1195 | } |
1024 | #endif | 1196 | #endif |
1197 | #endif /* CONFIG_PPC32 */ | ||
1025 | 1198 | ||
1199 | #ifdef CONFIG_PPC64 | ||
1200 | /* | ||
1201 | * We enter here if we get an unrecoverable exception, that is, one | ||
1202 | * that happened at a point where the RI (recoverable interrupt) bit | ||
1203 | * in the MSR is 0. This indicates that SRR0/1 are live, and that | ||
1204 | * we therefore lost state by taking this exception. | ||
1205 | */ | ||
1206 | void unrecoverable_exception(struct pt_regs *regs) | ||
1207 | { | ||
1208 | printk(KERN_EMERG "Unrecoverable exception %lx at %lx\n", | ||
1209 | regs->trap, regs->nip); | ||
1210 | die("Unrecoverable exception", regs, SIGABRT); | ||
1211 | } | ||
1212 | #endif /* CONFIG_PPC64 */ | ||
1213 | |||
1214 | #ifdef CONFIG_PPC32 | ||
1026 | #ifdef CONFIG_BOOKE_WDT | 1215 | #ifdef CONFIG_BOOKE_WDT |
1027 | /* | 1216 | /* |
1028 | * Default handler for a Watchdog exception, | 1217 | * Default handler for a Watchdog exception, |
@@ -1041,6 +1230,20 @@ void WatchdogException(struct pt_regs *regs) | |||
1041 | WatchdogHandler(regs); | 1230 | WatchdogHandler(regs); |
1042 | } | 1231 | } |
1043 | #endif | 1232 | #endif |
1233 | #endif /* CONFIG_PPC32 */ | ||
1234 | |||
1235 | #ifdef CONFIG_PPC64 | ||
1236 | /* | ||
1237 | * We enter here if we discover during exception entry that we are | ||
1238 | * running in supervisor mode with a userspace value in the stack pointer. | ||
1239 | */ | ||
1240 | void kernel_bad_stack(struct pt_regs *regs) | ||
1241 | { | ||
1242 | printk(KERN_EMERG "Bad kernel stack pointer %lx at %lx\n", | ||
1243 | regs->gpr[1], regs->nip); | ||
1244 | die("Bad kernel stack pointer", regs, SIGABRT); | ||
1245 | } | ||
1246 | #endif | ||
1044 | 1247 | ||
1045 | void __init trap_init(void) | 1248 | void __init trap_init(void) |
1046 | { | 1249 | { |