aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/mips/cavium-octeon/Makefile2
-rw-r--r--arch/mips/cavium-octeon/cpu.c52
-rw-r--r--arch/mips/include/asm/cop2.h23
-rw-r--r--arch/mips/include/asm/octeon/octeon.h1
-rw-r--r--arch/mips/kernel/traps.c60
-rw-r--r--arch/mips/kernel/unaligned.c25
6 files changed, 140 insertions, 23 deletions
diff --git a/arch/mips/cavium-octeon/Makefile b/arch/mips/cavium-octeon/Makefile
index 139436280520..3e9876317e61 100644
--- a/arch/mips/cavium-octeon/Makefile
+++ b/arch/mips/cavium-octeon/Makefile
@@ -9,7 +9,7 @@
9# Copyright (C) 2005-2009 Cavium Networks 9# Copyright (C) 2005-2009 Cavium Networks
10# 10#
11 11
12obj-y := setup.o serial.o octeon-platform.o octeon-irq.o csrc-octeon.o 12obj-y := cpu.o setup.o serial.o octeon-platform.o octeon-irq.o csrc-octeon.o
13obj-y += dma-octeon.o flash_setup.o 13obj-y += dma-octeon.o flash_setup.o
14obj-y += octeon-memcpy.o 14obj-y += octeon-memcpy.o
15 15
diff --git a/arch/mips/cavium-octeon/cpu.c b/arch/mips/cavium-octeon/cpu.c
new file mode 100644
index 000000000000..b6df5387e855
--- /dev/null
+++ b/arch/mips/cavium-octeon/cpu.c
@@ -0,0 +1,52 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2009 Wind River Systems,
7 * written by Ralf Baechle <ralf@linux-mips.org>
8 */
9#include <linux/init.h>
10#include <linux/irqflags.h>
11#include <linux/notifier.h>
12#include <linux/prefetch.h>
13#include <linux/sched.h>
14
15#include <asm/cop2.h>
16#include <asm/current.h>
17#include <asm/mipsregs.h>
18#include <asm/page.h>
19#include <asm/octeon/octeon.h>
20
21static int cnmips_cu2_call(struct notifier_block *nfb, unsigned long action,
22 void *data)
23{
24 unsigned long flags;
25 unsigned int status;
26
27 switch (action) {
28 case CU2_EXCEPTION:
29 prefetch(&current->thread.cp2);
30 local_irq_save(flags);
31 KSTK_STATUS(current) |= ST0_CU2;
32 status = read_c0_status();
33 write_c0_status(status | ST0_CU2);
34 octeon_cop2_restore(&(current->thread.cp2));
35 write_c0_status(status & ~ST0_CU2);
36 local_irq_restore(flags);
37
38 return NOTIFY_BAD; /* Don't call default notifier */
39 }
40
41 return NOTIFY_OK; /* Let default notifier send signals */
42}
43
44static struct notifier_block cnmips_cu2_notifier = {
45 .notifier_call = cnmips_cu2_call,
46};
47
48static int cnmips_cu2_setup(void)
49{
50 return register_cu2_notifier(&cnmips_cu2_notifier);
51}
52early_initcall(cnmips_cu2_setup);
diff --git a/arch/mips/include/asm/cop2.h b/arch/mips/include/asm/cop2.h
new file mode 100644
index 000000000000..6b04c98b7fad
--- /dev/null
+++ b/arch/mips/include/asm/cop2.h
@@ -0,0 +1,23 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2009 Wind River Systems,
7 * written by Ralf Baechle <ralf@linux-mips.org>
8 */
9#ifndef __ASM_COP2_H
10#define __ASM_COP2_H
11
12enum cu2_ops {
13 CU2_EXCEPTION,
14 CU2_LWC2_OP,
15 CU2_LDC2_OP,
16 CU2_SWC2_OP,
17 CU2_SDC2_OP,
18};
19
20extern int register_cu2_notifier(struct notifier_block *nb);
21extern int cu2_notifier_call_chain(unsigned long val, void *v);
22
23#endif /* __ASM_COP2_H */
diff --git a/arch/mips/include/asm/octeon/octeon.h b/arch/mips/include/asm/octeon/octeon.h
index cac9b1a206fc..4d0a8c61fc3e 100644
--- a/arch/mips/include/asm/octeon/octeon.h
+++ b/arch/mips/include/asm/octeon/octeon.h
@@ -47,6 +47,7 @@ struct octeon_cop2_state;
47extern unsigned long octeon_crypto_enable(struct octeon_cop2_state *state); 47extern unsigned long octeon_crypto_enable(struct octeon_cop2_state *state);
48extern void octeon_crypto_disable(struct octeon_cop2_state *state, 48extern void octeon_crypto_disable(struct octeon_cop2_state *state,
49 unsigned long flags); 49 unsigned long flags);
50extern asmlinkage void octeon_cop2_restore(struct octeon_cop2_state *task);
50 51
51extern void octeon_init_cvmcount(void); 52extern void octeon_init_cvmcount(void);
52 53
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);
79extern int fpu_emulator_cop1Handler(struct pt_regs *xcp, 81extern 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
83extern asmlinkage void octeon_cop2_restore(struct octeon_cop2_state *task);
84#endif
85
86void (*board_be_init)(void); 84void (*board_be_init)(void);
87int (*board_be_handler)(struct pt_regs *regs, int is_fixup); 85int (*board_be_handler)(struct pt_regs *regs, int is_fixup);
88void (*board_nmi_handler_setup)(void); 86void (*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 */
861static RAW_NOTIFIER_HEAD(cu2_chain);
862
863int __ref register_cu2_notifier(struct notifier_block *nb)
864{
865 return raw_notifier_chain_register(&cu2_chain, nb);
866}
867
868int cu2_notifier_call_chain(unsigned long val, void *v)
869{
870 return raw_notifier_call_chain(&cu2_chain, val, v);
871}
872
873static 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
891static struct notifier_block default_cu2_notifier = {
892 .notifier_call = default_cu2_call,
893 .priority = 0x80000000, /* Run last */
894};
895
860asmlinkage void do_cpu(struct pt_regs *regs) 896asmlinkage 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(&current->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