diff options
author | Paul Mackerras <paulus@samba.org> | 2005-10-05 23:27:05 -0400 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2005-10-05 23:27:05 -0400 |
commit | 8dad3f9257414f151cd821bfe01f54d7f52d2507 (patch) | |
tree | 2d9d5285eda91bbfbf3acf6f7f550ca69abfb985 /arch/powerpc | |
parent | b3491269f5604e4265ee2f27b47a76ce1e3678b6 (diff) |
powerpc: Merge traps.c a bit more
This reduces the differences between ppc32 and ppc64 in
arch/powerpc/kernel/traps.c a bit further.
Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc')
-rw-r--r-- | arch/powerpc/kernel/head.S | 2 | ||||
-rw-r--r-- | arch/powerpc/kernel/traps.c | 192 |
2 files changed, 35 insertions, 159 deletions
diff --git a/arch/powerpc/kernel/head.S b/arch/powerpc/kernel/head.S index 276793e05fd0..d9dbbd426744 100644 --- a/arch/powerpc/kernel/head.S +++ b/arch/powerpc/kernel/head.S | |||
@@ -416,7 +416,7 @@ FPUnavailable: | |||
416 | EXCEPTION_PROLOG | 416 | EXCEPTION_PROLOG |
417 | bne load_up_fpu /* if from user, just load it up */ | 417 | bne load_up_fpu /* if from user, just load it up */ |
418 | addi r3,r1,STACK_FRAME_OVERHEAD | 418 | addi r3,r1,STACK_FRAME_OVERHEAD |
419 | EXC_XFER_EE_LITE(0x800, KernelFP) | 419 | EXC_XFER_EE_LITE(0x800, kernel_fp_unavailable_exception) |
420 | 420 | ||
421 | /* Decrementer */ | 421 | /* Decrementer */ |
422 | EXCEPTION(0x900, Decrementer, timer_interrupt, EXC_XFER_LITE) | 422 | EXCEPTION(0x900, Decrementer, timer_interrupt, EXC_XFER_LITE) |
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 37b961f1e279..a2e4ad3f5a75 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c | |||
@@ -21,19 +21,17 @@ | |||
21 | #include <linux/mm.h> | 21 | #include <linux/mm.h> |
22 | #include <linux/stddef.h> | 22 | #include <linux/stddef.h> |
23 | #include <linux/unistd.h> | 23 | #include <linux/unistd.h> |
24 | #include <linux/ptrace.h> | ||
24 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
25 | #include <linux/user.h> | 26 | #include <linux/user.h> |
26 | #include <linux/a.out.h> | 27 | #include <linux/a.out.h> |
27 | #include <linux/interrupt.h> | 28 | #include <linux/interrupt.h> |
28 | #include <linux/init.h> | 29 | #include <linux/init.h> |
29 | #include <linux/module.h> | 30 | #include <linux/module.h> |
31 | #include <linux/prctl.h> | ||
30 | #include <linux/delay.h> | 32 | #include <linux/delay.h> |
31 | #include <linux/kprobes.h> | 33 | #include <linux/kprobes.h> |
32 | #include <asm/kdebug.h> | 34 | #include <asm/kdebug.h> |
33 | #ifdef CONFIG_PPC32 | ||
34 | #include <linux/ptrace.h> | ||
35 | #include <linux/prctl.h> | ||
36 | #endif | ||
37 | 35 | ||
38 | #include <asm/pgtable.h> | 36 | #include <asm/pgtable.h> |
39 | #include <asm/uaccess.h> | 37 | #include <asm/uaccess.h> |
@@ -56,12 +54,6 @@ | |||
56 | #include <asm/pmc.h> | 54 | #include <asm/pmc.h> |
57 | #endif | 55 | #endif |
58 | 56 | ||
59 | #ifdef CONFIG_PPC64 | ||
60 | #define __KPROBES __kprobes | ||
61 | #else | ||
62 | #define __KPROBES | ||
63 | #endif | ||
64 | |||
65 | #ifdef CONFIG_DEBUGGER | 57 | #ifdef CONFIG_DEBUGGER |
66 | int (*__debugger)(struct pt_regs *regs); | 58 | int (*__debugger)(struct pt_regs *regs); |
67 | int (*__debugger_ipi)(struct pt_regs *regs); | 59 | int (*__debugger_ipi)(struct pt_regs *regs); |
@@ -111,7 +103,7 @@ int die(const char *str, struct pt_regs *regs, long err) | |||
111 | console_verbose(); | 103 | console_verbose(); |
112 | spin_lock_irq(&die_lock); | 104 | spin_lock_irq(&die_lock); |
113 | bust_spinlocks(1); | 105 | bust_spinlocks(1); |
114 | #if defined(CONFIG_PPC32) && defined(CONFIG_PMAC_BACKLIGHT) | 106 | #ifdef CONFIG_PMAC_BACKLIGHT |
115 | if (_machine == _MACH_Pmac) { | 107 | if (_machine == _MACH_Pmac) { |
116 | set_backlight_enable(1); | 108 | set_backlight_enable(1); |
117 | set_backlight_level(BACKLIGHT_MAX); | 109 | set_backlight_level(BACKLIGHT_MAX); |
@@ -175,11 +167,7 @@ int die(const char *str, struct pt_regs *regs, long err) | |||
175 | #endif | 167 | #endif |
176 | panic("Fatal exception"); | 168 | panic("Fatal exception"); |
177 | } | 169 | } |
178 | #ifdef CONFIG_PPC32 | ||
179 | do_exit(err); | 170 | do_exit(err); |
180 | #else | ||
181 | do_exit(SIGSEGV); | ||
182 | #endif | ||
183 | 171 | ||
184 | return 0; | 172 | return 0; |
185 | } | 173 | } |
@@ -199,7 +187,6 @@ void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr) | |||
199 | info.si_addr = (void __user *) addr; | 187 | info.si_addr = (void __user *) addr; |
200 | force_sig_info(signr, &info, current); | 188 | force_sig_info(signr, &info, current); |
201 | 189 | ||
202 | #ifdef CONFIG_PPC32 | ||
203 | /* | 190 | /* |
204 | * Init gets no signals that it doesn't have a handler for. | 191 | * Init gets no signals that it doesn't have a handler for. |
205 | * That's all very well, but if it has caused a synchronous | 192 | * That's all very well, but if it has caused a synchronous |
@@ -221,7 +208,6 @@ void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr) | |||
221 | do_exit(signr); | 208 | do_exit(signr); |
222 | } | 209 | } |
223 | } | 210 | } |
224 | #endif | ||
225 | } | 211 | } |
226 | 212 | ||
227 | #ifdef CONFIG_PPC64 | 213 | #ifdef CONFIG_PPC64 |
@@ -231,7 +217,7 @@ void system_reset_exception(struct pt_regs *regs) | |||
231 | if (ppc_md.system_reset_exception) | 217 | if (ppc_md.system_reset_exception) |
232 | ppc_md.system_reset_exception(regs); | 218 | ppc_md.system_reset_exception(regs); |
233 | 219 | ||
234 | die("System Reset", regs, 0); | 220 | die("System Reset", regs, SIGABRT); |
235 | 221 | ||
236 | /* Must die if the interrupt is not recoverable */ | 222 | /* Must die if the interrupt is not recoverable */ |
237 | if (!(regs->msr & MSR_RI)) | 223 | if (!(regs->msr & MSR_RI)) |
@@ -241,7 +227,6 @@ void system_reset_exception(struct pt_regs *regs) | |||
241 | } | 227 | } |
242 | #endif | 228 | #endif |
243 | 229 | ||
244 | #ifdef CONFIG_PPC32 | ||
245 | /* | 230 | /* |
246 | * I/O accesses can cause machine checks on powermacs. | 231 | * I/O accesses can cause machine checks on powermacs. |
247 | * Check if the NIP corresponds to the address of a sync | 232 | * Check if the NIP corresponds to the address of a sync |
@@ -290,7 +275,6 @@ static inline int check_io_access(struct pt_regs *regs) | |||
290 | #endif /* CONFIG_PPC_PMAC */ | 275 | #endif /* CONFIG_PPC_PMAC */ |
291 | return 0; | 276 | return 0; |
292 | } | 277 | } |
293 | #endif /* CONFIG_PPC32 */ | ||
294 | 278 | ||
295 | #if defined(CONFIG_4xx) || defined(CONFIG_BOOKE) | 279 | #if defined(CONFIG_4xx) || defined(CONFIG_BOOKE) |
296 | 280 | ||
@@ -326,7 +310,6 @@ static inline int check_io_access(struct pt_regs *regs) | |||
326 | #define clear_single_step(regs) ((regs)->msr &= ~MSR_SE) | 310 | #define clear_single_step(regs) ((regs)->msr &= ~MSR_SE) |
327 | #endif | 311 | #endif |
328 | 312 | ||
329 | #ifdef CONFIG_PPC32 | ||
330 | /* | 313 | /* |
331 | * This is "fall-back" implementation for configurations | 314 | * This is "fall-back" implementation for configurations |
332 | * which don't provide platform-specific machine check info | 315 | * which don't provide platform-specific machine check info |
@@ -335,7 +318,6 @@ void __attribute__ ((weak)) | |||
335 | platform_machine_check(struct pt_regs *regs) | 318 | platform_machine_check(struct pt_regs *regs) |
336 | { | 319 | { |
337 | } | 320 | } |
338 | #endif | ||
339 | 321 | ||
340 | void machine_check_exception(struct pt_regs *regs) | 322 | void machine_check_exception(struct pt_regs *regs) |
341 | { | 323 | { |
@@ -497,13 +479,7 @@ void machine_check_exception(struct pt_regs *regs) | |||
497 | 479 | ||
498 | if (debugger_fault_handler(regs)) | 480 | if (debugger_fault_handler(regs)) |
499 | return; | 481 | return; |
500 | die("Machine check", regs, | 482 | die("Machine check", regs, SIGBUS); |
501 | #ifdef CONFIG_PPC32 | ||
502 | SIGBUS | ||
503 | #else | ||
504 | 0 | ||
505 | #endif | ||
506 | ); | ||
507 | 483 | ||
508 | /* Must die if the interrupt is not recoverable */ | 484 | /* Must die if the interrupt is not recoverable */ |
509 | if (!(regs->msr & MSR_RI)) | 485 | if (!(regs->msr & MSR_RI)) |
@@ -542,13 +518,9 @@ void RunModeException(struct pt_regs *regs) | |||
542 | } | 518 | } |
543 | #endif | 519 | #endif |
544 | 520 | ||
545 | void __KPROBES single_step_exception(struct pt_regs *regs) | 521 | void __kprobes single_step_exception(struct pt_regs *regs) |
546 | { | 522 | { |
547 | #ifdef CONFIG_PPC32 | ||
548 | regs->msr &= ~(MSR_SE | MSR_BE); /* Turn off 'trace' bits */ | 523 | regs->msr &= ~(MSR_SE | MSR_BE); /* Turn off 'trace' bits */ |
549 | #else | ||
550 | regs->msr &= ~MSR_SE; /* Turn off 'trace' bit */ | ||
551 | #endif | ||
552 | 524 | ||
553 | if (notify_die(DIE_SSTEP, "single_step", regs, 5, | 525 | if (notify_die(DIE_SSTEP, "single_step", regs, 5, |
554 | 5, SIGTRAP) == NOTIFY_STOP) | 526 | 5, SIGTRAP) == NOTIFY_STOP) |
@@ -565,15 +537,12 @@ void __KPROBES single_step_exception(struct pt_regs *regs) | |||
565 | * pretend we got a single-step exception. This was pointed out | 537 | * pretend we got a single-step exception. This was pointed out |
566 | * by Kumar Gala. -- paulus | 538 | * by Kumar Gala. -- paulus |
567 | */ | 539 | */ |
568 | static inline void emulate_single_step(struct pt_regs *regs) | 540 | static void emulate_single_step(struct pt_regs *regs) |
569 | { | 541 | { |
570 | if (single_stepping(regs)) { | 542 | if (single_stepping(regs)) { |
571 | #ifdef CONFIG_PPC32 | ||
572 | clear_single_step(regs); | 543 | clear_single_step(regs); |
573 | _exception(SIGTRAP, regs, TRAP_TRACE, 0); | 544 | _exception(SIGTRAP, regs, TRAP_TRACE, 0); |
574 | #else | ||
575 | single_step_exception(regs); | 545 | single_step_exception(regs); |
576 | #endif | ||
577 | } | 546 | } |
578 | } | 547 | } |
579 | 548 | ||
@@ -582,17 +551,7 @@ static void parse_fpe(struct pt_regs *regs) | |||
582 | int code = 0; | 551 | int code = 0; |
583 | unsigned long fpscr; | 552 | unsigned long fpscr; |
584 | 553 | ||
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); | 554 | flush_fp_to_thread(current); |
595 | #endif | ||
596 | 555 | ||
597 | fpscr = current->thread.fpscr; | 556 | fpscr = current->thread.fpscr; |
598 | 557 | ||
@@ -737,19 +696,8 @@ static int emulate_instruction(struct pt_regs *regs) | |||
737 | } | 696 | } |
738 | 697 | ||
739 | /* Emulating the dcba insn is just a no-op. */ | 698 | /* Emulating the dcba insn is just a no-op. */ |
740 | if ((instword & INST_DCBA_MASK) == INST_DCBA) { | 699 | 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 */ | ||
751 | return 0; | 700 | return 0; |
752 | } | ||
753 | 701 | ||
754 | /* Emulate the mcrxr insn. */ | 702 | /* Emulate the mcrxr insn. */ |
755 | if ((instword & INST_MCRXR_MASK) == INST_MCRXR) { | 703 | if ((instword & INST_MCRXR_MASK) == INST_MCRXR) { |
@@ -817,7 +765,7 @@ static int check_bug_trap(struct pt_regs *regs) | |||
817 | return 0; | 765 | return 0; |
818 | if (bug->line & BUG_WARNING_TRAP) { | 766 | if (bug->line & BUG_WARNING_TRAP) { |
819 | /* this is a WARN_ON rather than BUG/BUG_ON */ | 767 | /* this is a WARN_ON rather than BUG/BUG_ON */ |
820 | #if defined(CONFIG_PPC32) && defined(CONFIG_XMON) | 768 | #ifdef CONFIG_XMON |
821 | xmon_printf(KERN_ERR "Badness in %s at %s:%d\n", | 769 | xmon_printf(KERN_ERR "Badness in %s at %s:%d\n", |
822 | bug->function, bug->file, | 770 | bug->function, bug->file, |
823 | bug->line & ~BUG_WARNING_TRAP); | 771 | bug->line & ~BUG_WARNING_TRAP); |
@@ -843,12 +791,12 @@ static int check_bug_trap(struct pt_regs *regs) | |||
843 | return 0; | 791 | return 0; |
844 | } | 792 | } |
845 | 793 | ||
846 | void __KPROBES program_check_exception(struct pt_regs *regs) | 794 | void __kprobes program_check_exception(struct pt_regs *regs) |
847 | { | 795 | { |
848 | unsigned int reason = get_reason(regs); | 796 | unsigned int reason = get_reason(regs); |
849 | #if defined(CONFIG_PPC32) && defined(CONFIG_MATH_EMULATION) | ||
850 | extern int do_mathemu(struct pt_regs *regs); | 797 | extern int do_mathemu(struct pt_regs *regs); |
851 | 798 | ||
799 | #ifdef CONFIG_MATH_EMULATION | ||
852 | /* (reason & REASON_ILLEGAL) would be the obvious thing here, | 800 | /* (reason & REASON_ILLEGAL) would be the obvious thing here, |
853 | * but there seems to be a hardware bug on the 405GP (RevD) | 801 | * but there seems to be a hardware bug on the 405GP (RevD) |
854 | * that means ESR is sometimes set incorrectly - either to | 802 | * that means ESR is sometimes set incorrectly - either to |
@@ -860,58 +808,45 @@ void __KPROBES program_check_exception(struct pt_regs *regs) | |||
860 | emulate_single_step(regs); | 808 | emulate_single_step(regs); |
861 | return; | 809 | return; |
862 | } | 810 | } |
863 | #endif | 811 | #endif /* CONFIG_MATH_EMULATION */ |
864 | |||
865 | #ifdef CONFIG_PPC64 | ||
866 | if (debugger_fault_handler(regs)) | ||
867 | return; | ||
868 | #endif | ||
869 | 812 | ||
870 | if (reason & REASON_FP) { | 813 | if (reason & REASON_FP) { |
871 | /* IEEE FP exception */ | 814 | /* IEEE FP exception */ |
872 | parse_fpe(regs); | 815 | parse_fpe(regs); |
873 | } else if (reason & REASON_TRAP) { | 816 | return; |
817 | } | ||
818 | if (reason & REASON_TRAP) { | ||
874 | /* trap exception */ | 819 | /* trap exception */ |
875 | #ifdef CONFIG_PPC64 | ||
876 | if (notify_die(DIE_BPT, "breakpoint", regs, 5, 5, SIGTRAP) | 820 | if (notify_die(DIE_BPT, "breakpoint", regs, 5, 5, SIGTRAP) |
877 | == NOTIFY_STOP) | 821 | == NOTIFY_STOP) |
878 | return; | 822 | return; |
879 | #endif | ||
880 | if (debugger_bpt(regs)) | 823 | if (debugger_bpt(regs)) |
881 | return; | 824 | return; |
882 | if (check_bug_trap(regs)) { | 825 | if (check_bug_trap(regs)) { |
883 | regs->nip += 4; | 826 | regs->nip += 4; |
884 | return; | 827 | return; |
885 | } | 828 | } |
886 | _exception(SIGTRAP, regs, TRAP_BRKPT, | 829 | _exception(SIGTRAP, regs, TRAP_BRKPT, regs->nip); |
887 | #ifdef CONFIG_PPC32 | 830 | return; |
888 | 0 | 831 | } |
889 | #else | 832 | |
890 | regs->nip | 833 | /* Try to emulate it if we should. */ |
891 | #endif | 834 | if (reason & (REASON_ILLEGAL | REASON_PRIVILEGED)) { |
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. */ | ||
899 | switch (emulate_instruction(regs)) { | 835 | switch (emulate_instruction(regs)) { |
900 | case 0: | 836 | case 0: |
901 | regs->nip += 4; | 837 | regs->nip += 4; |
902 | emulate_single_step(regs); | 838 | emulate_single_step(regs); |
903 | break; | 839 | return; |
904 | case -EFAULT: | 840 | case -EFAULT: |
905 | _exception(SIGSEGV, regs, SEGV_MAPERR, regs->nip); | 841 | _exception(SIGSEGV, regs, SEGV_MAPERR, regs->nip); |
906 | break; | 842 | return; |
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; | ||
913 | } | 843 | } |
914 | } | 844 | } |
845 | |||
846 | if (reason & REASON_PRIVILEGED) | ||
847 | _exception(SIGILL, regs, ILL_PRVOPC, regs->nip); | ||
848 | else | ||
849 | _exception(SIGILL, regs, ILL_ILLOPC, regs->nip); | ||
915 | } | 850 | } |
916 | 851 | ||
917 | void alignment_exception(struct pt_regs *regs) | 852 | void alignment_exception(struct pt_regs *regs) |
@@ -929,25 +864,13 @@ void alignment_exception(struct pt_regs *regs) | |||
929 | /* Operand address was bad */ | 864 | /* Operand address was bad */ |
930 | if (fixed == -EFAULT) { | 865 | if (fixed == -EFAULT) { |
931 | if (user_mode(regs)) | 866 | if (user_mode(regs)) |
932 | _exception(SIGSEGV, regs, | 867 | _exception(SIGSEGV, regs, SEGV_ACCERR, regs->dar); |
933 | #ifdef CONFIG_PPC32 | ||
934 | SEGV_ACCERR, | ||
935 | #else | ||
936 | SEGV_MAPERR, | ||
937 | #endif | ||
938 | regs->dar); | ||
939 | else | 868 | else |
940 | /* Search exception table */ | 869 | /* Search exception table */ |
941 | bad_page_fault(regs, regs->dar, SIGSEGV); | 870 | bad_page_fault(regs, regs->dar, SIGSEGV); |
942 | return; | 871 | return; |
943 | } | 872 | } |
944 | _exception(SIGBUS, regs, BUS_ADRALN, | 873 | _exception(SIGBUS, regs, BUS_ADRALN, regs->dar); |
945 | #ifdef CONFIG_PPC32 | ||
946 | regs->dar | ||
947 | #else | ||
948 | regs->nip | ||
949 | #endif | ||
950 | ); | ||
951 | } | 874 | } |
952 | 875 | ||
953 | #ifdef CONFIG_PPC32 | 876 | #ifdef CONFIG_PPC32 |
@@ -976,18 +899,16 @@ void trace_syscall(struct pt_regs *regs) | |||
976 | } | 899 | } |
977 | #endif /* CONFIG_PPC32 */ | 900 | #endif /* CONFIG_PPC32 */ |
978 | 901 | ||
979 | #ifdef CONFIG_PPC64 | ||
980 | void kernel_fp_unavailable_exception(struct pt_regs *regs) | 902 | void kernel_fp_unavailable_exception(struct pt_regs *regs) |
981 | { | 903 | { |
982 | printk(KERN_EMERG "Unrecoverable FP Unavailable Exception " | 904 | printk(KERN_EMERG "Unrecoverable FP Unavailable Exception " |
983 | "%lx at %lx\n", regs->trap, regs->nip); | 905 | "%lx at %lx\n", regs->trap, regs->nip); |
984 | die("Unrecoverable FP Unavailable Exception", regs, SIGABRT); | 906 | die("Unrecoverable FP Unavailable Exception", regs, SIGABRT); |
985 | } | 907 | } |
986 | #endif | ||
987 | 908 | ||
988 | void altivec_unavailable_exception(struct pt_regs *regs) | 909 | void altivec_unavailable_exception(struct pt_regs *regs) |
989 | { | 910 | { |
990 | #if !defined(CONFIG_ALTIVEC) || defined(CONFIG_PPC64) | 911 | #if !defined(CONFIG_ALTIVEC) |
991 | if (user_mode(regs)) { | 912 | if (user_mode(regs)) { |
992 | /* A user program has executed an altivec instruction, | 913 | /* A user program has executed an altivec instruction, |
993 | but this kernel doesn't support altivec. */ | 914 | but this kernel doesn't support altivec. */ |
@@ -995,22 +916,9 @@ void altivec_unavailable_exception(struct pt_regs *regs) | |||
995 | return; | 916 | return; |
996 | } | 917 | } |
997 | #endif | 918 | #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 " | 919 | printk(KERN_EMERG "Unrecoverable VMX/Altivec Unavailable Exception " |
1011 | "%lx at %lx\n", regs->trap, regs->nip); | 920 | "%lx at %lx\n", regs->trap, regs->nip); |
1012 | die("Unrecoverable VMX/Altivec Unavailable Exception", regs, SIGABRT); | 921 | die("Unrecoverable VMX/Altivec Unavailable Exception", regs, SIGABRT); |
1013 | #endif | ||
1014 | } | 922 | } |
1015 | 923 | ||
1016 | #ifdef CONFIG_PPC64 | 924 | #ifdef CONFIG_PPC64 |
@@ -1024,8 +932,7 @@ void performance_monitor_exception(struct pt_regs *regs) | |||
1024 | } | 932 | } |
1025 | #endif | 933 | #endif |
1026 | 934 | ||
1027 | 935 | #ifdef CONFIG_8xx | |
1028 | #if defined(CONFIG_PPC32) && defined(CONFIG_8xx) | ||
1029 | void SoftwareEmulation(struct pt_regs *regs) | 936 | void SoftwareEmulation(struct pt_regs *regs) |
1030 | { | 937 | { |
1031 | extern int do_mathemu(struct pt_regs *); | 938 | extern int do_mathemu(struct pt_regs *); |
@@ -1054,7 +961,7 @@ void SoftwareEmulation(struct pt_regs *regs) | |||
1054 | } else | 961 | } else |
1055 | emulate_single_step(regs); | 962 | emulate_single_step(regs); |
1056 | } | 963 | } |
1057 | #endif /* defined(CONFIG_PPC32) && defined(CONFIG_8xx) */ | 964 | #endif /* CONFIG_8xx */ |
1058 | 965 | ||
1059 | #ifdef CONFIG_PPC32 | 966 | #ifdef CONFIG_PPC32 |
1060 | #if defined(CONFIG_40x) || defined(CONFIG_BOOKE) | 967 | #if defined(CONFIG_40x) || defined(CONFIG_BOOKE) |
@@ -1091,29 +998,14 @@ void TAUException(struct pt_regs *regs) | |||
1091 | void altivec_assist_exception(struct pt_regs *regs) | 998 | void altivec_assist_exception(struct pt_regs *regs) |
1092 | { | 999 | { |
1093 | int err; | 1000 | int err; |
1094 | #ifdef CONFIG_PPC64 | ||
1095 | siginfo_t info; | ||
1096 | #endif | ||
1097 | 1001 | ||
1098 | #ifdef CONFIG_PPC32 | ||
1099 | preempt_disable(); | ||
1100 | if (regs->msr & MSR_VEC) | ||
1101 | giveup_altivec(current); | ||
1102 | preempt_enable(); | ||
1103 | #endif | ||
1104 | if (!user_mode(regs)) { | 1002 | if (!user_mode(regs)) { |
1105 | printk(KERN_EMERG "VMX/Altivec assist exception in kernel mode" | 1003 | printk(KERN_EMERG "VMX/Altivec assist exception in kernel mode" |
1106 | " at %lx\n", regs->nip); | 1004 | " at %lx\n", regs->nip); |
1107 | die("Kernel " | 1005 | die("Kernel VMX/Altivec assist exception", regs, SIGILL); |
1108 | #ifdef CONFIG_PPC64 | ||
1109 | "VMX/" | ||
1110 | #endif | ||
1111 | "Altivec assist exception", regs, SIGILL); | ||
1112 | } | 1006 | } |
1113 | 1007 | ||
1114 | #ifdef CONFIG_PPC64 | ||
1115 | flush_altivec_to_thread(current); | 1008 | flush_altivec_to_thread(current); |
1116 | #endif /* CONFIG_PPC64 */ | ||
1117 | 1009 | ||
1118 | err = emulate_altivec(regs); | 1010 | err = emulate_altivec(regs); |
1119 | if (err == 0) { | 1011 | if (err == 0) { |
@@ -1124,15 +1016,7 @@ void altivec_assist_exception(struct pt_regs *regs) | |||
1124 | 1016 | ||
1125 | if (err == -EFAULT) { | 1017 | if (err == -EFAULT) { |
1126 | /* got an error reading the instruction */ | 1018 | /* got an error reading the instruction */ |
1127 | #ifdef CONFIG_PPC32 | ||
1128 | _exception(SIGSEGV, regs, SEGV_ACCERR, regs->nip); | 1019 | _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 | ||
1136 | } else { | 1020 | } else { |
1137 | /* didn't recognize the instruction */ | 1021 | /* didn't recognize the instruction */ |
1138 | /* XXX quick hack for now: set the non-Java bit in the VSCR */ | 1022 | /* XXX quick hack for now: set the non-Java bit in the VSCR */ |
@@ -1144,7 +1028,6 @@ void altivec_assist_exception(struct pt_regs *regs) | |||
1144 | } | 1028 | } |
1145 | #endif /* CONFIG_ALTIVEC */ | 1029 | #endif /* CONFIG_ALTIVEC */ |
1146 | 1030 | ||
1147 | #ifdef CONFIG_PPC32 | ||
1148 | #ifdef CONFIG_FSL_BOOKE | 1031 | #ifdef CONFIG_FSL_BOOKE |
1149 | void CacheLockingException(struct pt_regs *regs, unsigned long address, | 1032 | void CacheLockingException(struct pt_regs *regs, unsigned long address, |
1150 | unsigned long error_code) | 1033 | unsigned long error_code) |
@@ -1194,9 +1077,7 @@ void SPEFloatingPointException(struct pt_regs *regs) | |||
1194 | return; | 1077 | return; |
1195 | } | 1078 | } |
1196 | #endif | 1079 | #endif |
1197 | #endif /* CONFIG_PPC32 */ | ||
1198 | 1080 | ||
1199 | #ifdef CONFIG_PPC64 | ||
1200 | /* | 1081 | /* |
1201 | * We enter here if we get an unrecoverable exception, that is, one | 1082 | * We enter here if we get an unrecoverable exception, that is, one |
1202 | * that happened at a point where the RI (recoverable interrupt) bit | 1083 | * that happened at a point where the RI (recoverable interrupt) bit |
@@ -1209,9 +1090,7 @@ void unrecoverable_exception(struct pt_regs *regs) | |||
1209 | regs->trap, regs->nip); | 1090 | regs->trap, regs->nip); |
1210 | die("Unrecoverable exception", regs, SIGABRT); | 1091 | die("Unrecoverable exception", regs, SIGABRT); |
1211 | } | 1092 | } |
1212 | #endif /* CONFIG_PPC64 */ | ||
1213 | 1093 | ||
1214 | #ifdef CONFIG_PPC32 | ||
1215 | #ifdef CONFIG_BOOKE_WDT | 1094 | #ifdef CONFIG_BOOKE_WDT |
1216 | /* | 1095 | /* |
1217 | * Default handler for a Watchdog exception, | 1096 | * Default handler for a Watchdog exception, |
@@ -1230,9 +1109,7 @@ void WatchdogException(struct pt_regs *regs) | |||
1230 | WatchdogHandler(regs); | 1109 | WatchdogHandler(regs); |
1231 | } | 1110 | } |
1232 | #endif | 1111 | #endif |
1233 | #endif /* CONFIG_PPC32 */ | ||
1234 | 1112 | ||
1235 | #ifdef CONFIG_PPC64 | ||
1236 | /* | 1113 | /* |
1237 | * We enter here if we discover during exception entry that we are | 1114 | * 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. | 1115 | * running in supervisor mode with a userspace value in the stack pointer. |
@@ -1243,7 +1120,6 @@ void kernel_bad_stack(struct pt_regs *regs) | |||
1243 | regs->gpr[1], regs->nip); | 1120 | regs->gpr[1], regs->nip); |
1244 | die("Bad kernel stack pointer", regs, SIGABRT); | 1121 | die("Bad kernel stack pointer", regs, SIGABRT); |
1245 | } | 1122 | } |
1246 | #endif | ||
1247 | 1123 | ||
1248 | void __init trap_init(void) | 1124 | void __init trap_init(void) |
1249 | { | 1125 | { |