diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2009-11-23 20:24:58 -0500 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2009-12-16 20:57:30 -0500 |
commit | 69f3a7de1f1ec935924b1b13f83812f8b30e92ce (patch) | |
tree | a5f8a71b9cb3026a44ae7a1564488de8c3d8d2a9 /arch/mips/kernel/traps.c | |
parent | 4dd92e15b316d1a782772f16074571a70ceb9184 (diff) |
MIPS: Modularize COP2 handling
Away with the daemons of ifdef; get ready for future COP2 users.
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Patchwork: http://patchwork.linux-mips.org/patch/708/
Diffstat (limited to 'arch/mips/kernel/traps.c')
-rw-r--r-- | arch/mips/kernel/traps.c | 60 |
1 files changed, 45 insertions, 15 deletions
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 0a18b4c62afb..9fe21fb65305 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c | |||
@@ -25,10 +25,12 @@ | |||
25 | #include <linux/ptrace.h> | 25 | #include <linux/ptrace.h> |
26 | #include <linux/kgdb.h> | 26 | #include <linux/kgdb.h> |
27 | #include <linux/kdebug.h> | 27 | #include <linux/kdebug.h> |
28 | #include <linux/notifier.h> | ||
28 | 29 | ||
29 | #include <asm/bootinfo.h> | 30 | #include <asm/bootinfo.h> |
30 | #include <asm/branch.h> | 31 | #include <asm/branch.h> |
31 | #include <asm/break.h> | 32 | #include <asm/break.h> |
33 | #include <asm/cop2.h> | ||
32 | #include <asm/cpu.h> | 34 | #include <asm/cpu.h> |
33 | #include <asm/dsp.h> | 35 | #include <asm/dsp.h> |
34 | #include <asm/fpu.h> | 36 | #include <asm/fpu.h> |
@@ -79,10 +81,6 @@ extern asmlinkage void handle_reserved(void); | |||
79 | extern int fpu_emulator_cop1Handler(struct pt_regs *xcp, | 81 | extern int fpu_emulator_cop1Handler(struct pt_regs *xcp, |
80 | struct mips_fpu_struct *ctx, int has_fpu); | 82 | struct mips_fpu_struct *ctx, int has_fpu); |
81 | 83 | ||
82 | #ifdef CONFIG_CPU_CAVIUM_OCTEON | ||
83 | extern asmlinkage void octeon_cop2_restore(struct octeon_cop2_state *task); | ||
84 | #endif | ||
85 | |||
86 | void (*board_be_init)(void); | 84 | void (*board_be_init)(void); |
87 | int (*board_be_handler)(struct pt_regs *regs, int is_fixup); | 85 | int (*board_be_handler)(struct pt_regs *regs, int is_fixup); |
88 | void (*board_nmi_handler_setup)(void); | 86 | void (*board_nmi_handler_setup)(void); |
@@ -857,6 +855,44 @@ static void mt_ase_fp_affinity(void) | |||
857 | #endif /* CONFIG_MIPS_MT_FPAFF */ | 855 | #endif /* CONFIG_MIPS_MT_FPAFF */ |
858 | } | 856 | } |
859 | 857 | ||
858 | /* | ||
859 | * No lock; only written during early bootup by CPU 0. | ||
860 | */ | ||
861 | static RAW_NOTIFIER_HEAD(cu2_chain); | ||
862 | |||
863 | int __ref register_cu2_notifier(struct notifier_block *nb) | ||
864 | { | ||
865 | return raw_notifier_chain_register(&cu2_chain, nb); | ||
866 | } | ||
867 | |||
868 | int cu2_notifier_call_chain(unsigned long val, void *v) | ||
869 | { | ||
870 | return raw_notifier_call_chain(&cu2_chain, val, v); | ||
871 | } | ||
872 | |||
873 | static int default_cu2_call(struct notifier_block *nfb, unsigned long action, | ||
874 | void *data) | ||
875 | { | ||
876 | struct pt_regs *regs = data; | ||
877 | |||
878 | switch (action) { | ||
879 | default: | ||
880 | die_if_kernel("Unhandled kernel unaligned access or invalid " | ||
881 | "instruction", regs); | ||
882 | /* Fall through */ | ||
883 | |||
884 | case CU2_EXCEPTION: | ||
885 | force_sig(SIGILL, current); | ||
886 | } | ||
887 | |||
888 | return NOTIFY_OK; | ||
889 | } | ||
890 | |||
891 | static struct notifier_block default_cu2_notifier = { | ||
892 | .notifier_call = default_cu2_call, | ||
893 | .priority = 0x80000000, /* Run last */ | ||
894 | }; | ||
895 | |||
860 | asmlinkage void do_cpu(struct pt_regs *regs) | 896 | asmlinkage void do_cpu(struct pt_regs *regs) |
861 | { | 897 | { |
862 | unsigned int __user *epc; | 898 | unsigned int __user *epc; |
@@ -920,17 +956,9 @@ asmlinkage void do_cpu(struct pt_regs *regs) | |||
920 | return; | 956 | return; |
921 | 957 | ||
922 | case 2: | 958 | case 2: |
923 | #ifdef CONFIG_CPU_CAVIUM_OCTEON | 959 | raw_notifier_call_chain(&cu2_chain, CU2_EXCEPTION, regs); |
924 | prefetch(¤t->thread.cp2); | 960 | break; |
925 | local_irq_save(flags); | 961 | |
926 | KSTK_STATUS(current) |= ST0_CU2; | ||
927 | status = read_c0_status(); | ||
928 | write_c0_status(status | ST0_CU2); | ||
929 | octeon_cop2_restore(&(current->thread.cp2)); | ||
930 | write_c0_status(status & ~ST0_CU2); | ||
931 | local_irq_restore(flags); | ||
932 | return; | ||
933 | #endif | ||
934 | case 3: | 962 | case 3: |
935 | break; | 963 | break; |
936 | } | 964 | } |
@@ -1760,4 +1788,6 @@ void __init trap_init(void) | |||
1760 | flush_tlb_handlers(); | 1788 | flush_tlb_handlers(); |
1761 | 1789 | ||
1762 | sort_extable(__start___dbe_table, __stop___dbe_table); | 1790 | sort_extable(__start___dbe_table, __stop___dbe_table); |
1791 | |||
1792 | register_cu2_notifier(&default_cu2_notifier); | ||
1763 | } | 1793 | } |