Commit 69f3a7de1f1ec935924b1b13f83812f8b30e92ce

Authored by Ralf Baechle
1 parent 4dd92e15b3

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/

Showing 6 changed files with 140 additions and 23 deletions Side-by-side Diff

arch/mips/cavium-octeon/Makefile
... ... @@ -9,7 +9,7 @@
9 9 # Copyright (C) 2005-2009 Cavium Networks
10 10 #
11 11  
12   -obj-y := setup.o serial.o octeon-platform.o octeon-irq.o csrc-octeon.o
  12 +obj-y := cpu.o setup.o serial.o octeon-platform.o octeon-irq.o csrc-octeon.o
13 13 obj-y += dma-octeon.o flash_setup.o
14 14 obj-y += octeon-memcpy.o
15 15  
arch/mips/cavium-octeon/cpu.c
  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 +
  21 +static 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 +
  44 +static struct notifier_block cnmips_cu2_notifier = {
  45 + .notifier_call = cnmips_cu2_call,
  46 +};
  47 +
  48 +static int cnmips_cu2_setup(void)
  49 +{
  50 + return register_cu2_notifier(&cnmips_cu2_notifier);
  51 +}
  52 +early_initcall(cnmips_cu2_setup);
arch/mips/include/asm/cop2.h
  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 +
  12 +enum cu2_ops {
  13 + CU2_EXCEPTION,
  14 + CU2_LWC2_OP,
  15 + CU2_LDC2_OP,
  16 + CU2_SWC2_OP,
  17 + CU2_SDC2_OP,
  18 +};
  19 +
  20 +extern int register_cu2_notifier(struct notifier_block *nb);
  21 +extern int cu2_notifier_call_chain(unsigned long val, void *v);
  22 +
  23 +#endif /* __ASM_COP2_H */
arch/mips/include/asm/octeon/octeon.h
... ... @@ -47,6 +47,7 @@
47 47 extern unsigned long octeon_crypto_enable(struct octeon_cop2_state *state);
48 48 extern void octeon_crypto_disable(struct octeon_cop2_state *state,
49 49 unsigned long flags);
  50 +extern asmlinkage void octeon_cop2_restore(struct octeon_cop2_state *task);
50 51  
51 52 extern void octeon_init_cvmcount(void);
52 53  
arch/mips/kernel/traps.c
... ... @@ -25,10 +25,12 @@
25 25 #include <linux/ptrace.h>
26 26 #include <linux/kgdb.h>
27 27 #include <linux/kdebug.h>
  28 +#include <linux/notifier.h>
28 29  
29 30 #include <asm/bootinfo.h>
30 31 #include <asm/branch.h>
31 32 #include <asm/break.h>
  33 +#include <asm/cop2.h>
32 34 #include <asm/cpu.h>
33 35 #include <asm/dsp.h>
34 36 #include <asm/fpu.h>
... ... @@ -79,10 +81,6 @@
79 81 extern int fpu_emulator_cop1Handler(struct pt_regs *xcp,
80 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 84 void (*board_be_init)(void);
87 85 int (*board_be_handler)(struct pt_regs *regs, int is_fixup);
88 86 void (*board_nmi_handler_setup)(void);
... ... @@ -857,6 +855,44 @@
857 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 896 asmlinkage void do_cpu(struct pt_regs *regs)
861 897 {
862 898 unsigned int __user *epc;
... ... @@ -920,17 +956,9 @@
920 956 return;
921 957  
922 958 case 2:
923   -#ifdef CONFIG_CPU_CAVIUM_OCTEON
924   - prefetch(&current->thread.cp2);
925   - local_irq_save(flags);
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
  959 + raw_notifier_call_chain(&cu2_chain, CU2_EXCEPTION, regs);
  960 + break;
  961 +
934 962 case 3:
935 963 break;
936 964 }
... ... @@ -1760,5 +1788,7 @@
1760 1788 flush_tlb_handlers();
1761 1789  
1762 1790 sort_extable(__start___dbe_table, __stop___dbe_table);
  1791 +
  1792 + register_cu2_notifier(&default_cu2_notifier);
1763 1793 }
arch/mips/kernel/unaligned.c
... ... @@ -81,6 +81,7 @@
81 81 #include <asm/asm.h>
82 82 #include <asm/branch.h>
83 83 #include <asm/byteorder.h>
  84 +#include <asm/cop2.h>
84 85 #include <asm/inst.h>
85 86 #include <asm/uaccess.h>
86 87 #include <asm/system.h>
87 88  
88 89  
89 90  
90 91  
... ... @@ -451,17 +452,27 @@
451 452 */
452 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 460 case lwc2_op:
  461 + cu2_notifier_call_chain(CU2_LWC2_OP, regs);
  462 + break;
  463 +
455 464 case ldc2_op:
  465 + cu2_notifier_call_chain(CU2_LDC2_OP, regs);
  466 + break;
  467 +
456 468 case swc2_op:
  469 + cu2_notifier_call_chain(CU2_SWC2_OP, regs);
  470 + break;
  471 +
457 472 case sdc2_op:
458   - /*
459   - * These are the coprocessor 2 load/stores. The current
460   - * implementations don't use cp2 and cp2 should always be
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   - */
  473 + cu2_notifier_call_chain(CU2_SDC2_OP, regs);
  474 + break;
  475 +
465 476 default:
466 477 /*
467 478 * Pheeee... We encountered an yet unknown instruction or