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 | |
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')
-rw-r--r-- | arch/mips/kernel/traps.c | 60 | ||||
-rw-r--r-- | arch/mips/kernel/unaligned.c | 25 |
2 files changed, 63 insertions, 22 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 | } |
diff --git a/arch/mips/kernel/unaligned.c b/arch/mips/kernel/unaligned.c index 67bd626942ab..69b039ca8d83 100644 --- a/arch/mips/kernel/unaligned.c +++ b/arch/mips/kernel/unaligned.c | |||
@@ -81,6 +81,7 @@ | |||
81 | #include <asm/asm.h> | 81 | #include <asm/asm.h> |
82 | #include <asm/branch.h> | 82 | #include <asm/branch.h> |
83 | #include <asm/byteorder.h> | 83 | #include <asm/byteorder.h> |
84 | #include <asm/cop2.h> | ||
84 | #include <asm/inst.h> | 85 | #include <asm/inst.h> |
85 | #include <asm/uaccess.h> | 86 | #include <asm/uaccess.h> |
86 | #include <asm/system.h> | 87 | #include <asm/system.h> |
@@ -451,17 +452,27 @@ static void emulate_load_store_insn(struct pt_regs *regs, | |||
451 | */ | 452 | */ |
452 | goto sigbus; | 453 | goto sigbus; |
453 | 454 | ||
455 | /* | ||
456 | * COP2 is available to implementor for application specific use. | ||
457 | * It's up to applications to register a notifier chain and do | ||
458 | * whatever they have to do, including possible sending of signals. | ||
459 | */ | ||
454 | case lwc2_op: | 460 | case lwc2_op: |
461 | cu2_notifier_call_chain(CU2_LWC2_OP, regs); | ||
462 | break; | ||
463 | |||
455 | case ldc2_op: | 464 | case ldc2_op: |
465 | cu2_notifier_call_chain(CU2_LDC2_OP, regs); | ||
466 | break; | ||
467 | |||
456 | case swc2_op: | 468 | case swc2_op: |
469 | cu2_notifier_call_chain(CU2_SWC2_OP, regs); | ||
470 | break; | ||
471 | |||
457 | case sdc2_op: | 472 | case sdc2_op: |
458 | /* | 473 | cu2_notifier_call_chain(CU2_SDC2_OP, regs); |
459 | * These are the coprocessor 2 load/stores. The current | 474 | break; |
460 | * implementations don't use cp2 and cp2 should always be | 475 | |
461 | * disabled in c0_status. So send SIGILL. | ||
462 | * (No longer true: The Sony Praystation uses cp2 for | ||
463 | * 3D matrix operations. Dunno if that thingy has a MMU ...) | ||
464 | */ | ||
465 | default: | 476 | default: |
466 | /* | 477 | /* |
467 | * Pheeee... We encountered an yet unknown instruction or | 478 | * Pheeee... We encountered an yet unknown instruction or |